Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get count before limit in the Mongo aggregation pipeline

In the following query:

db.orders.aggregate([{ $match : { status: "A"}, { $limit: 5} }]);

How can I get the count of documents after the $match but before the $limit is applied?

I still want to return an array of 5 documents. But if I use $group it seems that it would not preserve the array of documents. Can this be done in one call, or do I have to make two calls?

like image 389
zenibeat Avatar asked Sep 18 '14 16:09

zenibeat


People also ask

Can we use count with aggregate function in MongoDB?

MongoDB $count AggregationThe MongoDB $count operator allows us to pass a document to the next phase of the aggregation pipeline that contains a count of the documents. There a couple of important things to note about this syntax: First, we invoke the $count operator and then specify the string.

How do you count aggregates?

Returns as a BIGINT the number of rows in each group where the expression is not NULL . If the query has no GROUP BY clause, COUNT returns the number of table rows. The COUNT aggregate function differs from the COUNT analytic function, which returns the number over a group of rows within a window.

How do you use limits in aggregation?

Answer: $skip before $limit In aggregate, $limit limits the number of documents sent to the next aggregation state, and $skip skips the first N documents, so if $skip is after $limit and $skip >= $limit, you won't get any results.


3 Answers

Starting in Mongo 3.4, the $facet aggregation stage allows processing multiple aggregation pipelines within a single stage on the same set of input documents:

// { "status" : "A", "v" : 3 }
// { "status" : "B", "v" : 14 }
// { "status" : "A", "v" : 7 }
// { "status" : "A", "v" : 5 }
db.collection.aggregate(
  { $match: { status: "A"} },
  { $facet: {
      count:  [{ $count: "count" }],
      sample: [{ $limit: 2 }]
  }}
)
// {
//   "count" : [ { "count" : 3 } ],
//   "sample" : [ { "status" : "A", "v" : 3 }, { "status" : "A", "v" : 7 } ]
// }

This:

  • starts by matching documents whose status is A.

  • and then produces via a $facet stage two fields that out of two distinct aggregation pipelines:

    • $count that simply provides the number of documents resulting from the preceding $match stage.

    • sample that is a $limited extract of documents resulting from the preceding $match stage.

like image 127
Xavier Guihot Avatar answered Oct 23 '22 03:10

Xavier Guihot


Unfortunately, right now you have to make two calls, one call with the $limit operator for your results followed by a second call for the count. You could use the aggregation framework without the $limit operator and with a $group operator to calculate a count or as wdberkeley points out you can pass your criteria to .count() to get a count instead of using the aggregation framework if you are using a single match stage.

See MongoDB - Aggregation Framework (Total Count).

like image 41
Brantino Avatar answered Oct 23 '22 02:10

Brantino


This can now be done in one call as of version 3.4 with the $facet aggregation. See here for an example: Mongo aggregation with paginated data and totals

like image 4
TylerFowler Avatar answered Oct 23 '22 04:10

TylerFowler