Mongoose populate嵌套数组

24

假设以下3个模型:

var CarSchema = new Schema({
  name: {type: String},
  partIds: [{type: Schema.Types.ObjectId, ref: 'Part'}],
});

var PartSchema = new Schema({
  name: {type: String},
  otherIds: [{type: Schema.Types.ObjectId, ref: 'Other'}],
});

var OtherSchema = new Schema({
  name: {type: String}
});

当我查询汽车时,我可以填充零件:

Car.find().populate('partIds').exec(function(err, cars) {
  // list of cars with partIds populated
});

在mongoose中是否有一种方法可以填充所有车辆的嵌套部件对象中的otherIds。

Car.find().populate('partIds').exec(function(err, cars) {
  // list of cars with partIds populated
  // Try an populate nested
  Part.populate(cars, {path: 'partIds.otherIds'}, function(err, cars) {
    // This does not populate all the otherIds within each part for each car
  });
});

我可能可以迭代每辆汽车并尝试填充:

Car.find().populate('partIds').exec(function(err, cars) {
  // list of cars with partIds populated

  // Iterate all cars
  cars.forEach(function(car) {
     Part.populate(car, {path: 'partIds.otherIds'}, function(err, cars) {
       // This does not populate all the otherIds within each part for each car
     });
  });
});

问题在于我必须使用像async这样的库来为每个populate调用进行等待,直到所有操作完成,然后才返回。

是否可以在不遍历所有汽车的情况下完成?

4个回答

45

更新: 请参考Trinh Hoang Nhu的答案,其中包含更紧凑的版本,该版本已在Mongoose 4中添加。以下是总结:

Car
  .find()
  .populate({
    path: 'partIds',
    model: 'Part',
    populate: {
      path: 'otherIds',
      model: 'Other'
    }
  })

Mongoose 3 及以下版本:

Car
  .find()
  .populate('partIds')
  .exec(function(err, docs) {
    if(err) return callback(err);
    Car.populate(docs, {
      path: 'partIds.otherIds',
      model: 'Other'
    },
    function(err, cars) {
      if(err) return callback(err);
      console.log(cars); // This object should now be populated accordingly.
    });
  });

对于像这样嵌套的人口,您必须告诉mongoose您想从哪个模式进行填充。


废话,看文档吧 ;) 我现在看到了。但是无论我尝试什么,otherIds 都会返回一个空数组。为了确保正常,如果我不调用 populate 方法,则有一个 id 数组(这是正确的)。populate 没有填充这些 ids。运行的是来自 npm 的最新版本 3.8.22。 - lostintranslation
同时打开日志记录。我没有看到另一个调用其他集合来填充“join”的方法。所以mongoose甚至没有发出调用。 - lostintranslation
2
@lostintranslation 在嵌套的 populate 调用中应该是 model: 'Other' - JohnnyHK
@JohnnyHK 再次拯救,感谢!顺便说一句,我以为我可以在第一次调用 Car.find().populate('partIds').populate({path: 'partIds.otherIds', model: 'Other').exec ... 就把所有东西都搞定。可惜没有成功,看来你必须先进行第一次查询调用以填充 partIds。 - lostintranslation
或者,您可以尝试使用mongoose-deep-populate插件,并使用以下代码重写整个过程:Car.find().deepPopulate('partIds.otherIds').exec(...)。(免责声明:我是作者。) - Buu
第一个例子对我来说非常有效。model属性除了字符串以外还可以接受其他类型吗?或者可以传递模式引用吗? - mrClean

29

Mongoose 4 支持此功能

Car
.find()
.populate({
  path: 'partIds',
  model: 'Part',
  populate: {
    path: 'otherIds',
    model: 'Other'
  }
})

2
注意:model: 'Other' 是必需的。如果没有它,它将返回空数组。文档没有说明此点:http://mongoosejs.com/docs/populate.html#deep-populate - Harshad Ranganathan
但我想在一个嵌套级别中进行双重填充。因此,基本上像下面这样的东西,汽车 .find() .populate({ path: 'partIds', model: 'Part', populate: { path: 'otherIds', model: 'Other' } populate: { path: 'ModelIds', model: 'Model' } }) - Shivam Verma

4

0

使用以下代码会更好

Car
.find()
.populate({
    path: 'partIds.othersId'
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接