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

Posted

技术标签:

【中文标题】SailsJS / Waterline ORM:仅使用一个查询更新多个条目【英文标题】:SailsJS / Waterline ORM : Update multiple entries using only one query 【发布时间】:2019-04-17 13:10:48 【问题描述】:

我目前正在使用 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】:

在你的控制器中

确保您是 awaiting 来自您的服务的响应。

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 回调中做出响应之前被记录到控制台。

【讨论】:

以上是关于SailsJS / Waterline ORM:仅使用一个查询更新多个条目的主要内容,如果未能解决你的问题,请参考以下文章

与你相遇好幸运,async解决循环回调问题

Node中的ORM库-Waterline

nodejs-ORM 操作数据库中间件waterline的使用

nodejs下的数据库ORM---waterline

Waterline ORM - 检查数组属性是不是包含值

Sails.js Waterline ORM:.findOrCreate() 没有 .populate() 方法