填充另一个对象引用的对象

我有一个产品列表,每个产品都有自己的选项。 例如:

  • 蓝色连衣裙(S – L)
  • 红色连衣裙(XS – S – M)

蓝色礼服红色礼服是产品, SLXSSM是select。 选项模型有一个产品模型的参考,我想检索所有的产品,然后列出自己的选项。

我只想用一个查询来实现它,我的问题是我从没有链接到它的选项的产品开始。 所以我开始find所有的产品,并与嵌套, 然后与foreach循环,我得到了所有的select。 然后我尝试将选项分配给产品对象(在我的情况下, forEach中的productElem ),但是当我将其从范围当中取出时,它是空的。 如何填充从产品查询开始的选项?

产品架构:

var schema = new Schema({ imagePath: {type: String}, title: {type: String, required: true}, description: {type: String, required: true} }); 

选项架构:

 var productOptionSchema = new Schema({ type: {type: String, enum: ['grams'], default: 'grams', required: true}, value: {type: String, required: true}, price: {type: Number, required:true}, product: {type: Schema.Types.ObjectId, ref: 'User', required:true} }); 

在这里,我尝试find产品后的选项

 router.get('/shop/products/list', isLoggedIn, function (req, res, next) { Product.find() .then(function (products) { products.forEach(function(productElem) { ProductOption.find({product: productElem._id}) .then(function (options) { productElem['options'] = []; options.forEach(function(optionElem) { productElem['options'].push(optionElem); }); }); }); res.render('shop/listProduct', {user:req.user, csrfToken: req.csrfToken(), messages:messages, partialCustom: }); }) .catch(function (err) { console.log('Error ' + err.code + ': ', err.message); res.status(500).send('Failed to get the Product List from the DB: ' + err); }); }); 

你的代码有一些缺陷。 forEach循环试图find所有基于product ID的选项,这看起来像是一个明显的方法,但这里的问题是find()方法的asynchronous性质。

由于find()的asynchronous特性, forEach循环在不等待find()的结果的情况下完成,因为尚未填充options 。 而循环后,它只是呈现“商店/ listProduct”,显然没有产品的select。

你可以做的是把所有的find()放在一个promises数组中,等待所有使用Promise.all() 。 在所有的承诺成功完成之后做res.render('shops/listProduct',{...})

替代方法:

我有一个更简单的方法来实现你想要使用aggregation

尝试这个:

 ProductOption.aggregate([{ $group : { _id : product, options : {$push : "$$ROOT"} } },{ $lookup : { from : "products", localField : "_id", foreignField : "_id", as : "product" } },{ $unwind : { path : "$product", preserveNullAndEmptyArrays : true } },{ $project : { _id : "$product._id" imagePath : "$product.imagePath", title : "$product.title", description : "$product.description", options : "$options" } }],function(err,result){ //result will have all the products with their options }); 

$group将根据productproduct分组(即产品ID), $lookup将填充产品对象, $project将以您想要的方式返回结果。

阅读关于mongodb Aggregation , $ group , $ lookup , $ project来更好地理解它。