【发布时间】:2019-10-18 14:35:03
【问题描述】:
我收到了一个我认为很简单的问题,但我无法弄清楚。我想做的是这样的:
- 查找集合中的所有文档并:
- 按特定日期字段对文档进行排序
- 在其其他字段之一上应用
distinct,但返回整个文档
最好在示例中显示。
这是一个模拟输入:
[
{
"commandName" : "migration_a",
"executionDate" : ISODate("1998-11-04T18:46:14.000Z")
},
{
"commandName" : "migration_a",
"executionDate" : ISODate("1970-05-09T20:16:37.000Z")
},
{
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
},
{
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
]
预期的输出是:
[
{
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
},
{
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
]
或者,换句话说:
- 按
commandName字段对输入数据进行分组 - 在每个组内对文档进行排序
- 返回每个组中的最新文档
我编写此查询的尝试失败了:
distinct()函数只会返回我正在区分的字段的值,而不是整个文档。这使得它不适合我的情况。尝试编写
aggregate查询,但遇到了如何从每个组内部排序和选择单个文档的问题?sort聚合阶段将对groups进行排序,这不是我想要的。
我对 Mongo 不太精通,这就是我碰壁的地方。关于如何继续的任何想法?
作为参考,这是我正在尝试扩展的正在进行中的聚合查询:
db.getCollection('some_collection').aggregate([
{ $group: { '_id': '$commandName', 'docs': {$addToSet: '$$ROOT'} } },
{ $sort: {'_id.docs.???': 1}}
])
解决后的编辑
感谢您的回答。我得到了我需要的东西。以供将来参考,这是完整的查询,它将执行所请求的操作并返回已过滤文档的列表,而不是组。
db.getCollection('some_collection').aggregate([
{ $sort: {'executionDate': 1}},
{ $group: { '_id': '$commandName', 'result': { $last: '$$ROOT'} } },
{ $replaceRoot: {newRoot: '$result'} }
])
没有$replaceRoot 阶段的查询结果将是:
[
{
"_id": "migration_a",
"result": {
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
}
},
{
"_id": "migration_b",
"result": {
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
}
]
外部的_id 和_result 只是我想要的实际文档的“组包装器”,它嵌套在result 键下。使用$replaceRoot 阶段将嵌套文档移动到结果的根目录。使用该阶段时的查询结果为:
[
{
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
},
{
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
]
【问题讨论】:
标签: mongodb mongodb-query aggregation-framework