可以使用聚合框架由給定組ID和成員陣列狀態字段來篩選組收集的文件。這將是您的初始管道階段,這是運營商驅動的$match
。
下一個流水線步驟應該是$filter
運算符,它根據給定的條件選擇成員數組的子集。這是必要的,因爲前一個流水線只能在文檔級進行過濾,而不能在數組/字段級進行過濾。
一旦你得到了過濾的數組,你可以應用功能作爲「填充」你的成員名單的手段。然而,由於localField
是一個數組,要匹配它裏面的元素反對foreignField
這是一個單一的元素,你需要$unwind
數組作爲聚合管線的一個階段應用$lookup
運營商之前。
下面的例子演示瞭如何應用在你的情況下,所有上述步驟:
Group.aggregate([
{
"$match": {
"_id": groupId,
"members.status": 1
}
},
{
"$filter": {
"input": "$members",
"as": "member",
"cond": { "$eq": ["$$member.status", 1] }
}
}
{ "$unwind": "$members" },
{
"$lookup": {
"from": "users"
"localField": "members.user_id",
"foreignField": "_id",
"as": "member"
}
}
]).exec(function(err, results) {
if (err) throw err;
console.log(results);
});
結果將包含具有兩個組和用戶屬性的文件清單。
如果您的MongoDB的版本不支持在3.2版本中引入的$filter
和$lookup
運營商。X和更新,然後考慮使用$setDifference
和$map
操作者的組合來過濾在$project
管線數組元素。
的$map
操作在本質上創建保持值作爲一個子表達式到數組的每個元素的邏輯評價的結果的新的數組字段。然後,運算符返回一個集合,其中的元素出現在第一個集合中,但不出現在第二個集合中;即執行第二組相對於第一組的相對補償。在這種情況下,它將通過status
屬性返回包含與父文檔無關的元素的最終成員數組。
的$project
流水線工序後,執行總運行和自恢復的文件都是普通的JavaScript對象,而不是Mongoose Documents(可以返回文檔的任何形狀),你需要轉換的結果,Mongoose Documents這樣就可以使用用結果在現場填充函數。
下面的例子演示了上述解決辦法:
Group.aggregate([
{
"$match": {
"_id": groupId,
"members.status": 1
}
},
{
"$project": {
"type": 1, "name": 1,
"members": {
"$setDifference": [
{
"$map": {
"input": "$members",
"as": "member",
"in": {
"$cond": [
{ "$eq": [ "$$member.status", 1 ] },
"$$member",
false
]
}
}
},
[false]
]
}
}
}
]).exec(function(err, result) {
if (err) throw err;
var docs = result.map(function(doc) { return new Group(doc) });
Group.populate(docs, { "path": "members" }, function(err, results) {
if (err) throw err;
console.log(JSON.stringify(results, undefined, 4));
res.json(results);
});
});
您的意思是對於給定的,而不是_group_對象_post_對象? – chridam
除了給出Schema定義之外,分享少量示例文檔和預期輸出將會很好,這樣很容易理解您要完成的任務。 – superUser
@chridam'組'對象。編輯了這個問題。 –