如何在mongo中执行此查询:获取用户列表的最新消息

时间:2014-02-01 08:16:09

标签: mongodb mongodb-query aggregation-framework nosql

我有一组消息,其中包含字段user_id,created_time和content。给定一个user_id列表,我想找回一个消息列表,其中每个user_id包含一条关于该用户的最新消息。我想在mongo中使用一个不同的命令和sort,但似乎没有得到支持。有没有办法在mongo中使用单个查询执行此操作?

1 个答案:

答案 0 :(得分:2)

MongoDB有Aggregation framework,您可以将其用于需要对集合中的数据进行操作的任务

考虑以下数据集

> db.messages.find().pretty()
{
    "_id" : ObjectId("52ecb77486d35a12f3552aa1"),
    "user_id" : "fred",
    "create_date" : ISODate("1392-09-21T00:00:00Z")
}
{
    "_id" : ObjectId("52ecb79286d35a12f3552aa2"),
    "user_id" : "fred",
    "create_date" : ISODate("1392-06-01T00:00:00Z")
}
{
    "_id" : ObjectId("52ecb7a386d35a12f3552aa3"),
    "user_id" : "marty",
    "create_date" : ISODate("1393-04-06T00:00:00Z")
}
{
    "_id" : ObjectId("52ecb7af86d35a12f3552aa4"),
    "user_id" : "marty",
    "create_date" : ISODate("1386-02-12T00:00:00Z")
}

因此,在将其传递给汇总时,我们希望对user_id进行分组并获取最新内容或maximum create_date

> db.messages.aggregate([
    { $group: { _id: { user_id: "$user_id" }, create_date: {  $max: "$create_date" }} }
  ])
{
    "result" : [
            {
                    "_id" : {
                            "user_id" : "marty"
                    },
                    "create_date" : ISODate("1393-04-06T00:00:00Z")
            },
            {
                    "_id" : {
                            "user_id" : "fred"
                    },
                    "create_date" : ISODate("1392-09-21T00:00:00Z")
            }
    ],
    "ok" : 1
}

这不错,但你可以用 $ project

清理它
> db.messages.aggregate([
    { $group: { _id: { user_id: "$user_id" }, create_date: {  $max: "$create_date" }} },
    { $project: {  _id: 0, user_id: "$_id.user_id", create_date: 1} }
  ])
{
    "result" : [
            {
                    "create_date" : ISODate("1393-04-06T00:00:00Z"),
                    "user_id" : "marty"
            },
            {
                    "create_date" : ISODate("1392-09-21T00:00:00Z"),
                    "user_id" : "fred"
            }
    ],
    "ok" : 1
}

所以它实际上看起来像一个干净的记录。在最新的驱动程序中,聚合返回的值应该是可以迭代的游标。所以结果和使用find一样。

可以找到有关运营商使用的其他文档here