Home > Mobile >  Mongodb aggregation to pass both a matched array and an unmatched array
Mongodb aggregation to pass both a matched array and an unmatched array

Time:08-04

I've got a MongoDB / Nodes aggregation that looks a little like this (there are other values in there, but this is the basic idea).

            [
            {
            '$unwind': {
                'path': '$Vehicles'
                }
            },
            {
            '$match': {
                'Vehicles.Manufacturer': 'FORD'
                }
            },
            {
            '$facet': {
                'makes': [
                        {
                    '$group': {
                    '_id': '$Vehicles.Manufacturer', 
                    'count': {
                        '$sum': 1
                                }
                            }
                        }
                    ]
                }
            },
            {
            '$project': {
                'makes': {
                '$sortArray': {
                    'input': '$makes', 
                    'sortBy': 1
                        }
                    }
                }
            }
        ]

This works fine. But I would also like to pass an unmatched list through. IE an an array of vehicles whose Manufacturer = FORD and an other list of all Manufacturer.

Can't get it to work. Any ideas please?

Thanks in advance.

Edit:-

The current output looks like this:

      [{
    "makes": [
      {
        "_id": "FORD",
        "count": 285
      }
    ]
  }]

and ideally it would look something like this:

      [{
    "makes": [
      {
        "_id": "FORD",
        "count": 285
      }
    ],
    "unfiltered_makes": [
      {
        "_id": "ABARTH",
        "count": 1
      },
      {
        "_id": "AUDI",
        "count": 7
      },
      {
        "_id": "BMW",
        "count": 2
      },
      {
        "_id": "CITROEN",
        "count": 4
      },
      {
        "_id": "DS",
        "count": 1
      },
      {
        "_id": "FIAT",
        "count": 1
      }.... etc
    ]
  }]

The data looks a bit like this:

"Vehicles": [
{
  "Id": 1404908,
  "Manufacturer": "MG",
  "Model": "3",
  "Price": 11995 .... etc
},{
  "Id": 1404909,
  "Manufacturer": "FORD",
  "ManufacturerId": 34,
  "Model": "Focus",
  "Price": 12000 .... etc
} ... etc
]

CodePudding user response:

In this case you can do something like:

db.collection.aggregate([
  {$unwind: "$Vehicles"},
  {$group: {
      _id: "$Vehicles.Manufacturer",
      count: {$sum: 1}}
  },
  {$facet: {
      makes: [{$match: {_id: "FORD"}}],
      unfiltered_makes: [{$group: {_id: 0, data: {$push: "$$ROOT"}}}]
    }
  },
  {$project: {makes: 1, unfiltered_makes: "$unfiltered_makes.data"}}
])

See how it works on the playground example

Another option is:

db.collection.aggregate([
  {$unwind: "$Vehicles"},
  {$group: {
      _id: "$Vehicles.Manufacturer",
      count: {$sum: 1}}
  },
  {$group: {
      _id: 0,
      unfiltered_makes: {$push: "$$ROOT"},
      makes: {$push: {$cond: [{$eq: ["$_id", "FORD"]}, "$$ROOT", "$$REMOVE"]}}
    }
  }
])

See how it works on the playground example

  • Related