Не на 100% ясно в вашем вопросе, но вы, похоже, ищете простые $lookup
по тем же данным со сравнением итоговых пользователей.Вы, вероятно, действительно хотите этого только для одного пользователя за раз, поэтому $match
для этого пользователя, как правило, является здесь «опцией».
В ней не так много, кроместандартный $lookup
результат с последующим использованием $map
для сравнения с «родителем» _id
и добавления нового свойства в массив.
В идеале с MongoDB 3.6 вы можете применять $mergeObjects
:
Person.aggregate([
// { "$match": { "_id": 3 } },
{ "$lookup": {
"from": Person.collection.name,
"localField": "following",
"foreignField": "_id",
"as": "following"
}},
{ "$addFields": {
"following": {
"$map": {
"input": "$following",
"in": {
"$mergeObjects": [
"$$this",
{ "is_following": {
"$in": [ "$_id", "$$this.following" ]
}}
]
}
}
}
}}
])
А для более ранних версий вам просто нужно назвать поля "явно" в пределах $map
, которые вы хотите вернуть:
Person.aggregate([
// { "$match": { "_id": 3 } },
{ "$lookup": {
"from": Person.collection.name,
"localField": "following",
"foreignField": "_id",
"as": "following"
}},
{ "$project": {
"_id": 1,
"name": 1,
"following": {
"$map": {
"input": "$following",
"in": {
"_id": "$$this._id",
"name": "$$this.name",
"following": "$$this.following",
"is_following": { "$setIsSubset": [["$_id"], "$$this.following"] }
}
}
}
}}
])
Основы таковы, что каждый элемент проверяется $map
. Вы можете сравнить их собственный массив "followers"
и текущийпользовательское _id
значение.Для сравнения можно использовать $in
или $setIsSubset
.Один сравнивает значение с массивом, а другие - с двумя «массивами».
Альтернативно, когда у вас даже нет доступа к $lookup
, вы можете .populate()
, а затем просто-map "содержимое массива во многом таким же образом:
let people = await Person.find().lean().populate('following');
people = people.map(p => ({
...p,
following: p.following.map(f => ({
...f,
is_following: f.following.some(e => e._id.equals(p._id))
}))
}));
Использование Array.some()
с методом ObjectID.equals()
для сравнения.Обратите внимание, что Array.includes()
не может применяться здесь без переназначения значений ObjectId
в строку из-за того, как работает «сравнение объектов».
Все формы здесь приводят к одному и тому же результату:
{
"_id" : 1,
"name" : "David",
"following" : [
{
"_id" : 2,
"name" : "Sam",
"following" : [
1
],
"is_following" : true
},
{
"_id" : 3,
"name" : "Lucy",
"following" : [
1,
2
],
"is_following" : true
}
]
}
{
"_id" : 2,
"name" : "Sam",
"following" : [
{
"_id" : 1,
"name" : "David",
"following" : [
2,
3
],
"is_following" : true
}
]
}
{
"_id" : 3,
"name" : "Lucy",
"following" : [
{
"_id" : 1,
"name" : "David",
"following" : [
2,
3
],
"is_following" : true
},
{
"_id" : 2,
"name" : "Sam",
"following" : [
1
],
"is_following" : false
}
]
}