我有一个带有 MongoDB 数据库的 Node.js 应用程序,并使用 mongoose 与其交互。
我有两个重要的模式: 首先是产品架构
export const productSchema = new Schema({
name: { type: String },
amazon_listing: { type: Schema.Types.ObjectId, ref: "AmazonListing" },
...
})
第二个是我的亚马逊列表模式,它由几个模式组成(不确定这是否是反模式?)
export const amazonListingSchema = new Schema({
asin: { type: String, required: true },
fee_details: { type: feeDetailsSchema },
...
})
const feeDetailsSchema = new Schema({
fees: [{ type: feeArraySchema }],
...
})
const feeArraySchema = new Schema({
type: { type: String },
amount: { type: Number },
final_fee: { type: Number },
promotion: { type: Number },
})
当我查询我的所有产品时,我也想填充
amazon_listing.fee_details.fees
,但我不知道如何实现。
我尝试过以下方法:
return ProductModel.find({})
.sort(sortOrder)
.populate("amazon_listing")
.populate("amazon_listing.fee_details.fees")
.exec()
但是每次当我检查网络流量时我的反应是:
"fee_details": {
...
"fees": [
{
"_id": "663fc68f066f091f9b029857"
},
{
"_id": "663fc68f066f091f9b029858"
},
{
"_id": "663fc68f066f091f9b029859"
},
{
"_id": "663fc68f066f091f9b02985a"
}
],
"_id": "663fc68f066f091f9b029856"
}
任何帮助和文档链接都会很棒,谢谢。
第二个是我的亚马逊列表模式,它由几个模式组成(不确定这是否是反模式?):
回复:这是很正常的,模式类型可以基于另一个模式。
当我查询我的所有产品时,我也想填充 amazon_listing.fee_details.fees 但我不知道如何。
return ProductModel.find({}) .sort(sortOrder) .populate("amazon_listing") .populate("amazon_listing.fee_details.fees") .exec()
回复:在上面的代码中,amazon_listing 是一个引用键,它引用了另一个模型,即 AmazonListing。因此,第一个填充调用 - populate("amazon_listing") 是有效的。然而,第二个填充调用 - populate("amazon_listing.fee_details.fees") 将被审查。
它试图填充关键费用。请看一下这个键的模式类型,它是这样的 - Fees: [{ type: FeeArraySchema }]。这意味着它不是引用类型键,而是 FeeArraySchema 的嵌入子文档的数组。这进一步意味着它已经作为填充文档 - amazon_listing 的一部分提供。因此,查找调用通过语句完成 - ProductModel.find({}) .sort(sortOrder) .populate("amazon_listing").exec().
现在,一旦通过 find 方法检索文档,就可以通过点符号访问关键费用,就像这样的嵌入式文档 - ProductModelDocument.amazon_listing.fee_details.fees。请参考下面的示例代码,里面有相关代码,请仔细查看line1和line2行。它实现了到目前为止所讨论的内容。
const mongoose = require('mongoose');
const { Schema } = mongoose;
run().catch((e) => console.log(e));
async function run() {
await mongoose.connect('mongodb://127.0.0.1:27017/test');
const feeArraySchema = new Schema({
type: { type: String },
amount: { type: Number },
final_fee: { type: Number },
promotion: { type: Number },
});
const feeDetailsSchema = new Schema({
fees: [{ type: feeArraySchema }],
});
const amazonListingSchema = new Schema({
asin: { type: String, required: true },
fee_details: { type: feeDetailsSchema },
});
const productSchema = new Schema({
name: { type: String },
amazon_listing: { type: Schema.Types.ObjectId, ref: 'AmazonListing' },
});
const AmazonListing = mongoose.model('AmazonListing', amazonListingSchema);
await AmazonListing.deleteMany();
const amazon = await new AmazonListing({
asin: 'asin',
fee_details: {
fees: [{ type: 'type', amount: 1, final_fee: 2, promotion: 3 }],
},
}).save();
const ProductList = mongoose.model('ProductList', productSchema);
await ProductList.deleteMany();
await new ProductList({ name: 'name', amazon_listing: amazon._id }).save();
// line1
const docs = await ProductList.find().populate('amazon_listing');
// line2
docs.forEach((d) => {
console.log(d);
console.log(d.amazon_listing.fee_details.fees);
});
}
OUTPUT:
{
_id: new ObjectId('6641e74c75090d74618c997a'),
name: 'name',
amazon_listing: {
_id: new ObjectId('6641e74c75090d74618c9975'),
asin: 'asin',
fee_details: { fees: [Array], _id: new ObjectId('6641e74c75090d74618c9976') },
__v: 0
},
__v: 0
}
[
{
type: 'type',
amount: 1,
final_fee: 2,
promotion: 3,
_id: new ObjectId('6641e74c75090d74618c9977')
}
]