使用分页数据和总计进行Mongo聚合

时间:2017-02-08 11:04:06

标签: mongodb pagination mongodb-query aggregation-framework

我已遍历堆栈溢出,并且未找到有关如何返回结果集中包含的正确分页数据的任何信息。

我正在尝试从我的mongo商店聚合一些数据。我想要的是回归:

    <?xml version="1.0" encoding="UTF-8"?>
<output>
   <case>
      <Applicants>
         <objectid>1234</objectid>
         <reason>
            <key>asd345</key>
         </reason>
         <reason>
            <key>asd34567</key>
         </reason>
      </Applicants>
      <Applicants>
         <objectid>3456</objectid>
         <reason>
            <key>asd1111</key>
         </reason>
      </Applicants>
      <Applicants>
         <objectid>7889</objectid>
         <reason>
            <key>asd9999</key>
         </reason>
      </Applicants>
   </case>
</output>

这是我到目前为止所做的:

{
  total: 5320,
  page: 0,
  pageSize: 10,
  data: [
    {
      _id: 234,
      currentEvent: "UPSTREAM_QUEUE",
      events: [
        { ... }, { ... }, { ... }
      ]
    },
    {
      _id: 235,
      currentEvent: "UPSTREAM_QUEUE",
      events: [
        { ... }, { ... }, { ... }
      ]
    }
  ]
}

我正在尝试将分页组作为root用户,其中包含实际的分组数据(以便我获得实际总数,同时仍然保留// page and pageSize are variables db.mongoAuditEvent.aggregate([ // Actual grouped data {"$group": { "_id" : "$corrId", "currentEvent": {"$last": "$event.status"}, "events": { $push: "$$ROOT"} }}, // Pagination group {"$group": { "_id": 0, "total": { "$sum": "corrId" }, "page": page, "pageSize": pageSize, "data": { "$push": { "_id": "$_id", "currentEvent": "$currentEvent", "events": "$events" } } }}, {"$sort": {"events.timestamp": -1} }, // Latest first {"$skip": page }, {"$limit": pageSize } ], {allowDiskUse: true}); skip)。

上面的代码将在mongo控制台中返回以下错误: limits

如果我从分页组中删除The field 'page' must be an accumulator objectpage,我仍会收到以下错误:

  

BSONObj大小:45707184(0x2B96FB0)无效。大小必须介于0和16793600之间(16MB)第一个元素:id:0

如果我一起删除分页组,查询工作正常。但是我真的需要返回我存储了多少文档pageSize,尽管实际上并不是必需的,totalpage也会很好地返回。

有人可以告诉我我做错了什么吗?或者告诉我是否可以一次性完成这项工作?

3 个答案:

答案 0 :(得分:14)

如果你有很多事件,{$ push:“$$ ROOT”},会让Mongo返回错误,我用$facet解决了它(仅适用于版本3.4 +)

aggregate([
    { $match: options },
    {
      $facet: {
        edges: [
          { $sort: sort },
          { $skip: skip },
          { $limit: limit },
        ],
        pageInfo: [
          { $group: { _id: null, count: { $sum: 1 } } },
        ],
      },
    },
  ])

答案 1 :(得分:1)

这是分两步而不是一步:

// Get the totals
db.mongoAuditEvent.aggregate([{$group: {_id: "$corrId"}}, {$group: {_id: 1, total: {$sum: 1}}}]);

// Get the data
db.mongoAuditEvent.aggregate([
  {$group: {
    _id : "$corrId", 
    currentEvent: {"$last": "$event.status"}, 
    "events": { $push: "$$ROOT"}
  }},
  {$sort: {"events.timestamp": -1} }, // Latest first
  {$skip: 0 },
  {$limit: 10}
], {allowDiskUse: true}).pretty();

如果有人能得到更好的解决方案,我会很高兴。

答案 2 :(得分:0)

性能优化提示:

  

在使用 $ facet 阶段进行分页时,   尝试尽快添加它。

例如:如果要添加$ project或$ lookup阶段,请将它们添加到$ facet中,而不要添加到$ facet中。

它将对聚合速度产生令人印象深刻的影响。因为$ project阶段要求MongoDB浏览所有文档并参与所有领域。