hitchhiker
hitchhiker

Reputation: 1319

How to count number of root documents in intermediate aggregate stage in mongo?

I want to implement pagination on a website and I'd like my mongodb query to return first perform the lookup between 2 collections, sort the documents, calculate the total number of documents and then return the relevant documents after $skip and $limit stages in the aggregation. This is my query:

const res = await Product.aggregate([
  {
    $lookup: {
      from: 'Brand',
      localField: 'a',
      foreignField: 'b',
      as: 'brand'
    }
  },
  {
    $sort: {
      c: 1,
      'brand.d': -1
    }
  },
  {
    $skip: offset
  },
  {
    $limit: productsPerPage
  }
])

I don't want to make 2 queries which are essentially the same only for the first one to return the count of documents and for the other to return the documents themselves.

So the result would be something like this:

{
  documents: [...],
  totalMatchedDocumentsCount: x
}

such that there will be for example 10 documents but totalMatchedDocumentsCount may be 500.

I can't figure out how to do this, I don't see that aggregate method returns cursor. Is it possible to achieve what I want in one query?

Upvotes: 1

Views: 593

Answers (1)

mickl
mickl

Reputation: 49945

You need $facet and you can run your pipeline with $limit and $skip as one subpipeline while $count can be used simultaneously:

const res = await Product.aggregate([
    // $match here if needed
    {
        $facet: {
            documents: [
                {
                    $lookup: {
                    from: 'Brand',
                    localField: 'a',
                    foreignField: 'b',
                    as: 'brand'
                    }
                },
                {
                    $sort: {
                    c: 1,
                    'brand.d': -1
                    }
                },
                {
                    $skip: offset
                },
                {
                    $limit: productsPerPage
                }
            ],
            total: [
                { $count: "count" }
            ]
        }
    },
    {
        $unwind: "$total"
    }
])

Upvotes: 2

Related Questions