MongoDB中使用Projection过滤嵌套数组的技术求助
MongoDB聚合:过滤嵌套数组中匹配父文档字段的元素
在MongoDB聚合操作中,完成lookup等步骤后得到如下文档结构:
[ { "_id": ObjectId("6407e265a15acdb137ec651e"), "myLocalId": "id1c1", "title": "id1c1 title", "details": [ { "myLocalId": "id1e2", "title": "id2e2 title2", "subarray": [ { "_id": "id1c1", "displayName": "id1c1 for id2e2" }, { "_id": "id1c2", "displayName": "id1c2 for id2e2" } ] }, { "myLocalId": "id2e3", "title": "id2e3 title3", "subarray": [ { "_id": "id1c1", "displayName": "id1c1 for id2e3" }, { "_id": "id2c2", "displayName": "id2c2 for id2e3" } ] } ] }, { "_id": ObjectId("6407e26da15acdb137ec651f"), "myLocalId": "id2c2", "title": "id2c2 title", "details": [ { "_id": ObjectId("6407e385a15acdb137ec6526"), "myLocalId": "id2e1", "title": "id2e1 title", "subarray": [ { "_id": "id2c2", "displayName": "id2c2 for id2e1" }, { "_id": "id2c3", "displayName": "id2c3 for id2e1" } ] }, { "_id": ObjectId("6407e385a15acdb137ec6526"), "myLocalId": "id2e2", "title": "id2e1 title", "subarray": [ { "_id": "id2c2", "displayName": "id2c2 for id2e2" }, { "_id": "id2c4", "displayName": "id2c4 for id2e2" } ] } ] } ]
需要过滤每个details数组元素下的subarray,仅保留其中_id与父文档myLocalId匹配的元素。尝试使用$project操作符未达到预期效果,期望输出如下结构:
[ { "_id": ObjectId("6407e265a15acdb137ec651e"), "myLocalId": "id1c1", "title": "id1c1 title", "details": [ { "myLocalId": "id1e2", "title": "id2e2 title2", "subarray": [ { "_id": "id1c1", "displayName": "id1c1 for id2e2" } ] }, { "myLocalId": "id2e3", "title": "id2e3 title3", "subarray": [ { "_id": "id1c1", "displayName": "id1c1 for id2e3" } ] } ] }, { "_id": ObjectId("6407e26da15acdb137ec651f"), "myLocalId": "id2c2", "title": "id2c2 title", "details": [ { "_id": ObjectId("6407e385a15acdb137ec6526"), "myLocalId": "id2e1", "title": "id2e1 title", "subarray": [ { "_id": "id2c2", "displayName": "id2c2 for id2e1" } ] }, { "_id": ObjectId("6407e385a15acdb137ec6526"), "myLocalId": "id2e2", "title": "id2e1 title", "subarray": [ { "_id": "id2c2", "displayName": "id2c2 for id2e2" } ] } ] } ]
解决方案
使用$map遍历外层details数组,结合$filter筛选每个subarray中符合条件的元素,聚合管道如下:
db.collection.aggregate([ { $addFields: { "details": { $map: { input: "$details", as: "detail", in: { // 保留原detail的所有字段,替换subarray为过滤后的结果 ..."$$detail", "subarray": { $filter: { input: "$$detail.subarray", as: "item", cond: { $eq: ["$$item._id", "$myLocalId"] } } } } } } } } ])
说明:
$map:遍历details数组,对每个元素进行自定义处理$filter:在每个detail的subarray中,筛选出_id等于父文档myLocalId的元素...$$detail:保留detail原有全部字段(需MongoDB 4.2及以上版本支持),若版本较低,可显式列出需要保留的字段,例如:in: { "_id": "$$detail._id", "myLocalId": "$$detail.myLocalId", "title": "$$detail.title", "subarray": { /* 过滤逻辑 */ } }
内容的提问来源于stack exchange,提问作者user2842284
相关产品推荐
相关产品推荐

