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

Use Bluebird to deep populate objects in Sailsjs?

我有 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 库 promises 以及我应该做的事情,我没有走得太远:

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.

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

您似乎在尝试绘制所有楼层的地图,然后将这些承诺恢复到一个楼层。 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 进行一次查找可能会更高效。但以上应该有效,并且似乎与您之前采用的方法一致。