mongodb Mongoose 限制/偏移和计数查询

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13935733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:58:12  来源:igfitidea点击:

Mongoose limit/offset and count query

mongodbmongoose

提问by leepowell

Bit of an odd one on query performance... I need to run a query which does a total count of documents, and can also return a result set that can be limited and offset.

查询性能有点奇怪……我需要运行一个查询,它会计算文档总数,并且还可以返回一个可以限制和偏移的结果集。

So, I have 57 documents in total, and the user wants 10 documents offset by 20.

所以,我总共有 57 个文档,用户想要 10 个文档偏移 20。

I can think of 2 ways of doing this, first is query for all 57 documents (returned as an array), then using array.slice return the documents they want. The second option is to run 2 queries, the first one using mongo's native 'count' method, then run a second query using mongo's native $limit and $skip aggregators.

我可以想到两种方法,首先是查询所有 57 个文档(作为数组返回),然后使用 array.slice 返回他们想要的文档。第二个选项是运行 2 个查询,第一个使用 mongo 的本机 'count' 方法,然后使用 mongo 的本机 $limit 和 $skip 聚合器运行第二个查询。

Which do you think would scale better? Doing it all in one query, or running two separate ones?

你认为哪个会更好地扩展?在一个查询中完成所有操作,还是运行两个单独的查询?

Edit:

编辑:

// 1 query
var limit = 10;
var offset = 20;

Animals.find({}, function (err, animals) {
    if (err) {
        return next(err);
    }

    res.send({count: animals.length, animals: animals.slice(offset, limit + offset)});
});


// 2 queries
Animals.find({}, {limit:10, skip:20} function (err, animals) {            
    if (err) {
        return next(err);
    }

    Animals.count({}, function (err, count) {
        if (err) {
            return next(err);
        }

        res.send({count: count, animals: animals});
    });
});

回答by user854301

I suggest you to use 2 queries:

我建议您使用 2 个查询:

  1. db.collection.count()will return total number of items. This value is stored somewhere in Mongo and it is not calculated.

  2. db.collection.find().skip(20).limit(10)here I assume you could use a sort by some field, so do not forget to add an index on this field. This query will be fast too.

  1. db.collection.count()将返回项目总数。这个值存储在 Mongo 的某个地方,它没有被计算出来。

  2. db.collection.find().skip(20).limit(10)在这里,我假设您可以按某个字段使用排序,所以不要忘记在该字段上添加索引。这个查询也会很快。

I think that you shouldn't query all items and than perform skip and take, cause later when you have big data you will have problems with data transferring and processing.

我认为您不应该查询所有项目而不是执行跳过和获取,因为以后当您拥有大数据时,您将在数据传输和处理方面遇到问题。

回答by DhineshYes

Instead of using 2 queries, use aggregate in a single query

不要使用 2 个查询,而是在单个查询中使用聚合

Aggregate "$facet"can be fetch more quickly, the Total Countand the Data with skip & limit

聚合“$facet”可以更快地获取,总计数带有跳过和限制数据

    db.collection.aggregate([

      //{$sort: {...}}

      //{$match:{...}}

      {$facet:{

        "stage1" : [ $group:{_id:null, count:{$sum:1}} ],

        "stage2" : [ { "$skip": 0}, {"$limit": 2} ]

      }},


     {$unwind: "$stage1"},

      //output projection
     {$project:{
        count: "$stage1.count",
        data: "$stage2"
     }}

 ]);

output as follows:-

输出如下:-

[{
     count: 50,
     data: [
        {...},
        {...}
      ]
 }]

回答by oli_taz

After having to tackle this issue myself, I would like to build upon user854301's answer.

在不得不自己解决这个问题之后,我想以 user854301 的回答为基础。

Mongoose ^4.13.8 I was able to use a function called toConstructor()which allowed me to avoid building the query multiple times when filters are applied. I know this function is available in older versions too but you'll have to check the Mongoose docs to confirm this.

Mongoose ^4.13.8 我能够使用一个被调用的函数toConstructor(),它允许我在应用过滤器时避免多次构建查询。我知道此功能在旧版本中也可用,但您必须检查 Mongoose 文档以确认这一点。

The following uses Bluebird promises:

以下使用 Bluebird 承诺:

let schema = Query.find({ name: 'bloggs', age: { $gt: 30 } });

// save the query as a 'template'
let query = schema.toConstructor();

return Promise.join(
    schema.count().exec(),
    query().limit(limit).skip(skip).exec(),

    function (total, data) {
        return { data: data, total: total }
    }
);

Now the count query will return the total records it matched and the data returned will be a subset of the total records.

现在计数查询将返回它匹配的总记录,返回的数据将是总记录的一个子集。

Please note the ()around query() which constructs the query.

请注意构造查询的 query ()周围的 ()。

回答by Dev01

There is a library that will do all of this for you, check out mongoose-paginate-v2

有一个库可以为您完成所有这些工作,请查看mongoose-paginate-v2