【问题标题】:Get total count along with Mongoose Query skip & limt获取总数以及 Mongoose 查询跳过和限制
【发布时间】:2016-04-28 23:36:05
【问题描述】:

我有一个包含许多对象的 json 数据。我想限制分页数据,我需要总项目数。请帮忙。

Model.find().skip((pageNumber-1)*limit).limit(limit).exec()

我想要计数和跳过的数据作为响应。

【问题讨论】:

标签: node.js database mongodb mongoose aggregation-framework


【解决方案1】:

您需要执行 2 次查询才能实现这一目标。一个获取结果,另一个获取.count() 的总项目金额。

例如,您可以在“paginator”上观看 mongoose mongoose-paginate 的代码。

【讨论】:

  • 我可以在一个 api 调用中做到这一点吗?@Alexy B
【解决方案2】:

您可以使用异步库一次运行 2 个查询。在您的情况下,您可以运行一个查询来获取文档的数量,另一个用于分页。

“用户”模型示例:

    var async = require('async');
    var User = require('./models/user');

    var countQuery = function(callback){
         User.count({}, function(err, count){
               if(err){ callback(err, null) }
               else{
                   callback(null, count);
                }
         }
    };

    var retrieveQuery = function(callback){
        User.find({}).skip((page-1)*PAGE_LIMIT)
                     .limit(PAGE_LIMIT)
                     .exec(function(err, doc){
                            if(err){ callback(err, null) }
                            else{
                            callback(null, doc);
                            }
                      }
    };

    async.parallel([countQuery, retrieveQuery], function(err, results){
         //err contains the array of error of all the functions
         //results contains an array of all the results
         //results[0] will contain value of doc.length from countQuery function
         //results[1] will contain doc of retrieveQuery function
         //You can send the results as

         res.json({users: results[1], pageLimit: PAGE_LIMIT, page: page, totalCount: results[0]});

    });

async 允许您根据所使用的硬件并行运行多个查询。这比使用 2 个独立查询来获取计数和获取所需文档要快。 希望这会有所帮助。

【讨论】:

    【解决方案3】:

    这些解决方案的问题在于,对于每个请求,您都会执行两个查询。当您拥有复杂的数据结构和大型数据集时,这会成为问题,因为性能会成为问题。考虑创建一个特殊函数来侦听/resource?count=true/resource/count GET 方法并仅返回计数。

    【讨论】:

      【解决方案4】:

      要只执行一个查询,您可以使用与 Promise 和数组切片相关联的 find() 方法。一个小例子是:

      getPaginated(query, skip, limit){
             return this.model.find(query)
                  .lean()
                  .then((value)=>{
                      if (value.length === 0) return {userMessage: 'Document not found'};
                      const count = value.length;
      
                      //skip===0 must be handled
                      const start = parseInt(limit)*parseInt(skip - 1);
                      const end = start + parseInt(reqQuery.pagesize);
      
                      //slicing the array
                      value = value.slice(start,end);
      
                      //could return it another way...
                      value.push( { 'querySize': count });
                      return value;
                    })
                    .catch((reason)=>{
                      //...handling code
                    });
                }
      

      【讨论】:

        【解决方案5】:

        我在 mongoose v3+ 中用$facetaggregate 解决了这个问题:

        const [{ paginatedResult, [{ totalCount }] }] = await Model.aggregate([{
          $facet: {
            paginatedResult: [
              { $match: query },
              { $skip: skip },
              { $limit: limit }
            ],
            totalCount: [
              { $match: query },
              { $count: 'totalCount' }
            ]
          }
        }])
        

        其中totalCount 是指与搜索查询匹配的记录总数,而paginatedResult 只是它们的分页切片。

        【讨论】:

        • 这个答案很好。但这是否会导致任何性能问题,因为我们再次对总计数进行匹配?
        • 嗯...很高兴知道在开箱即用的方面是否有任何优化。
        猜你喜欢
        • 2015-08-28
        • 1970-01-01
        • 1970-01-01
        • 2018-04-06
        • 1970-01-01
        • 1970-01-01
        • 2013-03-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多