Reputation: 323
I have document like following:
{
"_id": "5e8ecce4cf2647202dfd4551",
"logout_time": null,
"apps": [{
"name": "notepad",
"open_time": "1584351875000",
"close_time": null,
"duration": null,
"tasks": []
}],
"duration": null,
"user_id": "5e8109ea5bc5822aa531a57d",
"comp_id": "5e8d16a0c1834fd3d8e9e1eb",
"org_id": "5e8c7a34c358958a58be4755",
}
so now when I get close time I update it in apps.close_time using following function :
async function closeApp(app_name, session_id, time) {
try {
let updateObj = await Session.updateMany(
{ _id: session_id, "apps.name": app_name, "apps.close_time": null },
{
$set: {
"apps.$[].close_time": new Date(time),
},
}
);
return {
status: "success",
msg: "App Added successfully",
update_info: updateObj,
};
} catch (err) {
return { status: "failed", message: err.message };
}
}
but now I also want to update duration as close_time-open_time
.
I know it can be achieve using $subtract aggregation pipeline and its worked for me on non-nested objects.
I tried following code which is not working:
async function closeApp(app_name, session_id, time) {
try {
let updateObj = await Session.updateMany(
{ _id: session_id, "apps.name": app_name, "apps.close_time": null },
[
{
$set: {
"apps.$.close_time": new Date(time),
"apps.$.duration": {
$toInt: {
$divide: [
{ $subtract: [new Date(time), "$apps.$.$open_time"] },
60000,
],
},
},
},
},
]
);
return {
status: "success",
msg: "App Added successfully",
update_info: updateObj,
};
} catch (err) {
return { status: "failed", message: err.message };
}
}
so my question is how can we use $subtract aggregation pipeline operators along side with The positional $ operator to update nested object array in mongoDB using mongoose
I am using mongoDB version 4.2.2
Upvotes: 0
Views: 45
Reputation: 17915
As per comment - Since 'apps' is an array you need to use $map in aggregation to update values in an element.
Query :
[
{
$addFields: {
apps: {
$map: {
input: "$apps", /** Iterate through 'apps' array & re-create it */
in: {
$cond: [ /** Check for required conditions */
{ $and: [ { $eq: ["$$this.name", app_name] }, { $eq: ["$$this.close_time", null] }] },
{ /** If Yes, merge existing object with new field values */
$mergeObjects: [
"$$this",
{
close_time: new Date(time),
duration: { $toInt: { $divide: [ { $subtract: [new Date(time), "$$this.open_time"] },60000 ]}}
}
]
},
"$$this" /** If No, Return the element of 'apps' to apps array */
]
}
}
}
}
}
];
Upvotes: 1