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
Mongoose limit/offset and count query
提问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 个查询:
db.collection.count()
will return total number of items. This value is stored somewhere in Mongo and it is not calculated.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.
db.collection.count()
将返回项目总数。这个值存储在 Mongo 的某个地方,它没有被计算出来。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