我想填充一个模型,该模型具有文档的 ObjectId,该文档作为另一个模型上的子架构存在
子架构
var addressSchema = new Schema({
address: String,
phoneNumber: Number,
name: String,
pincode: Number,
augmontAddressId: String,
});
主架构 - 地址是一个数组,可以有多个地址,每个对象都有自己的 objecId,我想引用
var userSchema = new Schema(
{
name: String,
address: [addressSchema],
},
{
timestamps: true,
}
);
引用主模式的账本模式
var ledgerSchema = new Schema(
{
txnId: String,
paymentId: String,
addressId:{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
},
{
timestamps: true,
}
);
我试过了
LedgerSchema.findById().populate("addressId").then(res=>{
console.log(res);
})
但它没有填充addressId而是发送空值
{
_id: new ObjectId("650c49a20483f1ec8eb7aecd"),
addressId: null,
createdAt: 2023-09-21T13:48:18.667Z,
updatedAt: 2023-09-21T13:48:18.667Z,
__v: 0
}
我还尝试将 ledgerSchema 中的 ref 设置为“User.address” 但它给出了一个错误
MissingSchemaError: Schema hasn't been registered for model "User.Address".
哦,如果你能做
User.address
来参考事物,那就太好了。不幸的是,由于您设置子文档的方式,无法使用 populate
来完成此操作。在您的 userSchema
中,每个 address
本质上都是一个子文档,它“嵌入”在顶级文档中。相反,在您的 ledgerSchema
中,每个 addressId
都是一个 引用文档,并且是单独的顶级文档。 我的建议是更改您的
userSchema
,以便每个
address
都是一个引用文档,但这将在您的数据库中创建另一个集合(
addresses
)。您需要它来做参考。如果出于某种原因您无法修改架构并且需要将每个 address
保留为
embedded子文档,那么您可以使用 aggregate 实现所需的结果。这不是一个微不足道的任务,它并不漂亮,但它确实有效:
const ledger = await ledgerModel.aggregate([
{ $match: { _id: new mongoose.Types.ObjectId(id) } }, //< Your ledger _id
{
$lookup: //< Do a lookup to match addressId with userSchema.address._id
{
from: "users",
localField: "addressId",
foreignField: "address._id",
as: "address_details" //< This creates a new array
}
},
{ $unwind: '$address_details'}, //< Now you need to unwind the new array
{ $unwind: '$address_details.address'}, //< And unwind each address
{
$project: //< This stage only outputs the original ledger properties
{
txnId: 1,
paymentId: 1,
address_details: 1,
compare_address_ids: { $cmp: [ "$addressId", "$address_details.address._id" ] },
//^ Compare addressId against ones done via lookup to find a match
}
},
{
$match: {
compare_address_ids: 0 //< 0 means they matched
}
},
{
$project: //< Now get rid of these two made up properties from the output
{
compare_address_ids: 0,
'address_details.name': 0,
}
}
]);