Home > other >  Select specific fields from a specific element of array by $elemMatch
Select specific fields from a specific element of array by $elemMatch

Time:09-16

I want to select some specific fields from a particular object in a nested array, achieved through mongoose/mongo.

Playground Link

Consider the data:

[
  {
    "_id": ObjectId("5ff4b728b6af610f0851d2a6"),
    "totalScore": 500,
    "totalCompleted": 100,
    "monthly": [
      {
        year: 2021,
        month: 8,
        attempted: 10,
        completed: 5,
        score: 20,
        
      }
    ],
    
  },
]

I want to first get all the documents, and then inside the "monthly", I want to select only the ones which match month = 8, and return only the "score" field and ignore rest of the fields like "attempted", "completed", etc.

I have tried the following query so far:

db.collection.find({},
{
  totalScore: 1,
  "monthly": {
    $elemMatch: {
      year: 2021,
      month: 8,
      
    },
    
  },
  
})

It returns all the keys of the entire "monthly" object. Like so:

[
  {
    "_id": ObjectId("5ff4b728b6af610f0851d2a6"),
    "monthly": [
      {
        "attempted": 10,
        "completed": 5,
        "month": 8,
        "score": 20,
        "year": 2021
      }
    ],
    "totalScore": 500
  },
]

But, what I want, is to only select the "score" field from the "monthly". So the result data would be:

[
  {
    "_id": ObjectId("5ff4b728b6af610f0851d2a6"),
    "monthly": [
      {
        "score": 20,
      }
    ],
    "totalScore": 500
  },

How should I approach this problem?

CodePudding user response:

This can be done with a simple aggregation using $map and $filter:

db.collection.aggregate([
  {
    $project: {
      totalScore: 1,
      monthly: {
        $map: {
          input: {
            $filter: {
              input: "$monthly",
              as: "item",
              cond: {
                $eq: [
                  "$$item.month",
                  8
                ]
              }
            }
          },
          as: "item",
          in: {
            score: "$$item.score"
          }
        }
      }
    }        
  }      
])

Example on mongoplayground: https://mongoplayground.net/p/5PbR49Ufxb5

  • Related