如何编写MongoDB查询,筛选含标签a的嵌套元素并保留符合条件子项?
MongoDB筛选文档并过滤嵌套数组元素
给定数据集:
[ { "item": "journal", "qty": 25, "status": "A", "products": [ { "key": "item-one", "name": "item one", "tags": ["a", "b"] }, { "key": "item-two", "name": "item-two", "tags": ["a", "c", "d"] }, { "_id": 3, "name": "item-three", "tags": ["g"] } ] }, { "item": "notebook", "qty": 50, "status": "b", "products": [ { "key": "item-four", "name": "item four", "tags": ["a", "o"] }, { "key": "item-five", "name": "item-five", "tags": ["s", "a", "d"] } ] } ]
需求:筛选出所有包含标签a的文档(即products数组中至少有一个子文档的tags包含a),同时每个文档的products数组仅保留tags包含a的子文档,预期结果如下:
[ { "item": "journal", "qty": 25, "status": "A", "products": [ { "key": "item-one", "name": "item one", "tags": ["a", "b"] }, { "key": "item-two", "name": "item-two", "tags": ["a", "c", "d"] } ] }, { "item": "notebook", "qty": 50, "status": "b", "products": [ { "key": "item-four", "name": "item four", "tags": ["a", "o"] }, { "key": "item-five", "name": "item-five", "tags": ["s", "a", "d"] } ] } ]
解决方法:使用MongoDB聚合管道
通过$match结合$filter操作符即可实现需求,以下是两种可选方案:
方案1:显式指定保留字段($project)
db.collection.aggregate([ // 筛选出products中存在tags包含"a"的父文档 { $match: { "products.tags": "a" } }, // 过滤products数组,仅保留符合条件的子文档 { $project: { item: 1, qty: 1, status: 1, products: { $filter: { input: "$products", as: "product", cond: { $in: ["a", "$$product.tags"] } } } } } ])
方案2:自动保留所有原有字段($addFields)
如果父文档字段较多,不想逐个列举,可使用$addFields替换$project,自动保留所有字段并覆盖过滤后的products数组:
db.collection.aggregate([ { $match: { "products.tags": "a" } }, { $addFields: { products: { $filter: { input: "$products", as: "product", cond: { $in: ["a", "$$product.tags"] } } } } } ])
代码说明
$match阶段:快速过滤出符合条件的父文档,减少后续处理的数据量;$filter操作:遍历products数组,通过$in判断子文档的tags是否包含a,仅保留符合条件的子元素。
执行上述任意一段聚合查询,均可得到需求中的预期结果。
内容的提问来源于stack exchange,提问作者Amrinder Singh
相关产品推荐
相关产品推荐

