您希望$elemMatch
運營商選擇具有既條件和01元操作投影:
Models.Message.find(
{
"to": {
"$elemMatch": {
"username": "user2",
"section.archive": true
}
}
},
{ "created": 1, "message": 1, "to.$": 1 }
).sort([['to.updated','descending']]).exec(function (err, messages) {
});
請注意,這僅在投影「第一」元件匹配的作品。此外,您還希望對匹配的數組元素的值進行「排序」,並且您無法通過.find()
和.sort()
修改器來完成此操作。
如果你想在數組中有多個匹配,那麼你需要使用聚合方法。這確實更爲複雜的「過濾」和「投影」比是可能的,否則:
Models.Message.aggregate([
// Match documents
{ "$match": {
"to": {
"$elemMatch": {
"username": "user2",
"section.archive": true
}
}
}},
// Unwind to de-normalize
{ "$unwind": "$to" },
// Match the array elements
{ "$match": {
"to.username": "user2",
"to.section.archive": true
}},
// Group back to the original document
{ "$group": {
"_id": "$_id",
"created": { "$first": "$created" },
"message": { "$first": "$message" },
"to": { "$push": "$to" }
}}
// Sort the results "correctly"
{ "$sort": { "to.updated": -1 } }
],function(err,messages) {
});
或者,可以避免使用$unwind
和$group
通過與MongoDB中2.6或更高的操作者$map
應用一些邏輯。只是看,作爲$setDifference
應用到所產生的「過濾」數組你的數組內容是「真正的」獨特性:
Models.Message.aggregate([
{ "$match": {
"to": {
"$elemMatch": {
"username": "user2",
"section.archive": true
}
}
}},
{ "$project": {
"created": 1,
"message": 1,
"_id": 1,
"to": {
"$setDifference": [
{
"$map": {
"input": "$to",
"as": "el",
"in": {
"$cond": [
{
"$and": [
{ "$eq": [ "$$el.username", "user2" ] },
"$$el.section.archive"
]
},
"$$el",
false
]
}
}
},
[false]
]
}
}},
{ "$sort": { "to.updated": -1 } }
],function(err,messages) {
});
甚至使用$redact
:
Models.Messages.aggregate([
{ "$match": {
"to": {
"$elemMatch": {
"username": "user2",
"section.archive": true
}
}
}},
{ "$redact": {
"$cond": {
"if": {
"$and": [
{ "$eq": [
{ "$ifNull": [ "$username", "user2" ] },
"user2"
] },
{ "$ifNull": [ "$section.archive", true ] }
]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$sort": { "to.updated": -1 } }
],function(err,messages) {
});
但要小心爲$redact
工作在所有文檔的級別,所以你的結果可能是意想不到的。
可能你的「to」數組實際上只有單個條目可以匹配,所以通常標準投影應該沒問題。但這裏是你如何在MongoDB的數組元素中進行「多重」匹配。
這真的很棒..很多很多謝謝 – StackThis
你會推薦什麼方法來返回每個匹配文檔的全部內容?經過測試,我使用$ unwind + $ group聚合,其中所有其他字段都是$首先累積的。如何在最佳實踐中排名? – StackThis
@StackThis剛剛注意到,當然你想對那些匹配元素的「更新」日期進行「排序」。所以當然你需要一個聚合方法來做到這一點。你在做什麼很好,其他方法是新的介紹。如果您正在查找多個數組匹配項,您可能還需要在分組中輸入「$ min」或「$ max」日期值進行排序。甚至可能在分組之前對這些匹配進行排序。 –