[SERVER-30918] $sum and $avg Accumulators return null when only one document in $group Created: 01/Sep/17  Updated: 05/Sep/17  Resolved: 05/Sep/17

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: 3.4.7, 3.5.11, 3.5.12
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Neil Lunn Assignee: Kelsey Schubert
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
Operating System: ALL
Steps To Reproduce:

Using the standard dataset https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json

This works as expected:

db.restaurants.aggregate([
  { '$group': {
    '_id': '$cusine',
    'avg': {
      '$avg': {
        '$avg': {
          '$map': {
            'input': {
              '$filter': {
                'input': '$grades', 
                'as': 'g',
                'cond': { '$eq': [ '$$g.grade',  'A' ] }
              }
            },
            'as': 'g',
            'in': '$$g.score'
          }
        }
      }
    }
  }},
  { "$sort": { "avg": 1 } }
])

But this returns null values

db.restaurants.aggregate([
  { '$group': {
    '_id': '$_id',
    'avg': {
      '$avg': {
        '$avg': {
          '$map': {
            'input': {
              '$filter': {
                'input': '$grades', 
                'as': 'g',
                'cond': { '$eq': [ '$$g.grade',  'A' ] }
              }
            },
            'as': 'g',
            'in': '$$g.score'
          }
        }
      }
    }
  }},
  { "$sort": { "avg": 1 } }
])
 

And even in the simplified case

db.restaurants.aggregate([
  { '$group': {
    '_id': '$_id',
    'avg': {
      '$avg': {
        '$avg': "$grades.score"
      }
    }
  }},
  { "$sort": { "avg": 1 } }
])

Participants:

 Description   

Both $sum and $avg are meant to act both as accumulators with $group as well as working with a provided array. A common usage would be to $filter array content and feed that to $avg to obtain the average for the array in the document and then "accumulate" those values with another $avg in a $group pipeline.

When used in the style of:

result: {
  $avg: {
    $avg: '$values'
  }
}

This works as expected when the _id provided to $group accumulates more than one document. However if the provided property does not accumulate over more than one document, the value is returned as null.

This affects both $avg and $sum when applied as both accumulator and array reducer.



 Comments   
Comment by Kelsey Schubert [ 05/Sep/17 ]

Thanks for the follow-up, neillunn.

Comment by Neil Lunn [ 03/Sep/17 ]

False report. On further investigation all null values are actually from empty arrays and null would be expected

Generated at Thu Feb 08 04:25:26 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.