你真的在這裏問的是如何讓MongoDB返回一些與你存儲它的形式完全不同的東西。標準查詢操作確實允許使用「限制」形式的"projection",但即使在該鏈接中共享的頁面上的標題暗示,這實際上只是關於根據文檔中的內容「限制」在結果中顯示的字段已經。
因此,任何形式的「變更」都需要某種形式的聚合,聚合和mapReduce操作都允許將文檔結果「重新塑形」爲與輸入不同的形式。也許人們對聚合框架尤其缺乏的主要是關於「聚合」的全部,實際上「重塑」概念是其實現的核心。
所以爲了得到結果,你怎麼想,你可以採取這樣的做法,應該在大多數情況下是合適的:
db.collection.aggregate([
{ "$unwind": "$students" },
{ "$unwind": "$studentDept" },
{ "$group": {
"_id": "$students.name",
"tfee": { "$first": "$students.fee" },
"tdept": {
"$min": {
"$cond": [
{ "$eq": [
"$students.name",
"$studentDept.name"
]},
"$studentDept.dept",
false
]
}
}
}},
{ "$match": { "tdept": { "$ne": false } } },
{ "$sort": { "_id": 1 } },
{ "$project": {
"_id": 0,
"name": "$_id",
"fee": "$tfee",
"dept": "$tdept"
}}
])
或者交替只是「過濾掉」的情況下,這兩個「名稱「字段不匹配,然後就項目與你想要的字段的內容,如果穿越文檔之間的內容是不是對你很重要:
db.collection.aggregate([
{ "$unwind": "$students" },
{ "$unwind": "$studentDept" },
{ "$project": {
"_id": 0,
"name": "$students.name",
"fee": "$students.fee",
"dept": "$studentDept.dept",
"same": { "$eq": [ "$students.name", "$studentDept.name" ] }
}},
{ "$match": { "same": true } },
{ "$project": {
"name": 1,
"fee": 1,
"dept": 1
}}
])
從MongoDB的2.6及以上的,你甚至可以做同樣的事情」內聯「到兩個數組之間的文檔。你仍然想雖然重塑你的最終輸出數組的內容,但可以做的快一點:
db.collection.aggregate([
// Compares entries in each array within the document
{ "$project": {
"students": {
"$map": {
"input": "$students",
"as": "stu",
"in": {
"$setDifference": [
{ "$map": {
"input": "$studentDept",
"as": "dept",
"in": {
"$cond": [
{ "$eq": [ "$$stu.name", "$$dept.name" ] },
{
"name": "$$stu.name",
"fee": "$$stu.fee",
"dept": "$$dept.dept"
},
false
]
}
}},
[false]
]
}
}
}
}},
// Students is now an array of arrays. So unwind it twice
{ "$unwind": "$students" },
{ "$unwind": "$students" },
// Rename the fields and exclude
{ "$project": {
"_id": 0,
"name": "$students.name",
"fee": "$students.fee",
"dept": "$students.dept"
}},
])
那麼,你想基本上是「改變」輸出的結構,那麼你需要使用的一個聚合工具來做。即使你沒有真正聚合任何東西,你也可以。