Mongoose - 填充对象

时间:2018-04-20 14:21:30

标签: javascript node.js mongoose

假设我有 3个模型

// Parent
const ParentSchema = new Schema({
    child: {
        type: ObjectId,
        ref: 'Child'
    },

    ...
});

// Child
const ChildSchema = new Schema({
    subChild: {
        type: ObjectId,
        ref: 'SubChild'
    },

    ...
});

// SubChild
const SubChildSchema = new Schema({
    name: String,
    ...
});

我在findOne上使用Parent,我想在populate上使用Child,但也在SubChild上使用{/ 1}:

Parent.findOne(options)
    .populate('child', 'subChild')
    // Trying to add another populate on subChild property like : .populate('<above_subChild>', 'name')
    .select('child')
    .exec(function (err, parent) {
        callback(err, parent.toJSON());
    })
;

有没有办法用populate

来做到这一点

目前,parent.toJSON()返回:

{
    // Parent _id
    _id: XXX,
    child: {
        _id: XXX,
        subChild: <subChild_ObjectID>        
    }
}

以下是我希望在populate属性上添加另一个subChild的结果:

{
    // Parent _id
    _id: XXX,
    child: {
        _id: XXX,
        subChild: {
            _id: XXX,
            name: XXX
        }
    }
}

2 个答案:

答案 0 :(得分:2)

这也将起作用:

Parent.findOne(options)
  .select('child')
  .populate('child.subChild')
  .exec(function(err, parent) {
    callback(err, parent.toJSON());
  });

答案 1 :(得分:1)

参考populate的文档,查询需要按如下方式构建,以填充多个级别:

Parent.findOne(options)
  .populate({
    path: 'child',
    populate: {
      path: 'subChild'
    }
  })
  .select('child')
  .exec(function(err, parent) {
    callback(err, parent.toJSON());
  });

使用mongoose的populate方法需要注意的一点是,每个人口都需要单独的查询。所以在这种情况下,虽然实现使用一个显式findOne方法,但是mongoose实际上是串行执行三个查询。

这大致等同于(略微伪编码):

Parent.findOne().exec().then((parent) => ([
  parent,
  Child.findById(parent.child).exec()
])).then(([parent, child]) => ([
  parent,
  child,
  SubChild.findById(child.subChild).exec()
])).then(([parent, child, subChild]) => {
  child.subChild = subChild;
  parent.child = child;

  return parent;
});