长篇帖子道歉!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已经实现了我之后的完全一样。谢谢! –