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
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
]
}
}
}
])