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

时间:2019-04-17 13:10:48

标签: javascript orm sails.js waterline sails-mongo

我目前正在使用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      : "",
        };
    }

}

1 个答案:

答案 0 :(得分:1)

在您的控制器中

确保您await收到服务的回复。

let response = await CarService.setLocationOfCars(carsLocationArray);

在您的“服务”中

我可能会将_.forEach替换为常规的for循环。在您的情况下,请执行以下操作,请确保确实定义了gateway.id以及要返回给调用代码的值(您的问题中没有引用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个数据库查询,而不是“仅使用一个查询”。

但是为什么不_.forEach?

在forEach中使用async回调看起来并不像它可能会做的。在运行arrayOfIdsUpdated的任何调用之前 ,您的updateOne可能会返回到您的控制器代码为空。

以这个为例:

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

请注意“完成!”在await forEach回调中的响应之前记录到控制台。