Home > Blockchain >  Mongodb : Loop through array and update object field using ObjectId
Mongodb : Loop through array and update object field using ObjectId

Time:12-08

in the following example I have a company named Colors Company that owns many shops

{
    _id: ObjectId("78391283"),
    name: "Colors company",
    shops: [
        {shopID: ObjectId("123456a1cb"), income: 0},
        {shopID: ObjectId("2a1cb67890"), income: 0},
        {shopID: ObjectId("2a1cb010111"), income: 0},
        ...
      ],
}

I need to : 1- Loop on the shops array, find the requested array using {parsedBody.shopID} 2- Get use of the amount stored in “shop.$.income” as a number 2- Increase the income using {parsedBody.amountToAdd}

This is the POST request parsedBody :

{
    companyID: "78391283",
    shopID: "123456a1cb",
    amountToAdd: 200,
}

I’m using Next js 13.

Thanks for your help !

What i’ve tried :

const ObjectId = require("mongoose").Types.ObjectId;

Shops.findOneAndUpdate(
    { _id: parsedBody.shopID},
    {
        set: {
        // <-- missing loop here
        "shops.$.income": { parsedBody.amountToAdd   income }
        }
    }
)

I am expecting to loop through the shops array and update the income field.

CodePudding user response:

Option 1: This seems to be an easy option mongoDB 3.6

db.collection.update({},
{
 "$inc": {
"shops.$[x].income": 200
}
},
{
 arrayFilters: [
  {
   "x.shopID": 2
  }
 ]
})

Playground1


Option 2: Using update/aggregation mongoDB 4.2

 db.collection.update({},
 [
 {
 $addFields: {
  shops: {
    "$map": {
      "input": "$shops",
      "as": "s",
      "in": {
        "$cond": {
          "if": {
            $eq: [
              "$$s.shopID",
              2
            ]
          },
          "then": {
            $mergeObjects: [
              "$$s",
              {
                income: {
                  $sum: [
                    "$$s.income",
                    200
                  ]
                }
              }
            ]
          },
          "else": "$$s"
        }
      }
     }
    }
   }
  }
  ])    

Playground2


Option 3: Another simple option , Warning: This option need to be used when shopID is not expected to be found more then once in the shops array , since it will update only 1st found shop element , if there is more then one element in same document with the same shopID they will not be updated.

db.collection.update({
   "shops.shopID": 2
},
{
 $inc: {
  "shops.$.income": 200
 }
})

Playground3

CodePudding user response:

You should move your income field in your Company document to your Shops document in your database design so that you can update different incomes for different shops.

 Shops.findOneAndUpdate(
  { _id: parsedBody.shopID},
  {
    set: {
     "income": { parsedBody.amountToAdd   income }
    }
  }
 )
  • Related