mongoDB如何填充子子文档?

问题描述 投票:0回答:1

我有一个带有 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"
        }

任何帮助和文档链接都会很棒,谢谢。

node.js mongodb mongodb-query
1个回答
0
投票

第二个是我的亚马逊列表模式,它由几个模式组成(不确定这是否是反模式?):

回复:这是很正常的,模式类型可以基于另一个模式。

当我查询我的所有产品时,我也想填充 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')
  }
]
© www.soinside.com 2019 - 2024. All rights reserved.