Home > OS >  How to update an array value in mongodb using aggregation
How to update an array value in mongodb using aggregation

Time:10-02

My Document looks something like this

{ _id: ObjectId("60b114b2415731001943b17f"),
processList:[ 
    { processName: 'Wood cutting',
    createdAt: '2021-05-28T08:59:06.260Z',
    updatedAt: '2021-05-28T08:59:06.260Z',
    id: '60b0f0e9659a3b001c235300',
    endTime: '2021-07-09T22:25:57.973Z',
    isCompleted: false },
    { processName: 'Painting',
    createdAt: '2021-05-28T13:32:02.441Z',
    updatedAt: '2021-05-28T13:32:02.441Z',
    id: '60b0f0e9659a3b001c235301',
    endTime: 2021-05-28T17:05:06.067Z,
    isCompleted: true },
    {processName: 'Varnishing',
    createdAt: '2021-05-28T09:46:33.169Z',
    updatedAt: '2021-05-28T09:46:33.169Z',
    id: '60b0f0e9659a3b001c235302',
    endTime: 2021-05-28T20:05:06.067Z,
    isCompleted: false } 
],

   companyId: '60b0a2b7b0beab001a068f8c',
   customerId: '60b11289415731001943b17d',
   productName: 'Queen size bed',
   quantity: 1,
   orderStartedTime: 2021-05-28T16:05:06.067Z,
   estimatedEndTime: 2021-05-29T01:05:06.067Z,
   createdAt: 2021-05-28T16:05:06.069Z,
   updatedAt: 2021-07-09T22:20:58.019Z,
   __v: 0,
  percentageCompleted: 33.33333333333333 }

I'm trying to update the percentageCompleted and one of the process list's isCompleted true based on the id inside processList.

I ran this query but throws error

db.orders.findOneAndUpdate(
{
 _id: ObjectId('60b114b2415731001943b17f')
},
[
    {
    
    $set: {"processList.$[element].isCompleted": true} 
},
{
        multi: true,
        arrayFilters: [{ 'element.id': { $eq: "60b0f0e9659a3b001c235300" } }],
},


{
    $set: {
        percentageCompleted: {
            $multiply: [
                {
                    $divide: [{
                        $size: {
                            $filter: {
                                input: "$processList",
                                as: "process",
                                cond: { $eq: ["$$process.isCompleted", true] }
                            }
                        }
                    },
                    { $size: "$processList" }]
                }, 100
            ]
        },
    }
}
]
)

When I exclude the updation of array (isCompleted), the updation of percentageCompleted is getting calculated and set. Can someone help me how to proceed. Thanks in advance.

CodePudding user response:

Not possible. Aggregation is used only to fetch/read data.

You must work with 2 queries from server.

First to find the value to update using aggregate.

Then make another request to update the value.

This method will not work, if you are expecting multiple request at the same time trying to update the same document.

CodePudding user response:

We can mix update operators with aggregate operators, if we need aggregate operators we do update it with pipeline update.

pipeline updates require MongoDB >=4.2

Query

  • map to update the processList
  • your $set from your query

Test code here

db.collection.update({
  "_id": "60b114b2415731001943b17f"
},
[
  {
    "$set": {
      "processList": {
        "$map": {
          "input": "$processList",
          "in": {
            "$cond": [
              {
                "$eq": [
                  "$$this.id",
                  "60b0f0e9659a3b001c235300"
                ]
              },
              {
                "$mergeObjects": [
                  "$$this",
                  {
                    "isCompleted": true
                  }
                ]
              },
              "$$this"
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "percentageCompleted": {
        "$multiply": [
          {
            "$divide": [
              {
                "$size": {
                  "$filter": {
                    "input": "$processList",
                    "as": "process",
                    "cond": {
                      "$eq": [
                        "$$process.isCompleted",
                        true
                      ]
                    }
                  }
                }
              },
              {
                "$size": "$processList"
              }
            ]
          },
          100
        ]
      }
    }
  }
])
  • Related