Shashank Padwal
Shashank Padwal

Reputation: 323

how can we use $subtract aggregation pipeline operators along side with The positional $ operator in update?

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

Answers (1)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

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

Related Questions