如何在不使用$unwind的情况下执行多级$lookup查询?
不用$unwind实现多级$lookup的方案
完全可以做到!MongoDB 3.6及以上版本支持在$lookup阶段中使用自定义pipeline,这让我们能直接匹配数组中的ObjectId,无需先通过$unwind拆分数组。针对你的集合结构,具体的聚合查询如下:
db.venue.aggregate([ { $lookup: { from: "reviews", let: { venueReviewIds: "$reviews" }, pipeline: [ { $match: { $expr: { $in: ["$_id", "$$venueReviewIds"] } } } // 这里还可以添加其他针对reviews的处理阶段,比如$project筛选字段、$sort排序等 ], as: "reviewDetails" } } ])
代码解释:
let: 定义一个变量venueReviewIds,值就是当前venue文档中的reviews数组(存储的是review的ObjectId)pipeline: 在这个子管道里,我们用$match结合$expr和$in操作符,找出所有_id存在于venueReviewIds数组中的reviews文档as: 把匹配到的reviews结果数组命名为reviewDetails,最终会添加到每个venue文档中
查询结果示例:
执行后你会得到类似这样的文档结构,reviewDetails里直接包含了对应venue的所有reviews完整文档:
{ "_id" : ObjectId("5acdb8f65ea63a27c1facf86"), "name" : "ASA College - Manhattan Campus", "addedBy" : ObjectId("5ac8ba3582c2345af70d4658"), "reviews" : [ ObjectId("5acdb8f65ea63a27c1facf8b"), ObjectId("5ad8288ccdd9241781dce698") ], "reviewDetails" : [ { "_id" : ObjectId("5acdb8f65ea63a27c1facf8b"), "createdAt" : ISODate("...") }, { "_id" : ObjectId("5ad8288ccdd9241781dce698"), "createdAt" : ISODate("...") } ] }
这种方式不仅避免了$unwind带来的性能开销(尤其是当数组元素很多时),还能保持原始文档的结构完整性,非常适合你的场景。
内容的提问来源于stack exchange,提问作者Ashish Choudhary
相关产品推荐
相关产品推荐

