Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb Aggregate using $group twice

Tags:

mongodb

meteor

I have a bunch of documents in mongo with the following structure:

{
    "_id" : "",
    "number" : 2,
    "colour" : {
        "_id" : "",
        "name" : "Green",
        "hex" : "00ff00"
    },
    "position" : {
        "_id" : "",
        "name" : "Defence",
        "type" : "position"
    },
    "ageGroup" : {
        "_id" : "",
        "name" : "Minor Peewee",
        "type" : "age"
    },
    "companyId" : ""
}

I'm currently using Mongo's aggregate to group the documents by ageGroup.name which returns:

//Query
Jerseys.aggregate([
  {$match: { companyId: { $in: companyId } } },
  {$group: {_id: "$ageGroup.name", jerseys: { $push: "$$ROOT" }} }
]);

//returns
{
   _id: "Minor Peewee",
   jerseys: array[]
}

but I'd like it to also group by position.name within the age groups. ie:

{
  _id: "Minor Peewee",
  positions: array[]
}
//in positions array...
{
  _id: "Defence",
  jerseys: array[]
}
// or ageGroups->positions->jerseys if that makes more sense.

I've tried multiple groups but I don't think I'm setting them up correctly I always seem to get an array of _id's. I'm using Meteor as the server and I'm doing it within a meteor method.

like image 591
wiz Avatar asked Feb 07 '23 01:02

wiz


1 Answers

You can use a composite aggregate _id in the first grouping stage.

Then, you can use one of those keys as the "main" _id of the final aggregate and $push the other into another array.

Jerseys.aggregate([
  {
    $match: { companyId: { $in: companyId } } 
  },
  { 
    $group: { // each position and age group have an array of jerseys
      _id:   { position: "$position", ageGroup: "$ageGroup" }, 
      jerseys: { $push: "$$ROOT" } 
    } 
  }, 
  { 
    $group: { // for each age group, create an array of positions
      _id: { ageGroup: "$_id.ageGroup" }, 
      positions: { $push: { position: "$_id.position", jerseys:"$jerseys" } } 
    } 
  } 
]);
like image 193
MasterAM Avatar answered Apr 20 '23 17:04

MasterAM