英文:
How can I modify the resulting query in Mongoose without affecting the actual document?
问题
状态(截至2020年5月6日): 已解决,请查看下面找到的答案。
我希望尽管我们正经历全球危机,一切都好。我目前正在进行一个学校网站项目,需要渲染我分配的特定功能。我正在使用Mongoose与Express,并使用Handlebars进行模板化。请查看下面附上的模型架构和解释。
collegeModel - 集合 A
var collegeSchema = new Schema({
shortName: {type: String}, // 我打算同步查询它在集合 B 中的出现
longName: {type: String},
logo: {type: String},
contactUs: {
telNum: {type: String},
faxNum: {type: String},
email: {type: String}
},
aboutUs: {type: Array},
visionMission: {type: String},
coreValues: {type: String},
goals: {type: String},
founderBio: {type: String},
philosophy: {type: String},
icon: {type: String}
});
professorModel - 集合 B
var professorSchema = new Schema({
profNumber: {type: Int32},
college: {type: String}, // 与 shortName 进行比较的值
gender: {type: String},
profName: {type: String},
profCourse: {type: String}
});
伪代码 - 要实现的期望逻辑
app.get('/testCount', function(req, res) {
collegeModel.find({}).lean().exec(function(err, collegeRes) {
var collegeObject = [];
collegeRes.forEach(function(document) {
professorModel.countDocuments({college: document.shortName}, function(err2, professorCount) {
document.count = professorCount;
collegeObject.push(document); // 进行 console.log(collegeObject) 会返回空对象 []
});
});
});
});
我不知道我做错了什么,我知道 document.count 存在,因为每次我执行 console.log(document.count) 时都会返回一个值,但当它被推送时变成了 []。希望你能帮助我实现我的目标。谢谢!
英文:
Status (as of 5/6/2020): Solved, see the identified answer below.
I hope all is well despite the global crisis we are experiencing right now. I am currently doing a school web project and need to render a specific feature assigned to me. I am using Mongoose with Express, and Handlebars for templating. Please see the attached model schema and explanation below.
collegeModel - Collection A
var collegeSchema = new Schema({
shortName: {type: String}, //value that I intend to synchronously query its occurrence with Collection B
longName: {type: String},
logo: {type: String},
contactUs:{
telNum: {type: String},
faxNum: {type: String},
email: {type: String}
},
aboutUs: {type: Array},
visionMission: {type: String},
coreValues: {type: String},
goals: {type: String},
founderBio: {type: String},
philosophy: {type: String},
icon: {type: String}
});
professorModel - Collection B
var professorSchema = new Schema({
profNumber: {type: Int32},
college: {type: String}, //value to be compared with shortName
gender: {type: String},
profName: {type: String},
profCourse: {type: String}
});
Pseudocode - Desired logic to be achieved
app.get('/testCount', function(req,res) {
collegeModel.find({}).lean().exec(function(err,collegeRes){
var collegeObject = [];
collegeRes.forEach(function(document){
professorModel.countDocuments({college:document.shortName}, function(err2,professorCount){
document.count = professorCount;
collegeObject.push(document); //doing a console.log(collegeObject) would return empty objects [].
});
});
});
});
I don't know what I'm doing wrong and I know document.count exists since it returns a value everytime I do console.log(document.count) but when it's pushed it becomes []. Hope you can help me achieve my goal. Thanks!
答案1
得分: 1
你的查询是异步解析的,你必须找到一种方法来等待它们全部完成,以确保你拥有所需的所有数据。
解决这个问题的一种方式是使用 async/await
(Node.js >= 7.6.0)
app.get('/testCount', async function(req, res) { // 注意 async 关键字
const collegeRes = await collegeModel.find({}).lean().exec() // .exec() 返回一个 Promise,所以你可以用 `await` 等待它。
const resultPromises = collegeRes.map(async college => { // 箭头函数在这个上下文中相当于普通函数
const professorCount = await professorModel.countDocuments({ college: college.shortName })
college.count = professorCount
return college
})
const collegeObject = await Promise.all(resultPromises)
console.log(collegeObject)
})
稍微更可读的方式是使用 Promise.map
来自 bluebird
或者你也可以使用其他的 Promise 实用库。
const collegeObject = await Promise.map(collegeRes, college => {
const professorCount = await professorModel.countDocuments({ college: college.shortName })
college.count = professorCount
return college
})
console.log(collegeObject)
英文:
Your queries resolve asynchronously, you have to find a way to wait for all of them to complete to make sure you have all the data you need.
One way to solve this is using async/await
(Node.js >= 7.6.0)
app.get('/testCount', async function(req, res) { // note the async keyword
const collegeRes = await collegeModel.find({}).lean().exec() // .exec() returns a Promise, so you can `await` it.
const resultPromises = collegeRes.map(async college => { // arrow function is equivalent to function in this context
const professorCount = await professorModel.countDocuments({ college: college.shortName })
college.count = professorCount
return college
})
const collegeObject = await Promise.all(resultPromises)
console.log(collegeObject)
})
A bit more readable would be using Promise.map
from bluebird
or you can also use other promise utility library
const collegeObject = await Promise.map(collegeRes, college => {
const professorCount = await professorModel.countDocuments({ college: college.shortName })
college.count = professorCount
return college
})
console.log(collegeObject)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论