node.jsmongodbexpressmongodb-query

MongoDB - How to get the id of the matched object from an array


How should I get the id of the matched object from an array? Currently, I am getting all the IDs from the pricing array.

While I just want the one that matches.

await Item.find(
   {_id: "663a4dbb97674691089c835a", pricing: {$elemMatch: {mrp: 100, price: 100}}}, 
   {"pricing._id": 1})

MongoDB Document:

{
  "_id": {
    "$oid": "663a4dbb97674691089c835a"
  },
  "desc": {
    "name": "BLA BLA",
  },
  "pricing": [
    {
      "firstAddedDate": "05/30/2024",
      "mrp": 100,
      "price": 100,
      "qty": 1,
      "_id": {
        "$oid": "66578e181df0f2a544263b2b"
      }
    },
    {
      "firstAddedDate": "05/30/2024",
      "mrp": 100,
      "price": 80,
      "qty": -1,
      "_id": {
        "$oid": "66580f3425b849794bb87bd7"
      }
    }
  ]
}

Result I want:

66578e181df0f2a544263b2b


Solution

  • Approach 1

    In the projection, you should use $filter operator to filter the matching element.

    let item = await Item.find({
      _id: new ObjectId("663a4dbb97674691089c835a"),
      pricing: {
        $elemMatch: {
          mrp: 100,
          price: 100
        }
      }
    },
    {
      "pricing": {
        $filter: {
          input: "$pricing",
          cond: {
            $and: [
              {
                $eq: [
                  "$$this.mrp",
                  100
                ]
              },
              {
                $eq: [
                  "$$this.price",
                  100
                ]
              }
            ]
          }
        }
      }
    });
    
    let matchedId = item?.pricing[0]._id;
    

    Demo Approach 1 @ Mongo Playground


    Approach 2

    You may work with $map to return the matched _id.

    let item = await Item.find({
      _id: new ObjectId("663a4dbb97674691089c835a"),
      pricing: {
        $elemMatch: {
          mrp: 100,
          price: 100
        }
      }
    },
    {
      "pricing": {
        $map: {
          input: {
            $filter: {
              input: "$pricing",
              cond: {
                $and: [
                  {
                    $eq: [
                      "$$this.mrp",
                      100
                    ]
                  },
                  {
                    $eq: [
                      "$$this.price",
                      100
                    ]
                  }
                ]
              }
            }
          },
          in: "$$this._id"
        }
      }
    });
    
    let matchedId = item?.pricing[0];
    

    Demo Approach 2 @ Mongo Playground


    Approach 3

    Work with pricing.$ to return first matching element.

    let item = await Item.find({
      _id: {
        "$oid": "663a4dbb97674691089c835a"
      },
      pricing: {
        $elemMatch: {
          mrp: 100,
          price: 100
        }
      }
    },
    {
      "pricing.$": 1
    });
    
    let matchedId = item?.pricing[0]._id;
    

    Demo Approach 3 @ Mongo Playground