MongoDB-在聚合中选择组,但不指定字段
抱歉发了这么长的帖子 我有一个Mongo收藏,包含以下文档:MongoDB-在聚合中选择组,但不指定字段,mongodb,aggregation-framework,Mongodb,Aggregation Framework,抱歉发了这么长的帖子 我有一个Mongo收藏,包含以下文档: { "_id" : ObjectId("592811e3fab9f74b07139d73"), "Name" : "John", "Value" : 1, "AnotherValue": "12345" }, { "_id" : ObjectId("592811f8fab9f74b07139d78"), "Name" : "John", "Value" : 5, "Ano
{
"_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"
}
我想查询这些文档,并返回每个名称的最大值条目,因此我想要的结果集(顺序无关紧要)是:
如果我想在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" : "Steve",
"highest" : {
"_id" : ObjectId("5928122ffab9f74b07139d87"),
"Name" : "Steve",
"Value" : 4,
"AnotherValue": "33333"
}
},
{
"_id" : "Chris",
"highest" : {
"_id" : ObjectId("59281217fab9f74b07139d81"),
"Name" : "Chris",
"Value" : 3,
"AnotherValue": "11111"
}
},
{
"_id" : "John",
"highest" : {
"_id" : ObjectId("59281206fab9f74b07139d7e"),
"Name" : "John",
"Value" : 12,
"AnotherValue": "654321"
}
}
{
"_id" : ObjectId("5928122ffab9f74b07139d87"),
"Name" : "Steve",
"Value" : 4
},
{
"_id" : ObjectId("59281217fab9f74b07139d81"),
"Name" : "Chris",
"Value" : 3
},
{
"_id" : ObjectId("59281206fab9f74b07139d7e"),
"Name" : "John",
"Value" : 12
}
如您所见,我有一个文档数组,每个文档都包含一个“_id”字段(名称)和一个“highest”字段(实际文档)
这将用C表示为:
我想知道的是,是否可以向我的管道中添加另一个步骤,以确保我只选择实际的person文档,而不是包含person文档的组文档,并且我可以在不指定字段的情况下执行此操作?我希望编写一个C#类,该类能够对各种不同类型的对象使用此查询,因此字段可能未知(假设我可能要使用此查询的每个集合都有名称和值字段,它们都有一些公共属性)
如果我以完全错误的方式来处理这个问题,那么我会接受全新的建议。只要我最终得到了想要的结果,我就会很高兴
提前感谢您的帮助。非常感谢Neil Lunn,他在评论中回答了我的问题 MongoDB 3.4有一个$replaceRoot管道选项,可以完全满足我的需要:
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)
{ "$replaceRoot": { newRoot: "$highest" } }
])
结果集:
{
"_id" : "Steve",
"highest" : {
"_id" : ObjectId("5928122ffab9f74b07139d87"),
"Name" : "Steve",
"Value" : 4,
"AnotherValue": "33333"
}
},
{
"_id" : "Chris",
"highest" : {
"_id" : ObjectId("59281217fab9f74b07139d81"),
"Name" : "Chris",
"Value" : 3,
"AnotherValue": "11111"
}
},
{
"_id" : "John",
"highest" : {
"_id" : ObjectId("59281206fab9f74b07139d7e"),
"Name" : "John",
"Value" : 12,
"AnotherValue": "654321"
}
}
{
"_id" : ObjectId("5928122ffab9f74b07139d87"),
"Name" : "Steve",
"Value" : 4
},
{
"_id" : ObjectId("59281217fab9f74b07139d81"),
"Name" : "Chris",
"Value" : 3
},
{
"_id" : ObjectId("59281206fab9f74b07139d7e"),
"Name" : "John",
"Value" : 12
}
聚合无法扩展,因为它们不能很好地使用分片。如果您有MongoDB 3.4,则可以使用,否则需要使用
$project
指定所有字段。因此,如果必须升级,请升级。但真的有那么糟糕吗?在这两种情况下,我看到的折衷是在聚合管道中再次运行结果的成本,或者只是在客户端代码中处理每个返回的结果。对于这种琐碎的用法,我只需要在客户端代码中进行操作。$replaceRoot已经实现了我所追求的目标。非常感谢。