Taha Farooqui
Taha Farooqui

Reputation: 747

Mongodb Pagination after aggregate

Note: The code is working properly but need to optimize the logic.

db.collection('cms_brands').aggregate([
  {
    $facet: {
      data: [{ $match: {title:"clue brand"} }, { $skip: 0 }, { $limit: 10 }],
      metadatax: [ { $count: "total" }, { $addFields: { page: 0 } }],
      metadata: [ { $match: {title:"clue brand"} }, { $skip: 0 }, { $limit: 10 }, {$group: { _id: "$title", count: { $sum: 1 } }} ],

    }
  }
]).toArray()
    .then((items) => { return { statusCode: 200, body: items }; })
    .catch(err => {
      console.log('=> an error occurred: ', err);
      return { statusCode: 500, body: 'error' };
    });

Actual response :

[
    {
      "data": [
        {
          "_id": "5e91d2c4a3fda138bcdbfd82",
          "title": "clue brand"
        },
        {
          "_id": "5e91d2dea3fda138bcdbfd83",
          "title": "clue brand"
        }
      ],
      "metadatax": [
        {
          "total": 3,
          "page": 0
        }
      ],
      "metadata": [
        {
          "_id": "clue brand",
          "count": 2
        }
      ]
    }
  ]

Expected response :

[
    {
      "data": [
        {
          "_id": "5e91d2c4a3fda138bcdbfd82",
          "title": "clue brand"
        },
        {
          "_id": "5e91d2dea3fda138bcdbfd83",
          "title": "clue brand"
        }
      ],
      "metadata": [
        {
          "total": 3,
          "page": 0,
          "_id": "clue brand",
          "count": 2
        }
      ]
    }
  ]

Upvotes: 1

Views: 2563

Answers (1)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

Reputation: 17915

You can change few things, try below query :

db.collection.aggregate([
  {
    $facet: {
      metadatax: [{ $count: "total" }, { $addFields: { page: 0 } }],
      metadata: [
        { $match: { title: "clue brand" } },
        { $skip: 0 },
        { $limit: 10 },
        {
          $group: {
            _id: "$title",
            count: { $sum: 1 },
            data: { $push: "$$ROOT" }
          }
        }
      ]
    }
  },
  { $unwind: "$metadata" },
  {
    $project: {
      data: "$metadata.data",
      metadata: {
        $mergeObjects: [
          { _id: "$metadata._id", count: "$metadata.count",total_pages: { $ceil: { $divide: [ { $arrayElemAt: [ "$metadatax.total",  0 ] } , 8 ] } } },
          { $arrayElemAt: ["$metadatax", 0] }
        ]
      }
    }
  }
]);

Test : MongoDB-Playground

Updates :

  1. You don't need this data: [{ $match: {title:"clue brand"} }, { $skip: 0 }, { $limit: 10 }] additional step in $facet, can be replaced with data: { $push: "$$ROOT" } in $group of metadata.
  2. Also as metadata will always be an array of single object - instead of being an array, I would suggest it to be an object for easy access in code. Just in case if you need it as an array all you need is to wrap $mergeObjects in array in $project.

Like this :

  metadata: [{
    $mergeObjects: [
      { _id: "$metadata._id", count: "$metadata.count" },
      { $arrayElemAt: ["$metadatax", 0] }
    ]
  }]

Upvotes: 2

Related Questions