長篇帖子道歉!MongoDB - 選擇聚合中的組而不指定字段
我有一個蒙戈集合與下列文件:
{
"_id" : ObjectId("592811e3fab9f74b07139d73"),
"Name" : "John",
"Value" : 1,
"AnotherValue": "12345"
},
{
"_id" : ObjectId("592811f8fab9f74b07139d78"),
"Name" : "John",
"Value" : 5,
"AnotherValue": "55555"
},
{
"_id" : ObjectId("59281206fab9f74b07139d7e"),
"Name" : "John",
"Value" : 12,
"AnotherValue": "654321"
},
{
"_id" : ObjectId("59281217fab9f74b07139d81"),
"Name" : "Chris",
"Value" : 3,
"AnotherValue": "11111"
},
{
"_id" : ObjectId("59281223fab9f74b07139d85"),
"Name" : "Steve",
"Value" : 2,
"AnotherValue": "22222"
},
{
"_id" : ObjectId("5928122ffab9f74b07139d87"),
"Name" : "Steve",
"Value" : 4,
"AnotherValue": "33333"
}
我要查詢這些文件和返回值最高爲每名的條目,所以我期望的結果集(順序不物質)是:
{
"_id" : ObjectId("59281206fab9f74b07139d7e"),
"Name" : "John",
"Value" : 12,
"AnotherValue": "654321"
},
{
"_id" : ObjectId("59281217fab9f74b07139d81"),
"Name" : "Chris",
"Value" : 3,
"AnotherValue": "11111"
},
{
"_id" : ObjectId("5928122ffab9f74b07139d87"),
"Name" : "Steve",
"Value" : 4,
"AnotherValue": "33333"
}
如果我想要做的正是在C#同樣的事情,我會用:
var result =
from item in collection
orderby item.Value descending
group item by item.Name into itemGroup
select itemGroup.First();
使用聚合管道我有儘可能:
db.getCollection('test').aggregate(
[
{ "$sort" : { "Value" : -1 } }, //sort descendingly by the Value field
{ "$group" : { "_id" : "$Name", "highest" : { "$first" : "$$ROOT" } } }, //group by name and select the first document in the group (as they are sorted descendingly, this will be the document with the highest value)
])
這給了我下面的結果集:
正如你所看到的,我的文檔的陣列,每個都包含一個作爲名稱的「_id」字段和作爲實際文檔的「最高」字段。
這將在C#中表示爲:
var result =
from item in collection
orderby item.Value descending
group item by item.Name into itemGroup
select new { id = itemGroup.Key, highest = itemGroup.First() };
我想知道的,是有可能的另一個步驟添加到我的管道,以確保我只選擇實際的個人文檔,而不是一組文檔其中包含人員文檔,並且可以在不指定字段的情況下執行此操作?我希望編寫一個C#類,它將能夠使用這個查詢的各種不同類型的對象,所以字段可能不知道(假設我可能想使用這個查詢的每個集合都有名稱和值字段,他們都會有一些共同的屬性)。
如果我以完全錯誤的方式來解決這個問題,那麼我會接受全新的建議。只要我最終達到預期結果,我就會開心。
在此先感謝您的幫助。
聚集規模做不大,因爲他們不與分片玩好。 – arboreal84
如果你有MongoDB 3.4你可以使用['$ replaceRoot'](https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/),否則你需要用'$ project指定所有的字段'。所以升級如果這是必須的。但這真的很糟嗎?在任何一種情況下,我都會看到折衷是在聚合管道中再次運行結果的成本,或者僅處理每個返回的客戶端代碼結果。對於這種微不足道的用法,我只是在客戶端代碼中進行。 –
$ replaceRoot已經實現了我之後的完全一樣。謝謝! –