【发布时间】:2016-08-04 20:34:40
【问题描述】:
假设我们在 mongodb 中存储了以下一组文档:
{ "fooId" : "1", "status" : "A", "timestamp" : ISODate("2016-01-01T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "1", "status" : "B", "timestamp" : ISODate("2016-01-02T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "1", "status" : "C", "timestamp" : ISODate("2016-01-03T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "2", "status" : "A", "timestamp" : ISODate("2016-01-01T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "2", "status" : "B", "timestamp" : ISODate("2016-01-02T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "3", "status" : "A", "timestamp" : ISODate("2016-01-01T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "3", "status" : "B", "timestamp" : ISODate("2016-01-02T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "3", "status" : "C", "timestamp" : ISODate("2016-01-03T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "3", "status" : "D", "timestamp" : ISODate("2016-01-04T00:00:00.000Z") "otherInfo" : "BAR", ... }
我想根据时间戳获取每个 fooId 的最新状态。因此,我的回报看起来像:
{ "fooId" : "1", "status" : "C", "timestamp" : ISODate("2016-01-03T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "2", "status" : "B", "timestamp" : ISODate("2016-01-02T00:00:00.000Z") "otherInfo" : "BAR", ... }
{ "fooId" : "3", "status" : "D", "timestamp" : ISODate("2016-01-04T00:00:00.000Z") "otherInfo" : "BAR", ... }
我一直在尝试通过使用 group 运算符的聚合来解决这个问题,但我想知道的部分是有一种简单的方法可以从聚合中获取整个文档,因此它看起来就像我使用了查找查询?似乎您必须在分组时指定所有字段,如果文档上可以包含我可能不知道的可选字段,这似乎不可扩展。我当前的查询如下所示:
db.collectionName.aggregate(
[
{ $sort: { timestamp: 1 } },
{
$group:
{
_id: "$fooId",
timestamp: { $last: "$timestamp" },
status: { "$last": "$status" },
otherInfo: { "$last": "$otherInfo" },
}
}
]
)
【问题讨论】:
-
您已经以正确的方式进行操作了。当然,您可以使用
$$ROOT并将整个文档放在一个属性中,但这不是同一个结构,是吗?如果您非常担心“输入”每个字段,那么只需“在代码中生成最终的$group管道语句”。这是一件非常简单的事情,所有 MongoDB 查询和聚合管道语句毕竟只是“数据结构”。
标签: mongodb mongodb-query aggregation-framework