使用Bluebird深度填充Sailsjs中的对象?

时间:2015-09-15 20:01:15

标签: promise sails.js waterline bluebird

我有two popular和类似的问题,但区别在于那些只需要担心一个对象的深度填充关联,而我的是N个对象。

假设我有3个模型定义(为清楚起见,省略了一些属性):

identity: 'room',
attributes: {
      LocationId : { type: 'integer',
                  primaryKey: true,
                  required: true,
                  autoIncrement: true },
      DisplayName : { type: 'string',
                      unique: true },

      FloorId : { model: 'Floor' }
 }

  identity: 'floor',
  attributes: {
      FloorId : { type: 'integer',
                  primaryKey: true },
      FloorName : { type: 'string' },

      BuildingId : { model: 'Building' },
      rooms: {collection:'room', via:'FloorId'}
  }


identity: 'building',
attributes: {
      BuildingId : { type: 'integer',
                  primaryKey: true },
      BuildingName : { type: 'string' },

      floors: {collection:'floor', via:'BuildingId'}
 }

最终目标是拥有一个具有这种基本结构的对象数组:

[{
    "LocationId": 555,
    "DisplayName": 'SomeCoolName',
    "Floor" : { 
           "FloorId": 1337,
           "FloorName": '5',
           "Building": {
                "BuildingId": 4321,
                "BuildingName": 'HQ'
            }
     }
},  {...}]

由于不知道 BlueBird库 承诺以及我应该这样做,我没有走得太远:

showWithAssetGeo: function(req, res) {
    room.find( { assetCount: { '>': 0 } } )
        .populate('FloorId')
        .each(function(room){
            var Building = Building.find({ id: _.pluck(room.FloorId, 'BuildingId') })
            .then(function(Building) {return Building;});
            return [room, Building];
        })
        .spread(function(room, Building) {
            //Something to combine it all?
        })
        .catch (function(err) {
            if (err) { res.badRequest('reason' + err); }
         }
}

更新:必须调整下面标记的答案。 Here is the final working code.

1 个答案:

答案 0 :(得分:2)

你需要确保通过调用then或exec来执行find(每个都不会这样做)。

好像你试图在所有楼层上映射,然后将这些承诺带回一个楼层。 Promise.all()就是这样做的。

尝试以下内容:

showWithAssetGeo: function(req, res) {
  room.find( { assetCount: { '>': 0 } } )
    .populate('FloorId')
    .then(function(rooms) {
      return Promise.all(rooms.map(function(room) {
        return Building.findOne({id: room.FloorId.BuildingId})
          .then(function(building) {
            room.FloorId.building = building;
          });
      })
    })
    .then(function(deeplyPopulatedRooms) {
      res.json(deeplyPopulatedRooms);
    })
    .catch(function(error) {
      if (err) { res.badRequest('reason' + err); }
    });
}

然而,拔掉所有可能建筑物的id并且找到所有id的id可能会更高效。但上述内容应该有效,并且似乎与您之前采用的方法一致。