Dave Wicomo
Dave Wicomo

Reputation: 163

Aggreggate - map though object keys that values are arrays

guys.

I can't figure it out how to map though object keys that values are arrays. I tried something with $map but that seems to iterate though array itself, which is not my case.

Document looks like this:

{     
    id: 1234,     
    name: 'Random',     
    subjects: {        
         math: [5,4,3],         
        biology: [3,3,3]     
    } 
} 

I need to make query that return average of each subject, for above code should be mathAvg: 4, biologyAvg: 3

Desired output:

{     
    id: 1234,     
    name: 'Random',     
    subjects: {        
         math: [5,4,3],         
        biology: [3,3,3]     
    },
    mathAvg: 4,
    biology: 3

} 

I figured out how to make for one subject, but cant iterate though subjects to make this operation for many.

For each subject:

db.students.aggregate([{$match: {id: 1234}}, {$addFields: {mathAvg:{$avg:`$subjects.math`}}}])

Upvotes: 1

Views: 100

Answers (2)

simagix
simagix

Reputation: 1922

Simpler pipeline with exact expected output.

db.collection.aggregate([
    {
        '$project': {
            'name': 1, 
            'subjects': 1, 
            'mathAvg': {
                '$avg': '$subjects.math'
            }, 
            'biology': {
                '$avg': '$subjects.biology'
            }
        }
    }
])

Upvotes: 0

Ashh
Ashh

Reputation: 46481

You can use below aggregation

db.collection.aggregate([
  { "$addFields": {
    "subjectsAvg": {
      "$arrayToObject": {
        "$map": {
          "input": { "$objectToArray": "$subjects" },
          "as": "a",
          "in": {
            "k": "$$a.k",
            "v": { "$avg": "$$a.v" }
          }
        }
      }
    }
  }}
])

Upvotes: 1

Related Questions