Node.js NodeJS批处理Mongo操作,等待回调
我正在尝试对mongo数据库执行批处理操作。其想法是迭代每个用户,然后找到学习同一课程或上同一所大学的其他用户,并存储有关这些匹配的信息 所有内容都包含在如下循环中:Node.js NodeJS批处理Mongo操作,等待回调,node.js,mongodb,Node.js,Mongodb,我正在尝试对mongo数据库执行批处理操作。其想法是迭代每个用户,然后找到学习同一课程或上同一所大学的其他用户,并存储有关这些匹配的信息 所有内容都包含在如下循环中: User.find({}, function(err, doc){ doc.forEach(function(candidate){ //other find operations in here ... } } 其中“User”是在站点上注册的用户的集合。我遇到的问题是forEa
User.find({}, function(err, doc){
doc.forEach(function(candidate){
//other find operations in here
...
}
}
其中“User”是在站点上注册的用户的集合。我遇到的问题是forEach循环正在为每个用户分派所有回调,而我希望在进入下一个文档之前,等待forEach循环中的所有回调完成
我尝试过使用异步,但我似乎无法理解这一点
如何一次处理一个用户?您可以使用
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
}
});
请参阅:将函数推入数组并稍后调用它们的一种方法是使用Observable,这对于循环异步操作非常有用
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]() }
无需为每个用户分派所有回调即可轻松完成此任务,在聚合操作中使用管道,在用户集合上创建
“自连接”
,使用管道过滤文档,仅返回与其他用户共享同一课程的用户
例如,如果有一个名为课程
的字段,下面将返回学习同一课程的所有用户:
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"
}
]
}
非常感谢。混合使用async.eachSeries()和async.serial()实现了这一点。