如何在不影响实际文档的情况下修改Mongoose中的查询结果?

huangapple go评论160阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2020年5月4日 03:08:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/61580163.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定