NodeJS Batch Mongo 操作,等待回调
Posted
技术标签:
【中文标题】NodeJS Batch Mongo 操作,等待回调【英文标题】:NodeJS Batch Mongo operation, wait for callbacks 【发布时间】:2017-06-20 21:39:34 【问题描述】:我正在尝试对 mongo 数据库执行批处理操作。想法是遍历每个用户,然后找到正在学习相同课程或上同一所大学的其他用户,并存储有关这些匹配项的信息。
一切都包含在这样的循环中:
User.find(, function(err, doc)
doc.forEach(function(candidate)
//other find operations in here
...
“用户”是在网站上注册的用户集合。我遇到的问题是 forEach 循环正在为每个用户分派所有回调,而我想等待 forEach 循环中的所有回调完成,然后再转到下一个文档。
我尝试过使用异步,但我似乎无法弄清楚这一点。
如何一次处理每个用户?
【问题讨论】:
【参考方案1】:您可以为此使用async
,例如async.eachSeries
:
async.eachSeries(doc, function (candidate, cb)
//other find operations in here
...
// and you call cb() once they're done (important!)
// or call cb('some error') if it failed
, function (err)
if (err)
// this means that some cb() above was called with error
else
// here all candidates are processed successfully
);
见:https://caolan.github.io/async/docs.html#eachSeries
【讨论】:
谢谢!混合使用 async.eachSeries() 和 async.serial() 就可以了。【参考方案2】:将函数推入数组并稍后调用它们的一种方法是使用可观察对象,这对于循环异步操作非常有用。
var candidatesOps = [];
User.find(, function(err, doc)
doc.forEach(function(candidate)
var func = function(candidate)
//other find operations in here
;
candidatesOps.push(func);
...
if(candidatesOps) //call them candidatesOps[0]()
【讨论】:
【参考方案3】:此任务可以轻松完成,无需为每个用户分派所有回调,在聚合操作中使用 $lookup
管道,您可以在用户集合上创建 "self-join"
,使用 $match
管道过滤文档以仅返回与其他用户共享同一课程的用户。
例如,假设有一个名为course
的字段,以下将返回正在学习同一课程的所有用户:
User.aggregate([
"$match": "course": "$exists": true ,
"$lookup":
"from": "users",
"localField": "course",
"foreignField": "course",
"as": "users_courses"
,
"$match": "users_courses.1": "$exists": true
], callback);
在 mongo shell 中测试
db.test.insert([
"name": "a", "course": "maths" ,
"name": "b", "course": "english" ,
"name": "c", "course": "maths" ,
"name": "d", "course": "science" ,
"name": "e", "course": "maths" ,
"name": "f", "course": "history" ,
"name": "g", "course": "history"
])
运行聚合操作
db.test.aggregate([
"$match": "course": "$exists": true ,
"$lookup":
"from": "users",
"localField": "course",
"foreignField": "course",
"as": "users_courses"
,
"$match": "users_courses.1": "$exists": true
])
样本输出
/* 1 */
"_id" : ObjectId("58948c0dd04f1bbdbf331ea7"),
"name" : "a",
"course" : "maths",
"users_courses" : [
"_id" : ObjectId("58948c0dd04f1bbdbf331ea7"),
"name" : "a",
"course" : "maths"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331ea9"),
"name" : "c",
"course" : "maths"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331eab"),
"name" : "e",
"course" : "maths"
]
/* 2 */
"_id" : ObjectId("58948c0dd04f1bbdbf331ea9"),
"name" : "c",
"course" : "maths",
"users_courses" : [
"_id" : ObjectId("58948c0dd04f1bbdbf331ea7"),
"name" : "a",
"course" : "maths"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331ea9"),
"name" : "c",
"course" : "maths"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331eab"),
"name" : "e",
"course" : "maths"
]
/* 3 */
"_id" : ObjectId("58948c0dd04f1bbdbf331eab"),
"name" : "e",
"course" : "maths",
"users_courses" : [
"_id" : ObjectId("58948c0dd04f1bbdbf331ea7"),
"name" : "a",
"course" : "maths"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331ea9"),
"name" : "c",
"course" : "maths"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331eab"),
"name" : "e",
"course" : "maths"
]
/* 4 */
"_id" : ObjectId("58948c0dd04f1bbdbf331eac"),
"name" : "f",
"course" : "history",
"users_courses" : [
"_id" : ObjectId("58948c0dd04f1bbdbf331eac"),
"name" : "f",
"course" : "history"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331ead"),
"name" : "g",
"course" : "history"
]
/* 5 */
"_id" : ObjectId("58948c0dd04f1bbdbf331ead"),
"name" : "g",
"course" : "history",
"users_courses" : [
"_id" : ObjectId("58948c0dd04f1bbdbf331eac"),
"name" : "f",
"course" : "history"
,
"_id" : ObjectId("58948c0dd04f1bbdbf331ead"),
"name" : "g",
"course" : "history"
]
【讨论】:
以上是关于NodeJS Batch Mongo 操作,等待回调的主要内容,如果未能解决你的问题,请参考以下文章