我试图在mongo数据库上进行批量操作。我们的想法是迭代每个用户,然后找到正在学习相同课程的其他用户,或者去同一所大学,并存储有关这些匹配的信息。
所有内容都包含在这样的循环中:
User.find({}, function(err, doc){
doc.forEach(function(candidate){
//other find operations in here
...
}
}
用户'是在网站上注册的用户的集合。我遇到的问题是forEach循环正在为每个用户调度所有回调,而我想在转移到下一个文档之前等待forEach循环中的所有回调完成。
我尝试过使用异步,但我似乎无法解决这个问题。
我如何一次处理一个用户?
答案 0 :(得分: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
}
});
答案 1 :(得分:0)
将函数推入数组并稍后以其他方式调用它们的一种方法是使用对于循环异步操作非常有用的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]() }
答案 2 :(得分:0)
此任务可以轻松完成而无需为每个用户分派所有回调,在您创建"self-join"
的聚合操作中使用 $lookup
管道用户集合,使用 $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"
}
]
}