Aggregation help please


#1

I’ve never done aggregations before, and I need some help. I’m planning to use the meteorhacks:aggregations package. I have a collection of Regions (5 in total), and each region has a lot of snow_load_factors. Following is some truncated code from my insert file.

Regions.insert({name: "My Region #1",
                ... 
                snow_load_factors: {
                   ...
                   levels: [
                      { year: new Date(1941,0,1), roof: 'standard', importance: 'all', pitch: 0, factor: 1.92 },
                         ... factors for every 5 degrees of pitch ...
                      { year: new Date(1941,0,1), roof: 'standard', importance: 'all', pitch: 90, factor: 0.00 },
                      { year: new Date(1941,0,1), roof: 'slippery', importance: 'all', pitch: 0, factor: 1.92 },
                          ... factors for every 5 degrees of pitch ...
                      { year: new Date(1941,0,1), roof: 'slippery', importance: 'all', pitch: 90, factor: 0.00 },
                      { year: new Date(1953,0,1), roof: 'standard', importance: 'all', pitch: 0, factor: 1.92 },
                         ... factors for every 5 degrees of pitch ...
                      { year: new Date(1953,0,1), roof: 'standard', importance: 'all', pitch: 90, factor: 0.00 },
                      { year: new Date(1953,0,1), roof: 'slippery', importance: 'all', pitch: 0, factor: 1.92 },
                          ... factors for every 5 degrees of pitch ...
                      { year: new Date(1953,0,1), roof: 'slippery', importance: 'all', pitch: 90, factor: 0.00 }, 
                   ]
                }
               });

I need to know the min, max and mean (average) of the factors in a region, grouped by roof and pitch

I know the final result won’t look like the following array, but it shows what I need:

[
  My Region #1 slippery and 0: {min: 0.00, max: 1.92, avg: 0.82},
  My Region #1 slippery and 5: {min: 0.00, max: 1.90, avg: 1.43},
  ....
  My Region #1 standard and 0: {min: 0.00, max: 1.92, avg: 0.82},
  My Region #1 standard and 5: {min: 0.00, max: 1.90, avg: 1.43},
  ....
  My Region #2 slippery and 0: {min: 0.00, max: 1.89, avg: 0.82},
  My Region #2 slippery and 5: {min: 0.00, max: 1.70, avg: 1.36},
  ....
  My Region #2 standard and 0: {min: 0.00, max: 1.88, avg: 0.81},
  My Region #2 standard and 5: {min: 0.00, max: 1.23, avg: 0.65},
  ....
]

#2

You need to use the Mongo API directly using Collection.rawCollection(). You can use all aggregation functions including min, max from mongo’s aggregate pipeline api.
https://docs.mongodb.com/manual/core/aggregation-pipeline/

But you need to be careful on dealing with the mongo API. There is a known issue with meteor Id conflicting with how mongo outputs some cases of aggregate.
See here my example of how I got aggregation working:

Hope that helps.


#3

Hey @sidae,

Try this reactive aggregation package. I’ve used it and it works perfectly on my app.

Here’s a blog post demonstrating this package.

Hope this helps.


#4

Are you maybe looking for a bit of code to get you started?

The aggregation pipeline in a sequence of operations, defined as objects in an array. Each object contains one pipeline operation and the array is processed in sequence with documents being “piped” out of one operation and into the next. Sometimes, more documents come out of an operation than went in ($unwind is an example).

The basic pipeline for your example would be:

[
  {
    $match: {}
  },
  {
    $unwind: '$snow_load_factors.levels',
  },
  {
    $group: {
      _id: {
        name: '$name',
        roof: '$snow_load_factors.levels.roof',
        pitch: '$snow_load_factors.levels.pitch'
      },
      min: { $min: '$snow_load_factors.levels.factor' },
      max: { $max: '$snow_load_factors.levels.factor' },
      avg: { $avg: '$snow_load_factors.levels.factor' },
    }
  }
]

HTH :slight_smile: