MongoDB / Mongoose orderby日期和groupby用户

时间:2014-07-29 20:44:18

标签: mongodb mongoose

我有一个集合,其中多个文档可能具有相同的userId字段。我想将userId分组,以便获得唯一userId的列表,但也按date排序,以便每个返回的文档都是userId的最新文档}。我用sql完成了这样的查询,我真的希望mongo可以实现。

在此示例集合中:

{ userId: 456, date: 5/16/1988 },
{ userId: 456, date: 5/17/1988 },
{ userId: 789, date: 5/18/1988 },
{ userId: 789, date: 5/17/1988 }

我想回复:

{ userId: 456, date: 5/17/1988 },
{ userId: 789, date: 5/18/1988 }

3 个答案:

答案 0 :(得分:2)

以下是如何在mongo中执行此操作。请注意,它使用日期格式yyyy-mm-dd。

db.collection.aggregate({
  $group: {
    id : '$userId',
    date: { $max: '$date'} 
  }
})

资料来源:http://docs.mongodb.org/manual/

答案 1 :(得分:0)

在你的问题中,你说你想要返回完整的文件。您可以将完整文档作为$group运算符中的字段返回。

db.coll.aggregate([
  {$sort:{date:-1}},
  {$group: {_id: "$userId", doc:{$first: "$$CURRENT"}} }
])

我在Date类型的问题中创建了四个文档作为一些随机日期。这会给你以下结果:

{
    "_id" : 789,
    "doc" : {
        "_id" : ObjectId("53d80e246ebc37d0c33321ba"),
        "userId" : 789,
        "date" : ISODate("2014-07-05T04:00:00.000Z")
    }
}, 
{
    "_id" : 456,
    "doc" : {
        "_id" : ObjectId("53d80e246ebc37d0c33321b8"),
        "userId" : 456,
        "date" : ISODate("2014-07-05T04:00:00.000Z")
    }
}

有关$$CURENT

的详情,请参阅http://docs.mongodb.org/manual/reference/operator/aggregation/group/#variables

答案 2 :(得分:0)

虽然它们可能是正确的方法,但我无法使用db.collection.aggregate方法,因为在这种情况下我需要在Model.find上使用其他东西,如.populate()。所以我提出了一个解决方法,我在find(选项)中对userID和date进行排序,如下所示:

{ sort: { updateDate: -1, userId: -1 } }

然后我在前端编写了一个函数来为每个用户提取最新记录:

filterLatest: function(docs) {
    var lastUserId = null;
    var latestDocs = [];

    docs.forEach(function(doc) {
        if(lastUserId != doc.userId) latestDocs.push(doc);
        lastUserId = doc.userId;
    });

    return latestDocs;
}