首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何按组进行聚合并正确排序

如何按组进行聚合并正确排序
EN

Stack Overflow用户
提问于 2014-05-27 21:38:39
回答 3查看 2.3K关注 0票数 2

我在用Mongodb。考虑我的下一份文件:

代码语言:javascript
复制
{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 1, created: ISODate("2014-05-01..."), another_col : "f" },
{ uid: 2, created: ISODate("2014-05-22..."), another_col : "a" }

我要做的是在uid上创建一个简单的groupby,并按降序排序创建的,这样我就可以得到每个uid的第一行。

预期输出的示例

代码语言:javascript
复制
{ uid: 1, created: ISODate("2014-05-05..."), another_col: "y" },
{ uid: 2, created: ISODate("2014-05-22..."), another_col: "a" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col: "w" }

我能得到的最好结果是:

代码语言:javascript
复制
db.mycollection.aggregate( {$group: {_id: "$uid", rows: {$push: { "created" : "$created" }}}}, sort { // doesnt work well }  )

有谁能引导我通过分组和排序来正确组合?只是不像我预料的那样起作用了。(注:我检查过许多线程,但无法找到正确的答案)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-05-30 07:43:22

这里有几个陷阱需要理解。

当您使用$group时,边界将按照在没有初始或结束阶段$sort操作的情况下被发现的顺序排序。因此,如果您的文档最初是按如下顺序排列的:

代码语言:javascript
复制
{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },

然后,只要在管道的末尾使用没有$sort$sort,就会返回如下结果:

代码语言:javascript
复制
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },

这是一个概念,但实际上,您在结果中所期望的似乎需要按照uid的排序顺序返回“最后一个其他字段”,这就是您要寻找的。在这种情况下,获得结果的方法实际上是首先使用$sort,然后使用$last操作符:

代码语言:javascript
复制
db.mycollection.aggregate([

    // Sorts everything first by _id and created
    { "$sort": { "_id": 1, "created": 1 } },

    // Group with the $last results from each boundary
    { "$group": {
        "_id": "$uid",
        "created": { "$last": "$created" },
        "another_col": { "$last": "$created" }
    }}
])

或者从本质上对你想要的东西应用这种方法。

$last$max的不同之处在于,后者将为分组_id中的给定字段选择“最高”值,而不管在未排序的顺序上当前排序如何。另一方面,$last将选择与“最后”分组_id值相同的“行”中的值。

如果您实际上是想对数组的值进行排序,那么这种方法是相似的。保持数组成员的“创建”顺序,您也可以先排序:

代码语言:javascript
复制
db.mycollection.aggregate([

    // Sorts everything first by _id and created
    { "$sort": { "_id": 1, "created": 1 } },

    // Group with the $last results from each boundary
    { "$group": {
        "_id": "$uid",
        "row": {
            "$push": {
                "created": "$created",
                "another_col": "$another_col"
            }
        }
    }}
])

带有这些字段的文档将按照已经被排序的顺序添加到数组中。

票数 4
EN

Stack Overflow用户

发布于 2014-05-27 21:49:49

如果你要找的只是第一行,那就意味着你在寻找最大的。只需使用内置$max累加器即可。

代码语言:javascript
复制
db.mycollection.aggregate([{$group: {_id: "$uid", rows: {$max:"$created"}}}])

如果需要处理所有创建日期,可以使用$push累加器。有关累加器的更多信息,请参见:http://docs.mongodb.org/manual/reference/operator/aggregation/group/

如果您想要返回完整的文档,并且希望能够迭代所有文档,那么就不需要聚合结果了。像这样的东西应该能让你得到你想要的。

代码语言:javascript
复制
db.mycollection.find({$query:{}, $orderby:{uid:1,created:-1}})
票数 0
EN

Stack Overflow用户

发布于 2014-05-28 11:25:41

在使用$project的同时

代码语言:javascript
复制
db.mycollection.aggregate([{$group: {_id: "$uid", rows: {$max:"$created"}}}])

应该对你有帮助,请参考以下链接

http://docs.mongodb.org/manual/reference/operator/aggregation/project/

Mongodb group and project operators

mongodb aggregation framework group + project

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23899409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档