mongo分页查询,同时返回分页记录和记录数

今天做了一个mongo的分页查询,记录一下mongo如何同时返回分页记录和记录数的方法,利用的是mongo的聚合查询里面的$facet阶段,具体使用参考官方文档即可https://docs.mongodb.com/manual/reference/operator/aggregation/facet/

按照官方文档的说法,

Input documents are passed to the $facet stage only once. $facet enables various aggregations on the same set of input documents, without needing to retrieve the input documents multiple times.

利用的是同一个上个阶段返回的记录集,所以从原理上来说是没有二次查询的,效率自然比传统数据库里面的分页实现方式效率上要高,不过由于aggregate的返回只能是文档,所以对于结果的处理可能会比较繁琐,需要自己一个个解析以及类型强转。

类似的facet阶段可以采用如下形式

{
     '$facet': {
       'count': [
         {
           '$count': 'count'
         }
       ],
       'data': [
         {
           '$sort': {
             '_id': 1
           }
         }, {
           '$skip': 1
         }, {
           '$limit': 2
         }
       ]
     }
}

出来的结果是一个文档,而且由于mongo的单文档限制是16M,所以相应的data字段里面的记录集不能太多,不过既然做分页了,这个地方应该就不需要考虑了吧.出来的记过类似这个样子

{
    "count": [
        {
            "count": 14453
        }
    ],
    "data": [
        {
            "ts": "2021-01-21 08:00:28",
            "x": "0.0000",
            "y": "0.2089"
        },
        {
            "ts": "2021-01-21 08:01:19",
            "x": "0.0000",
            "y": "0.3256"
        }
    ]
}

最后如果是在java里面的话,最后的结果集可能就需要自己进行额外处理了,类似这个样子

Object count = ((Document)((List)rs.get(0).get("count")).get(0)).get("count");
Object data = (List)rs.get(0).get("data");

有点不好看.

##补充

如果是在mongo shell 里面的话,对于db.test.find()方法返回的游标cursor,官方文档里面提供了cursor.count(applySkipLimit),用以忽略skip()和limit()的影响,如果applySkipLimit设置为true的话,就会对相关返回结果应用limit和skip的效应,有兴趣的可以自己去研究一下.不知道其他语言的驱动里面有没有相关的api,在java里面我是没找到。

原文地址:https://www.cnblogs.com/marshwinter/p/14309713.html