Search code examples
javascriptmongodbmongoosemongodb-queryaggregation-framework

How to query an object inside an array by multiple value in mongoose (javascript)?


I have an object and the server will receive a user_id and a part_id. I need to get the certain user, then filter the parts by the provided part ID and get the price.

    {

       _id: 6086b8eec1f5325278846983,
       user_id: '13',
       car_name: 'Car name 1',
       created_at: 2008-11-25T00:46:52.000Z,
       parts: [
         {
           _id: 6086ee212681320190c3c8e0,
           part_id: 'P456',
           part_name: 'Part name 1',
           image: 'image url',
           stats: {
               price: 10,
           }
         },
         {
           _id: 6087e7795e2ca925fc6ead27,
           part_id: 'P905',
           part_name: 'Part name 2',
           image: 'image url',
           stats: {
               price: 15,
           }
         }
       ]
    }

I tried to run the following, but ignores the part_id filter and returns every parts in the array.

Customers.findOne({'user_id': '13', 'parts.part_id': 'P456'})

Also tried with aggregate but still no luck.

Customers.aggregate([
    { $match: { 'user_id': '13'}}
]).unwind('parts')

I checked the mongoose documentation but cannot wrap my head around it. Please let me know what I am missing.

Mongoose version: 5.12.4


Solution

  • Option - 1

    This will work if you've only 1 matching parts

    $ (projection)

    The $ operator projects the first matching array element from each document in a collection based on some condition from the query statement.

    Demo - https://mongoplayground.net/p/tgFL01fK3Te

    db.collection.find(
     { "user_id": "13", "parts.part_id": "P456" },
     { "parts.$": 1, car_name: 1 } // add fields you need to projection
    )
    

    Option -2

    $unwind

    Demo - https://mongoplayground.net/p/_PeP0WHVpJH

    db.collection.aggregate([
      {
        $match: {
          "user_id": "13",
          "parts.part_id": "P456"
        }
      },
      {
        $unwind: "$parts" //  break into individual documents
      },
      {
        $match: {
          "parts.part_id": "P456"
        }
      }
    ])