Mongoose Constraint / Offset Request and Counter

A bit odd in query performance ... I need to run a query that runs the total number of documents, and can also return a result set that can be limited and biased.

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

I can think of two ways to do this, first a query for all 57 documents (returned as an array), and then using array.slice returns the documents they need. The second option is to run 2 queries, the first of which uses the count count mongo method, and then run the second query using mongo native $ limit and $ skip aggregators.

Which, in your opinion, will be better scaled? Doing all this in a single 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}); }); }); 
+61
mongodb mongoose
Dec 18 '12 at 15:03
source share
3 answers

I suggest you use 2 queries:

  • db.collection.count() will return the total number of elements. This value is stored somewhere in Mongo, and it is not calculated.

  • db.collection.find().skip(20).limit(10) Here I assume that you can use sorting by some field, so do not forget to add an index to this field. This request will also be quick.

I think that you do not have to request all the elements and skip and accept, because later, when you have big data, you will have problems with the transmission and processing of data.

+94
Mar 13 '13 at 14:02
source share

After I myself solved this problem, I would like to be based on the answer of user854301.

Mongoose ^ 4.13.8 I was able to use the toConstructor() function which allowed me to avoid multiple query building when applying filters. I know this feature is available in older versions too, but you will have to check Mongoose docs to confirm this.

The following uses the promises of 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 request will return the total number of records found, and the returned data will be a subset of the common records.

Note the () around query (), which creates the query.

+1
Jan 17 '18 at 0:31
source share

Instead of using 2 queries, use aggregate in one query

The "$ facet" collection can be obtained faster, the total amount and data with a pass and a limit

  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: [ {...}, {...} ] }] 
+1
Feb 15 '19 at 6:17
source share



All Articles