Nani
Nani

Reputation: 446

add new field in mongoDB projections

I have a mongo collection (store details) like below...

{
    _id: "",
    storeName: "store1",
    items: [
        {
            itemName: "mongo",
            itemPrice: 20,
            itemAvailablity: 100 
        },
        {
            itemName: "apples",
            itemPrice: 50,
            itemAvailablity: 70 
        }
    ]
},
{
    _id: "",
    storeName: "store2",
    items: [
        {
            itemName: "banana",
            itemPrice: 10,
            itemAvailablity: 30 
        },
        {
            itemName: "apple",
            itemPrice: 45,
            itemAvailablity: 90 
        }
    ]
},
{
    _id: "",
    storeName: "store3",
    items: [
        {
            itemName: "apple",
            itemPrice: 10,
            itemAvailablity: 30 
        },
        {
            itemName: "mongo",
            itemPrice: 30,
            itemAvailablity: 50 
        }
    ]
}

from the above data, I want to get particular item details along with storeName.

If I want to get "mongo" details from all stores then my expected output will be like

[
    {
        itemName: "mongo",
        itemPrice: 20,
        itemAvailablity: 100,
        storeName: "store1"
    },
    {
        itemName: "mongo",
        itemPrice: 30,
        itemAvailablity: 50,
        storeName: "store3" 
    }
]

I try with different mongo aggregation queries but I didn't get the output as I expect

can anyone help me out of this

thank you

Upvotes: 2

Views: 2254

Answers (3)

Rubin Porwal
Rubin Porwal

Reputation: 3845

  db.collection.aggregate(

        // Pipeline
        [
            // Stage 1
            {
                $match: {
                    items: {
                        $elemMatch: {
                            "itemName": "mongo"
                        }
                    }
                }
            },

            // Stage 2
            {
                $project: {
                    items: {
                        $filter: {
                            input: "$items",
                            as: "item",
                            cond: {
                                $eq: ["$$item.itemName", 'mongo']
                            }
                        }
                    },

                    storeName: 1

                }
            },

            // Stage 3
            {
                $addFields: {
                    "items.storeName": '$storeName'
                }
            },

        ]



    );

Upvotes: 0

Ashh
Ashh

Reputation: 46471

You can use below aggregation

db.collection.aggregate([
  { "$match": { "items.itemName": "mongo" }},
  { "$unwind": "$items" },
  { "$match": { "items.itemName": "mongo" }},
  { "$addFields": { "items.storeName": "$storeName" }},
  { "$replaceRoot": { "newRoot": "$items" }}
])

MongoPlayground

Or either you can do this way

db.collection.aggregate([
  { "$match": { "items.itemName": "mongo" }},
  { "$addFields": {
    "items": {
      "$map": {
        "input": {
          "$filter": {
            "input": "$items",
            "as": "item",
            "cond": { "$eq": ["$$item.itemName", "mongo"]}
          }
        },
        "as": "item",
        "in": { "$mergeObjects": ["$$item", { "storeName": "$storeName" }] }
      }
    }
  }},
  { "$unwind": "$items" },
  { "$replaceRoot": { "newRoot": "$items" }}
])

MongoPlayground

Upvotes: 3

Akrion
Akrion

Reputation: 18525

You can achieve this via this aggregation:

db.collection.aggregate([
  {
    $project: {
      storeName: "$$CURRENT.storeName",
      items: {
        $filter: {
          input: "$items",
          as: "item",
          cond: { $eq: ["$$item.itemName","mongo"] }
        }
      }
    }
  },
  { $unwind: "$items" },
  { $addFields: { "items.storeName": "$storeName"} },
  { $replaceRoot: { newRoot: "$items" }}
])

You can see it working here

Upvotes: 3

Related Questions