【问题标题】:How to get count before limit in the Mongo aggregation pipeline如何在 Mongo 聚合管道中获取限制之前的计数
【发布时间】:2014-09-18 16:34:56
【问题描述】:

在以下查询中:

db.orders.aggregate([{ $match : { status: "A"}, { $limit: 5} }]);

如何在$match 之后但在$limit 应用之前获取文档数?

我仍然想返回一个包含 5 个文档的数组。但是如果我使用$group,它似乎不会保留文档数组。可以一个电话完成,还是我必须打两个电话?

【问题讨论】:

    标签: mongodb count limit aggregation-framework


    【解决方案1】:

    Mongo 3.4 开始,$facet 聚合阶段允许在单个阶段内对同一组输入文档处理多个聚合管道:

    // { "status" : "A", "v" : 3 }
    // { "status" : "B", "v" : 14 }
    // { "status" : "A", "v" : 7 }
    // { "status" : "A", "v" : 5 }
    db.collection.aggregate(
      { $match: { status: "A"} },
      { $facet: {
          count:  [{ $count: "count" }],
          sample: [{ $limit: 2 }]
      }}
    )
    // {
    //   "count" : [ { "count" : 3 } ],
    //   "sample" : [ { "status" : "A", "v" : 3 }, { "status" : "A", "v" : 7 } ]
    // }
    

    这个:

    • matching 开始,statusA 的文档。

    • 然后通过$facet 阶段从两个不同的聚合管道中生成两个字段:

      • $count 仅提供从前面的$match 阶段生成的文档数。

      • sample 是从前面的$match 阶段产生的文档的$limited 提取。

    【讨论】:

    • 禁止我这样做,因为我的管道使用 mongoDB Atlas 搜索阶段
    • 使用$facet 的问题是它返回单个文档。尽管它包含一个文档列表,但该文档本身与 mongodb 中的其他文档一样,限制为 16MB。 $limit 可用于限制其大小,但响应中的单个文档可能会违反它。因此,如果您怀疑结果可能超过 16MB,最好的方法是查询两次。
    【解决方案2】:

    不幸的是,现在您必须进行两次调用,一次调用 $limit 运算符获取结果,然后第二次调用计数。您可以使用不带 $limit 运算符和 $group 运算符的聚合框架来计算计数,或者正如 wdberkeley 指出的那样,您可以将条件传递给 .count() 以获取计数,而不是使用聚合框架(如果您正在使用)一个单一的比赛阶段。

    MongoDB - Aggregation Framework (Total Count)

    【讨论】:

    • 使用.count()统计结果总数。
    • @wdberkeley 与聚合它不起作用。你必须打两个电话,就像 Brantino 说的那样
    • 请注意,如果您使用.count(),则将计算可能已在您的聚合调用中被 $group 消除的重复结果。
    【解决方案3】:

    从 3.4 版开始,现在可以使用 $facet 聚合在一次调用中完成此操作。示例见此处:Mongo aggregation with paginated data and totals

    【讨论】:

      【解决方案4】:

      另一种选择是在应用层而不是在 Mongo 查询中限制结果。这样您就可以得到完整结果的计数,而不必打两次电话。

      例如,在 Python 中你会这样做:

      data = db.orders.aggregate([{ "$match" : { "status": "A"} }])['result']
      count = len(data)
      data = data[skip:skip+limit]
      

      如果您对大型数据集进行复杂的聚合调用,这比进行两次调用要快得多。

      【讨论】:

      • 如果数据集非常大,它可能不适合内存 - 这就是为什么您可以获得流式游标而不是将所有结果集加载到应用程序服务器内存中的原因。此外,由 db 服务器执行计数操作将为您的应用程序服务器执行其他操作节省时间。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-26
      • 2016-04-26
      • 2018-09-20
      相关资源
      最近更新 更多