Обход двух массивов с оператором MongoDB `$ []` и обновление соответствующих документов - PullRequest
0 голосов
/ 09 ноября 2018

После обновления до Mongo 4.0 я пытаюсь использовать новую функциональность $[] Mongo. То, что я в основном пытаюсь сделать, это взять один или несколько идентификаторов «покрытия» и пройти через два массива, чтобы фильтровать обновления по совпадениям с теми, которые были переданы в идентификаторах «покрытия». Соответствующая часть моего кода выглядит так:

if (coverage) {
    let arrCoverage = [];
    arrCoverage = coverage.split(",");

    if (arrCoverage) {
      // convert each ID to a mongo ID
      let mongoArrCoverage = arrCoverage.map(coverage => new mongo.ObjectID(coverage));

      if (mongoArrCoverage) {
        try {
          let bulk = db.collection("customers").initializeUnorderedBulkOp();
          let count = 0;
          let batch = 1;

          db.collection("customers")
            .aggregate([
              {
                $match: {
                  "paymentOptions.coverages._id": {
                    $in: mongoArrCoverage
                  }
                }
              },
              {
                $unwind: "$paymentOptions"
              },
              {
                $unwind: "$coverages"
              },
              {
                $match: {
                  "coverages._id": {
                    $in: mongoArrCoverage
                  }
                }
              },
              {
                $project: {
                  _id: 0,
                  coverages_id: "$coverages._id",
                  "coverages.status": "$coverages.status"
                }
              }
            ])
            .forEach(function(doc) {
              let coverages_id = doc.paymentOptions.coverages_id;
              bulk
                .find({
                  "paymentOptions.coverages._id": coverages_id
                })
                .updateOne({
                  $set: {
                    "paymentOptions.$[].coverages.$[].coverageEnd": lastDayOfMonth,
                    "paymentOptions.$[].coverages.$[].status": doc.paymentOptions.coverages.status == "active" ? null : doc.paymentOptions.coverages.status,
                    "paymentOptions.$[].coverages.$[].lastAdvanceDate": today
                  }
                });
              count++;
              if (count == batch) {
                bulk.execute();
                bulk = db.collection("customers").initializeUnorderedBulkOp();
                count = 0;
              }
            });

          if (count > 0) {
            bulk.execute();
          }

          res.sendStatus(200);
        } catch (e) {
          console.log(e);
        }
      }
    }
  }
};

Но это, похоже, не делает ожидаемых обновлений. Я думаю, что проблема может быть в первоначальной агрегации, которую я делаю? Этот код выглядит правильно? В нашей предыдущей модели массив «покрытия» находился в корне документа. Теперь, когда это свойство в "paymentOptions", которое также является массивом, я предполагаю, что мне нужно $unwind оба этих массива в моей первоначальной агрегации.

Кстати, соответствующая часть документа выглядит так:

{
  _id: <ObjectId>,
  someProp: <value>,
  paymentOptions: [
    {
     _id: <ObjectId>,
     otherProp: <value>,
     coverages: [
        {
          _id: <ObjectId>,  // Want to match on this
          coverageStart: <Date>,
          coverageEnd: <Date>, // Want to update this
          status: "active"
        },
        {
          _id: <ObjectId>, // Want to match on this
          coverageStart: <Date>,
          coverageEnd: <Date>, // Want to update this
          status: "active"
        }
     ]
    }
  ]
}

1 Ответ

0 голосов
/ 09 ноября 2018

Вы должны использовать фильтры массива. Также, чтобы разматывать вложенные массивы, вы должны использовать точечную запись, чтобы включить весь путь.

Что-то вроде должно работать

if (coverage) {
  let arrCoverage = [];
  arrCoverage = coverage.split(",");
  if (arrCoverage) {
    // convert each ID to a mongo ID
    let mongoArrCoverage = arrCoverage.map(coverage => new mongo.ObjectID(coverage));
    if (mongoArrCoverage) {
      try {
        let bulk = db.collection("customers").initializeUnorderedBulkOp();
        let count = 0;
        let batch = 1;
        db.collection("customers").aggregate([{
          $match: {
            "paymentOptions.coverages._id": {
              $in: mongoArrCoverage
            }
          }
        }, {
          $unwind: "$paymentOptions"
        }, {
          $unwind: "$paymentOptions.coverages"
        }, {
          $match: {
            "paymentOptions.coverages._id": {
              $in: mongoArrCoverage
            }
          }
        }, {
          $project: {
            _id: 0,
            "paymentOptions_id": "$paymentOptions._id",
            "coverages_id": "$paymentOptions.coverages._id",
            "coverages_status": "$paymentOptions.coverages.status"
          }
        }]).forEach(function(doc) {
            let paymentOption_id = doc.paymentOptions_id;
            let coverages_id = doc.coverages_id;
            let status = doc.coverages_status;
            bulk.find({}).arrayFilters([
                {"po._id": paymentOption_id},
                {"cr._id":  coverages_id}]).updateOne({
                $set: {
                  "paymentOptions.$[po].coverages.$[cr].coverageEnd": lastDayOfMonth,
                  "paymentOptions.$[po].coverages.$[cr].status": status == "active" ? null : status,
                  "paymentOptions.$[po].coverages.$[cr].lastAdvanceDate": today
                }
              }); count++;
              if (count == batch) {
                bulk.execute();
                bulk = db.collection("customers").initializeUnorderedBulkOp();
                count = 0;
              }
            });
          if (count > 0) {
            bulk.execute();
          }
          res.sendStatus(200);
        }
        catch (e) {
          console.log(e);
        }
      }
    }
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...