如何填充子文档的字段,该子文档是另一个文档的数组元素?

let collection = await Collection.findOne({ 'works._id': req.params.id }).populate('works.0.photo');

此代码将填充索引0中的work子文档,但是我希望它填充与req.params.id对应的索引。

我想要类似.populate('works.i.photo')的东西,其中i代表包含与_id相匹配的req.params.id的作品的索引。


我想出了办法,但是我敢肯定有更好的方法。

let collection = await Collection.findOne({ 'works._id': req.params.id });
const idx = collection.works.findIndex(work => work._id == req.params.id);
collection = await collection.populate(`works.${idx}.photo`).execPopulate();

这看起来不像预期的方式。是否可以在不迭代查找索引的情况下执行此操作?最好只执行一次查询。

xiaoyr062285 回答:如何填充子文档的字段,该子文档是另一个文档的数组元素?

假设您的数据是这样的:

someCollection:

/* 1 */
{
    "_id" : ObjectId("5dc9c61959f03a3d68cfb8d3"),"works" : []
}

/* 2 */
{
    "_id" : ObjectId("5dc9c72e59f03a3d68cfd009"),"works" : [ 
        {
            "_id" : 123,"photoId" : ObjectId("5dc9c6ae59f03a3d68cfc584")
        },{
            "_id" : 456,"photoId" : ObjectId("5dc9c6b659f03a3d68cfc636")
        }
    ]
}

照片集:

/* 1 */
{
    "_id" : ObjectId("5dc9c6ae59f03a3d68cfc584"),"photo" : "yes"
}

/* 2 */
{
    "_id" : ObjectId("5dc9c6b659f03a3d68cfc636"),"photo" : "no"
}

/* 3 */
{
    "_id" : ObjectId("5dc9c6c259f03a3d68cfc714"),"photo" : "yesno"
}

猫鼬模式:

const photoSchema = new Schema({
    _id: Schema.Types.ObjectId,photo: String,});

const someColSchema = new Schema({
    _id: { type: Schema.Types.ObjectId },works: [{ _id: { type: Number },photoId: { type: Schema.Types.ObjectId,ref: 'photo' } }]
});

const someCol = mongoose.model('someCollection',someColSchema,'someCollection');
const photoCol = mongoose.model('photo',photoSchema,'photo');

代码:

1)使用猫鼬填充(Mongoose Populate):

let values = someCol.find({"works._id": 123},{_id: 0,'works.$': 1}).populate('works.photoId').lean(true).exec();

2)使用mongoDB的本机$ lookup(mongoDB $lookup):

someCol.aggregate([{ $match: { 'works._id': 123 } },{ $unwind: '$works' },{ $match: { 'works._id': 123 } },{
    $lookup:
    {
        from: "photo",localField: "works.photoId",foreignField: "_id",as: "doc"
    }
},{ $project: { _id: 0,doc: { $arrayElemAt: ["$doc",0] } } }])

两者的工作原理相似,在聚合中,我们正在$match过滤给定的条件,而$unwind展开包装工作数组,再次进行过滤以仅保留匹配过滤条件的数组中的值,然后做$lookup来从其他集合中获取相应的文档。

本文链接:https://www.f2er.com/3121741.html

大家都在问