SailsJS / Waterline ORM:仅使用一个查询更新多个条目

SailsJS / Waterline ORM : Update multiple entries using only one query

我目前正在使用 SailsJS 框架,我正在尝试仅使用 MongoDB 数据库中的一个查询来更新一组元素。

这是我正在做的,但记录没有更新..

传入JSON:

{
  "cars": [
    {
      "id": "5cb5cbd5c395a01b4c9d86da",
      "latitude": "-5",
      "longitude": "551"
    },
    {
      "id": "5cb5cbd7c395a01b4c9d86db",
      "latitude": "-4",
      "longitude": "4421",
    }
  ]
}

控制器:

async setLocationOfCars(req, res) {

    try {

        sails.log.info(controllerName + "::" + req.options.action + "() - called");

        const carsLocationArray = req.body.cars;

        let response = CarService.setLocationOfCars(carsLocationArray);
        switch (response.status) {
            case constants.RESOURCE_SUCCESSFULLY_UPDATED :
                return HttpResponseService.json(200, res, constants.RESOURCE_SUCCESSFULLY_UPDATED, response.data);
            default:
                return HttpResponseService.internalServerError(res, response);
        }

    } catch(err) {
        return HttpResponseService.internalServerError(res, err);
    }

}

服务:

async setLocationOfCars(cars) {

    try {

        const arrayOfIdsUpdated = [];
        _.forEach(cars, async function(car){

            let attributesToUpdate = {};
            if (car.hasOwnProperty("latitude")) {
                attributesToUpdate.latitude = car.latitude;
            }
            if (car.hasOwnProperty("longitude")) {
                attributesToUpdate.longitude = car.longitude;
            }

            await Car.updateOne({
                id: car.id
            }).set(attributesToUpdate);

            arrayOfIdsUpdated.push(gateway.id)

        });

        return {
            status: constants.RESOURCE_SUCCESSFULLY_UPDATED,
            data  : arrayOfIdsUpdated
        };

    } catch (err) {
        return {
            status : constants.DATABASE_ERROR,
            name   : err.name ? err.name      : "",
            message: err.message ? err.message: "",
            stack  : err.stack ? err.stack    : "",
            code   : err.code ? err.code      : "",
        };
    }

}

在你的控制器中

确保您await正在接收服务的响应。

let response = await CarService.setLocationOfCars(carsLocationArray);

在你的"Service"

我可能会将 _.forEach 替换为常规 for 循环。在您的情况下,如下所示,确保实际定义了 gateway.id 以及您想要 return 调用代码的值(您的问题中没有对 gateway 的引用)。

for (let car of cars) {
  let attributesToUpdate = {};
  if (car.hasOwnProperty("latitude")) {
    attributesToUpdate.latitude = car.latitude;
  }
  if (car.hasOwnProperty("longitude")) {
    attributesToUpdate.longitude = car.longitude;
  }

  await Car.updateOne({
    id: car.id
  }).set(attributesToUpdate);


  // Where does gateway.id come from?
  arrayOfIdsUpdated.push(gateway.id)
}

也就是说,这将执行 cars.length 次数据库查询,而不是 "using only one query"。

但为什么不 _.forEach?

在 forEach 中使用 async 回调之类的方法看起来不会执行您可能希望它执行的操作。在 对 updateOne 运行 的任何调用之前,您的 arrayOfIdsUpdated 很可能会被 return 编辑为空的控制器代码。

以此为例:

const _ = require('lodash');

function doNothing() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 0)
  });
}

var foos = [1, 2, 3, 4, 5, 6]
_.forEach(foos, async (foo) => {
  await doNothing();
  console.log(`Finished #${foo}`);
});


console.log('Done!')

运行 它给出输出

Done!
Finished #1
Finished #2
Finished #3
Finished #4
Finished #5
Finished #6

请注意 "Done!" 如何在 await 在 forEach 回调中进行响应之前记录到控制台。