как мы можем использовать операторы конвейера агрегации $ subtract вместе с оператором позиционного $ в обновлении? - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть документ, подобный следующему:

{

    "_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 вместе с оператором Positional $ для обновления массива вложенных объектов в mongoDB, используя mon goose

Я использую mongoDB версии 4.2.2

1 Ответ

1 голос
/ 09 апреля 2020

Согласно комментарию - Поскольку 'apps' - это массив, вам нужно использовать $ 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 */
            ]
          }
        }
      }
    }
  }
];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...