Эта задача может быть легко сделан без необходимости диспетчерского всех обратных вызовов для каждого пользователя, используйте $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);
Тестирование в Монго оболочки
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(), сделал трюк. –