Home > Enterprise >  Mongodb query to get count of field based on the value
Mongodb query to get count of field based on the value

Time:03-28

I have the following Mongodb document.

{
  "_id" : ObjectId("62406bfaa1d66f8d99c6e97d"),
  "skill": "Programming Language"
  "supply" : [
    {
        "employeeName" : "A1",
        "avgSkillRating" : 3
    }, 
    {
        "employeeName" : "A2",
        "avgSkillRating" : 4
    }, 
    {
        "employeeName" : "A3",
        "avgSkillRating" : 4
    }, 
    {
        "employeeName" : "A4",
        "avgSkillRating" : 4
    }, 
    {
        "employeeName" : "A5",
        "avgSkillRating" : 3
    }, 
    {
        "employeeName" : "A6",
        "avgSkillRating" : 4
    }, 
    {
        "employeeName" : "A7",
        "avgSkillRating" : 2
    }, 
    {
        "employeeName" : "A8",
        "avgSkillRating" : 2
    }, 
    {
        "employeeName" : "A9",
        "avgSkillRating" : 4
    }, 
    {
        "employeeName" : "A10",
        "avgSkillRating" : 3
    }, 
    {
        "employeeName" : "A11",
        "avgSkillRating" : 3
    }, 
    {
        "employeeName" : "A12",
        "avgSkillRating" : 3
    }, 
    {
        "employeeName" : "A13",
        "avgSkillRating" : 2
    }, 
    {
        "employeeName" : "A14",
        "avgSkillRating" : 4
    }, 
    {
        "employeeName" : "A15",
        "avgSkillRating" : 4
    }
  ]
}

How can I write a Mongodb query to produce the following output.

{
  skillName : "Programming Language",
  skillRating1: 0,  <-- Count of avgSkillRating with value 1
  skillRating2: 3,  <-- Count of avgSkillRating with value 2
  skillRating3: 5,  <-- Count of avgSkillRating with value 3
  skillRating4: 7,  <-- Count of avgSkillRating with value 4
  skillRating5: 0  <-- Count of avgSkillRating with value 5
}

[Note: I am learning to write Mongodb queries]

CodePudding user response:

You can go with aggregation,

  • $unwind to deconstruct the array
  • $group to get the sum of avg by _id and the avg
  • $arrayToObject to make the field to object with the help of $concat. Because we need the skillRating1,skillRating2...
  • $replaceRoot to get the object to root document
  • $project to decide whether to show or not

Here is the code,

db.collection.aggregate([
  { "$unwind": "$supply" },
  {
    "$group": {
      "_id": { _id: "$_id", avg: "$supply.avgSkillRating" },
      "count": { "$sum": 1 },
      "skill": { "$first": "$skill" }
    }
  },
  {
    "$group": {
      "_id": "$_id._id",
      "skill": { "$first": "$skill" },
      "data": {
        $push: {
          k: {
            $concat: [ "avgSkillRating", { $toString: "$_id.avg" } ]
          },
          v: "$count"
        }
      }
    }
  },
  { "$addFields": { "data": { "$arrayToObject": "$data" } } },
  {
    "$replaceRoot": {
      "newRoot": { "$mergeObjects": [ "$$ROOT", "$data" ] }
    }
  },
  { "$project": { data: 0 } }
])

Working Mongo playground

CodePudding user response:

Maybe something like this:

db.collection.aggregate([
{
  $unwind: "$supply"
},
{
  $group: {
  _id: "$supply.avgSkillRating",
  cnt: {
    $push: "$supply.avgSkillRating"
  },
  skill: {
    $first: "$skill"
  }
 }
},
{
  $project: {
  z: [
    {
      "k": {
        "$concat": [
          "avgSkillRating",
          {
            $toString: "$_id"
          }
        ]
      },
      "v": {
        $size: "$cnt"
      }
    }
  ],
  skill: 1
 }
 },
 {
  $replaceRoot: {
    newRoot: {
      "$mergeObjects": [
      {
        "$arrayToObject": "$z"
      },
      {
        skillName: "$skill"
      }
     ]
    }
  }
},
{
$group: {
  _id: "$skillName",
  x: {
    $push: "$$ROOT"
  }
 }
},
{
  "$replaceRoot": {
    "newRoot": {"$mergeObjects": "$x"}
  }
 }
])

Explained:

  1. Unwind the supply array
  2. group avgSkillRating to array cnt ( to be possible to count )
  3. form z array with k,v suitable for arrayToObject
  4. mergeObjects to form the keys and values
  5. group to join the objects and leave only single skillName
  6. replace the root document with the newly formed document with the necesary details.

playground

  • Related