mongodbmongodb-querymongodb-compasstornado-motor

MongoDB: How to filter nested array of objects


The following are my two entries in my collection

{
'_id': ObjectId('6287443338ed135a9e0b1b9d'),
 'data': [{'pChange': 166.9602348545503, 'strikePrice': 34000},
          {'pChange': -55.820553402827045, 'strikePrice': 34000},
          {'pChange': -60.35031847133758, 'strikePrice': 33600},
          {'pChange': -49.24757466962035, 'strikePrice': 34500}],
 'timestamp': '20-May-2022 13:01:59'
},
{
  '_id': ObjectId('7287443338ed13532e0b1b4y'),
  data': [{'pChange': 24.8545503, 'strikePrice': 34000},
          {'pChange': -51.827045, 'strikePrice': 34100},
          {'pChange': -20.133758, 'strikePrice': 33900},
          {'pChange': -40.57962035, 'strikePrice': 33500}],
  timestamp': '20-May-2022 13:02:45'
},

I want all the entries with their strike price = 34000.

Expected Result:

{
    '_id': ObjectId('6287443338ed135a9e0b1b9d'),
     'data': [{'pChange': 166.9602348545503, 'strikePrice': 34000},
              {'pChange': -55.820553402827045, 'strikePrice': 34000},],
     'timestamp': '20-May-2022 13:01:59'
},
{
  '_id': ObjectId('7287443338ed13532e0b1b4y'),
  data': [{'pChange': 24.8545503, 'strikePrice': 34000}}],
  timestamp': '20-May-2022 13:02:45'
},

Solution

  • Use $unwind to get every array element into its own document. We can then use $match to filter by strkePrice. In the end we $group to re-assemble the array.

    db.collection.aggregate({
      $unwind: "$data"
    },
    {
      $match: {
        "data.strikePrice": 34000
      }
    },
    {
      $group: {
        _id: "$_id",
        data: {
          $push: "$data"
        }
      }
    })
    

    Playground