MongoDB-在聚合中选择组,但不指定字段

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

抱歉发了这么长的帖子

我有一个Mongo收藏,包含以下文档:

{
    "_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已经实现了我所追求的目标。非常感谢。