如何使用Mongoose填充同一模型上子文档?

tct7dpnv  于 11个月前  发布在  Go
关注(0)|答案(1)|浏览(107)

这是我的产品模型。

const featureHeaderSchema = new Schema({
    header: {
        type: String,
        required: true,
    },
});
const featureSchema = new Schema({
    title: {
        type: String,
        required: true,
    },
    parentHeader: { type: Schema.Types.ObjectId, ref: "product.featureHeaders" }, // not sure if this is correct
    parentFeature: { type: Schema.Types.ObjectId, ref: "product.features" },  // not sure if this is correct
});
const productSchema = new Schema(
    {
        title: {
            type: String,
            required: true,
        },
        thumbnail: String,
        description: String,
        manufacture: { type: Schema.Types.ObjectId, ref: "user" },
        featureHeaders: {
            type: [featureHeaderSchema],
        },
        features: {
            type: [featureSchema],
        },
    },
    { timestamps: true }
);
const productModel = mongoose.model("product", productSchema);

字符串
我想通过id找到一个产品,并使用populate获取parentHeader的标题和parentFeature的标题。
我试图通过产品ID获取产品信息,并填充parentHeader和parentFeature,这样我就可以在输出中显示它们的标题。
我试过这个查询:

const output = await productModel
    .findById(newProduct._id)
    .populate("features.parentFeature")
    .exec();


但是我得到了这个错误:MissingSchemaError:Schema hasn't been registered for model“product.features”.

n1bvdmb6

n1bvdmb61#

首先,populate不可能实现你想要做的事情。这是因为schema声明中的ref属性是用来引用一个模型,而不是一个路径。它用来告诉mongoose你想使用哪个模型来执行$lookup,mongoose希望那个模型对应于你数据库中的一个集合。
其次,您在productSchema中为featureHeadersfeatures数组使用子文档,因此无论如何populate都不适用。
幸运的是,你可以修复这个问题,让populate为你工作。虽然你的命名约定和用例有点混乱,希望这将有助于解释它是如何做到的:

  1. FeatureHeaderFeature需要有它们自己的集合,而不是子文档,所以你需要为它们创建模型。
import mongoose from "mongoose";
const featureHeaderSchema = new mongoose.Schema({
    header: {
        type: String,
        required: true,
    }
});
// You need create the FeatureHeader model
const FeatureHeader = mongoose.model("FeatureHeader", featureHeaderSchema);

const featureSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true,
    },
    parentHeader: { 
       type: mongoose.Schema.Types.ObjectId, 
       ref: "FeatureHeader" //< Reference the FeatureHeader model
    }, 
    parentFeature: { 
       type: mongoose.Schema.Types.ObjectId, 
       ref: "Feature" //< You can reference the same model (i.e self)
    }
});
// You need create the Feature model
const Feature = mongoose.model("Feature", featureSchema);

const productSchema = new mongoose.Schema({
   title: {
      type: String,
      required: true,
   },
   thumbnail: String,
   description: String,
   manufacture: { 
      type: mongoose.Schema.Types.ObjectId, 
      ref: "User" //< Capitalise the model name
   },
   featureHeaders: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: "FeatureHeader", //< Reference the FeatureHeader model
   }],
   features: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: "Feature", //< Reference the Feature model
   }],
},
{ timestamps: true });
// You need create the Feature model
const Product = mongoose.model("Product", productSchema);

字符串

  1. FeatureHeaderFeature需要单独保存在各自的集合中,以便引用。
const newFeatureOne = await Feature.create({
   title: 'Marvel',
});

const newFeatureHeader = await FeatureHeader.create({
   header: 'Superhero'
});

const newFeatureTwo = await Feature.create({
   title: 'Repulsor Beams',
   parentHeader: newFeatureHeader._id,
   parentFeature: newFeatureOne._id
});

const newProduct = await Product.create({
   title: 'Repulsor Beams',
   //...
   //... 
   featureHeaders: [newFeatureHeader._id],
   features: [newFeatureTwo._id],
});


1.现在,您可以调用populate来将ObjectId替换为相应的文档:

const id = req.body.id; //< Could be req.params.id or however you get the id

const product = await Product.findById(id)
   .populate("featureHeaders")
   .populate("features");

备注:根据您的设计以及模型的作用域,您可能需要指定populate选项对象的path和/或model属性,如下所示:

const id = req.body.id; //< Could be req.params.id or however you get the id

const product = await Product.findById(id)
   .populate({path: "featureHeaders", model: "FeatureHeader"})
   .populate({path: "features", model: "Feature"});


希望所有这些都是有意义的,如果你有任何问题,请在评论中提出。

相关问题