首页 > 解决方案 > 我们如何在更新中使用 $subtract 聚合管道运算符和位置 $ 运算符?

问题描述

我有如下文件:

{

    "_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",

}

所以现在当我接近时间时,我使用以下函数在 apps.close_time 中更新它:

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 };
  }
}

但现在我也想将持续时间更新为close_time-open_time. 我知道它可以使用 $subtract 聚合管道来实现,它对我来说适用于非嵌套对象。我尝试了以下不起作用的代码:

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 };
  }
}

所以我的问题是我们如何使用 $subtract 聚合管道运算符与位置 $ 运算符一起使用 mongoose 更新 mongoDB 中的嵌套对象数组

我正在使用 mongoDB 版本 4.2.2

标签: node.jsmongodbmongoose

解决方案


根据评论 - 由于“应用程序”是一个数组,您需要在聚合中使用$map来更新元素中的值。

询问 :

[
  {
    $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 */
            ]
          }
        }
      }
    }
  }
];

推荐阅读