是否可以通过管道在 Mongo 中高效地进行排序、分组和限制?

2023-11-30

给定具有年龄索引的用户:

{ name: 'Bob',
  age:   21  }

{ name: 'Cathy,
  age:   21  }

{ name: 'Joe',
  age:   33  }

获取输出:

[ 
  { _id: 21,
    names: ['Bob, 'Cathy'] },
  { _id: 33,
    names: ['Joe'] }
]

是否可以按年龄排序、分组和限制?

db.users.aggregate(
   [  
      {
        $sort: { 
           age: 1 
        }
      },
      {
        $group : {
           _id : $age,
           names:{ $push: '$name' }
      },
      {
        $limit: 10
      }
  ]

我做了一些研究,但不清楚是否可以先排序然后分组。在我的测试中,该组失去了排序,但我不明白为什么。

如果组保留排序,那么排序和限制可以大大减少所需的处理。它只需要做足够的工作来“填满”10组的限制。

So,

  1. 组是否保留排序顺序?还是必须先分组然后排序?
  2. 是否可以进行排序、分组和限制,仅进行足够的处理来返回限制?还是需要处理整个集合然后进行限制?

回答你的第一个问题:$group does not保留订单。有一个开放的更改请求,这些更改也稍微突出了背景,但看起来不会更改产品以保留输入文档的顺序:

  • https://jira.mongodb.org/browse/SERVER-24799
  • https://jira.mongodb.org/browse/SERVER-4507
  • https://jira.mongodb.org/browse/SERVER-21022

一般可以说两件事:您通常希望先进行分组,然后再进行排序。原因是对较少的元素(分组通常产生的)进行排序将比对所有输入文档进行排序更快。

其次,MongoDB 将确保尽可能高效且尽可能少地进行排序。这文档 states:

当管道中 $sort 紧邻 $limit 之前时,$sort 操作仅在进行时保留前 n 个结果,其中 n 是指定的限制,MongoDB只需要存储n个项目 记忆。当allowDiskUse为true并且 n 个项目超出了聚合内存限制。

所以这段代码可以完成您的情况:

collection.aggregate({
    $group: {
        _id: '$age',
        names: { $push: '$name' }
    }
}, {
    $sort: { 
        '_id': 1 
    }
}, {
    $limit: 10
})

EDIT根据您的评论:

我同意你说的。进一步考虑你的逻辑,我什至会说:如果$group足够聪明,可以使用索引,那么它甚至不需要$sort开始时的阶段。不幸的是,它不是(还可能不是)。就今天的情况来看,$group永远不会使用索引,也不会根据以下阶段走捷径($limit在这种情况下)。另请参阅此link有人进行了一些基本测试。

聚合框架还很年轻,所以我想,为了使聚合管道更智能、更快速,还有很多工作要做。

StackOverflow 上有答案(例如here)人们建议使用预先$sort阶段以“强制”MongoDB 以某种方式使用索引。然而,这显着减慢了我的测试速度(使用不同随机分布的样本形状的 100 万条记录)。

当谈到聚合管道的性能时,$match开始的阶段才是真正有帮助的。如果您可以从一开始就限制需要通过管道的记录总量,那么这就是您最好的选择 - 显然......;)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以通过管道在 Mongo 中高效地进行排序、分组和限制? 的相关文章

随机推荐

  • 输入模式,至少 1 个非空白字符

    我想将以下内容重写为 HTML 模式 if S test myString string is not empty and not just whitespace So
  • 使用 jQuery 访问 css“:after”选择器[重复]

    这个问题在这里已经有答案了 我有以下CSS pageMenu active after content margin top 6px display inline block width 0px height 0px border top
  • 类变量在Python中的所有实例之间共享? [复制]

    这个问题在这里已经有答案了 我一周前开始用 python 编码 这是我的错误 我很快就开始使用 oops 类和对象进行编码 我认为我的 C 熟练程度会有所帮助 我被以下代码所困扰 class A var 0 list def init se
  • 在 ASP.NET Core 的 Application Insights 中填写用户 ID 字段

    我希望能够使用我的真实用户名数据填充 Application Insights 中的 用户 ID 字段 这是一个内部应用程序 因此简单的用户名字段的隐私问题没有实际意义 据我所知 所有在线可用的解决方案都严格适用于 NET Framewor
  • Spring Kafka 支持多个消费者的要求

    正如人们所期望的那样 通常希望不同的消费者以不同的方式反序列化 Kafka 中的主题 Spring Boot 自动配置存在一个已知问题 似乎一旦定义了其他工厂 Spring Kafka 或自动配置就会抱怨无法再找到合适的消费者工厂 有人指出
  • 在php中将数字等字母增加一定的值

    在 php 中如果我写 c A c 它递增到 B 但如果我想将其递增 2 3 或更多 例如 c 2 或 c 3 获取替代字母表 for column B column lt highestColumn column cell workshe
  • 在函数之间传递 MutableLiveData

    我在 ViewModel 中有一个函数 A 它从 firebase 检索数据 并将值分配给MutableLiveData
  • Spring MVC 4 和 Thymeleaf - 防止页面刷新

    我保证 我已经用谷歌搜索过这个了 我有一个 Spring MVC 4 应用程序 它使用 Thymeleaf 收集表单数据并将其放入数据库中 工作得很好 除了我希望我的应用程序在用户点击提交按钮后将用户留在表单页面上 以便他们可以继续编辑 每
  • 单应性到射影变换

    我一直在试图弄清楚如何在两个平面之间获取单应性并将其转换为射影变换 Matlab 自动执行此操作 但我一直在尝试弄清楚 matlab 如何实现转换 你可以在toolbox images images maketform m中查看源代码 至少
  • Javascript/jQuery - 浮点验证?

    我有一个文本字段 人们可以在其中输入价格 XX xx 有没有办法确保他们只输入小数点后不超过 2 位数字 以下是主要的验证类型 document ready function for numeric integer only var num
  • 使用 jQuery 对记录进行分页

    我有一个包含大量记录的 JSON 结果 我想显示第一个 但有一个下一个按钮可以查看第二个 依此类推 我不希望页面刷新 这就是为什么我希望 JavaScript jQuery 甚至第三方 AJAX 库的组合可以提供帮助 有什么建议么 希望这可
  • 非类型模板参数

    我在使用非类型 int 变量 模板参数时遇到问题 为什么我不能将常量 int 变量传递给函数并让函数实例化模板 template
  • R 从带有 csv 文件内容的内联字符串中读取 .csv 数据

    这应该是一件微不足道的事情 但我没有在谷歌上找到任何东西 我的 csv 文件中有以下数据 test csv var1 var2 a 1 b 2 我用它读入 R d lt read csv test csv 我有办法在 R 代码中插入 csv
  • 可以在带引号的 XML 属性值字符串中使用文字尖括号吗?

    例如 这是有效的 XML 吗
  • 生成指数分布的随机数

    include
  • 如何在SQL中获取3天内的记录分组日期?

    每 5 天对记录进行分组和显示变得越来越困难 这是我的数据 FLIGHT DATE LANDINGS PILOTID COPILOTNAME MONT DPT 11 16 2013 1 A B 11 5 5 11 17 2013 1 A B
  • SSRS 2012 和 CSV 导出

    我正在使用 SSRS 2012 尝试执行以下操作 某些列应仅根据用户请求使用组合框可见 列的可见性取决于组合上所选的列 这看起来效果很好 当我以不同于 csv 的任何格式导出输出时 这些列保持不可见 但是 当导出到 csv 时 会显示不可见
  • 如何修改jenkins中可编辑电子邮件插件中的mime消息

    我想修改从詹金斯发送的电子邮件 我该怎么做 我尝试使用 msg 变量并使用 msg setContent 这是我在电子邮件正文中想要的字符串 设置内容 但它失败了 有任何想法吗 我刚刚面临同样的任务 msg setContent Test
  • 如何在应用程序制作工具中创建rest api?

    有没有办法在应用程序制造商的服务器端脚本中创建 REST API 我需要从 iOS 应用程序调用服务器端函数 传递一些参数并获得响应 而无需转到应用程序中的页面 我知道对于常规的谷歌应用程序脚本来说 可以通过执行 API 来实现 但我不知道
  • 是否可以通过管道在 Mongo 中高效地进行排序、分组和限制?

    给定具有年龄索引的用户 name Bob age 21 name Cathy age 21 name Joe age 33 获取输出 id 21 names Bob Cathy id 33 names Joe 是否可以按年龄排序 分组和限制