skip to Main Content

I have collection: bookSchema as:

[
    {
      _id: ObjectId("637d05dc32428ed75ea08d09"),
      book_details: {
        book_name: "random123",
        book_auth: "Amber"
      }
    },
    {
      _id: ObjectId("637d0673ce0f17f6c473dee2"),
      book_details: {
        book_name: "random321",
        book_auth: "Amber"
      }
    },
    {
      _id: ObjectId("637d069a3d597c8458ebe4ec"),
      book_details: {
        book_name: "random676",
        book_auth: "Amber"
      }
    },
    {
      _id: ObjectId("637d06c05b32d503007bcb54"),
      book_details: {
        book_name: "random999",
        book_auth: "Saurav"
      }
    }
  ]

Desired O/P to show as:

{
  score_ambr: 3,
  score_saurabh: 1
}

For this I tried as:

db.bookSchema.aggregate([
  {
    "$group": {
      "_id": {
        "$eq": [
          "$book_details.book_auth",
          "Amber"
        ]
      },
      "score_ambr": {
        "$sum": 1
      }
    },

  },
  {
    "$group": {
      "_id": {
        "$eq": [
          "$book_details.book_auth",
          "Saurav"
        ]
      },
      "score_saurabh": {
        "$sum": 1
      }
    },

  }
])

I tried using $group to as I want to group all the matching documents in one and use $count to give the number of count for the matching documents but it doesn’t seem to be working and gives the O/P as

O/P:

[
  {
    "_id": false,
    "score_sau": 2
  }
]

MongoDB Playground: https://mongoplayground.net/p/cZ64KwAmwlv

2

Answers


  1. It looks like what you want is two group twice and create a dynamic key from the book_details.book_auth:

    db.bookSchema.aggregate([
      {$group: {_id: "$book_details.book_auth", count: {$sum: 1}}},
      {$group: {
          _id: 0, 
          data: {$push: {
              k: {$concat: ["score_", {$toLower: "$_id"}]},
              v: {$sum: "$count"}
          }}
      }},
      {$replaceRoot: {newRoot: {$arrayToObject: "$data"}}}
    ])
    

    See how it works on the playground example

    Login or Signup to reply.
  2. I don’t know what mean 3 and 1 in your example but if I’ve understood correctly you can try this query:

    The trick here is to use $facet to create "two ways" in the aggregation. One option will filter by Amber and the other one by Saurav.

    And then, as values are filtered, you only need yo know the size of the array generated.

    db.collection.aggregate([
      {
        "$facet": {
          "score_ambr": [
            {
              "$match": {
                "book_details.book_auth": "Amber"
              }
            }
          ],
          "score_saurabh": [
            {
              "$match": {
                "book_details.book_auth": "Saurav"
              }
            }
          ]
        }
      },
      {
        "$project": {
          "score_ambr": {
            "$size": "$score_ambr"
          },
          "score_saurabh": {
            "$size": "$score_saurabh"
          }
        }
      }
    ])
    

    Example here

    Note that in this way you avoid to use $group.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search