Mongo 查询怎样先按一个字段分组,然后对所有组进行组内排序(按另一字段)?

发布于 2022-09-04 06:56:00 字数 484 浏览 9 评论 0

比方说数据库存有 Post 类型的数据,每个文档记录了发布帖子的时间和该帖子获得的投票数:

...
{ time: 1481185194698,
  vote: 2 }
...

我这里想执行一个 find({}) 操作,把所有帖子按照发布时间 24 小时间隔分组(新一天的组排前面),然后每个组内再按照投票数排序。我查遍了 MongoDB 的文档,没有找到解决方案,请问这可以办到吗?

我也查看了 Mongo 的 aggregate 操作,聚合的 $group 和 $bucket 操作都会合并文档,我这里只想查询,不想合并文档。

------------------------UPDATE 2016/12/09--------------------------

问题解决了,最终采用的解决方案是在数据库里新增一个 daysFrom 字段,用来保存距离 1970/1/1 过去的天数,然后按照该天数排序。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一桥轻雨一伞开 2022-09-11 06:56:00

办法还是有的,会比较绕一些。
首先你的时间是NumberLong,这种类型无法直接取到天。所以第一步需要转换类型,把所有记录的“天”拿出来投影成一个字段。
然后没理解错的话,你的要求应该是按天排序,同样的天内再按vote排序。所以第二个pipeline是一个$sort。处理之后应该是你想要的结果。

db.test.aggregate([
    // {$match: <cond>}
    {
        $project: {
            time: "$time",
            date: {$multiply: [{$floor: {$divide: ["$time", 86400000]}}, 86400000]}, // 864000ms = 1天
            vote: "$vote"
        }
    },
    {$sort: {date: 1, vote: -1}}
])

注意:

  1. 如果对全部数据都做这个操作,肯定是一个很费时的操作,所以建议第一个条件用$match先过滤出你感兴趣的时间再进行后面的操作

  2. 如果考虑到时区问题,可能还要做些修改。不妨自己理解一下上面的语句再自己修改。

ゞ花落谁相伴 2022-09-11 06:56:00

1、假设model如下:

{ title : 'xxxx',
  time : 1481185194698,
  vote : 2}

2、试试如下的aggregation

db.post.aggregate([
                    {$group: {
                    _id: {year : {$year :'$time'},
                          month: {$month :'$time'},
                          day: {$dayOfMonth : '$time'},
                          title : $title
                    },
                    total: {$sum:'$vote'}}},
                    {$sort: {_id:-1}}
                  ]);

看到您更新的说明,如果不使用aggregate,那么使用基于time的range查询不满足您的需求吗?

关于time,留意一下:1、时区;2、在使用string,还是date类型

db.post.find({time: {$gte: start, $lt: end}});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文