如何在更新中将$ subtract聚合管道运算符与位置$运算符一起使用?

时间:2020-04-09 16:54:45

标签: node.js mongodb mongoose

我有如下文件:

{

    "_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中的嵌套对象数组

我正在使用4.2.2版的mongoDB

1 个答案:

答案 0 :(得分:1)

根据评论-由于“应用”是一个数组,因此您需要使用$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 */
            ]
          }
        }
      }
    }
  }
];