MongoDB如何简化嵌套数组标签过滤查询,无需枚举返回字段?
MongoDB查询:自动返回所有字段同时过滤嵌套数组
问题描述
我的数据结构如下:
[ { "item": "journal", "qty": 25, "status": "A", "weekNumber": 1, "sortOrder": 1, "label": 1, "numberOfPossibleDays": 1, "editable": 1, "selectedDate": 1, "deliveryDays": 1, "products": [ { "key": "item-one", "name": "item one", "tags": ["v", "b"] }, { "key": "item-two", "name": "item-two", "tags": ["a", "c", "d"] }, { "_id": 3, "name": "item-three", "tags": ["g"] } ] }, { "item": "notebook", "status": "b", "qty": 1, "weekNumber": 1, "sortOrder": 1, "label": 1, "numberOfPossibleDays": 1, "editable": 1, "selectedDate": 1, "deliveryDays": 1, "products": [ { "key": "item-four", "name": "item four", "tags": ["a", "o"] }, { "key": "item-five", "name": "item-five", "tags": ["s", "a", "b"] } ] } ]
需要查询所有包含标签a的文档,并且返回时过滤掉products数组中包含a的元素,预期结果如下:
[ { "_id": ObjectId("5a934e000102030405000000"), "deliveryDays": 1, "editable": 1, "item": "journal", "label": 1, "numberOfPossibleDays": 1, "products": [ { "key": "item-one", "name": "item one", "tags": ["v", "b"] } ], "qty": 25, "selectedDate": 1, "sortOrder": 1, "status": "A", "weekNumber": 1 }, { "_id": ObjectId("5a934e000102030405000001"), "deliveryDays": 1, "editable": 1, "item": "notebook", "label": 1, "numberOfPossibleDays": 1, "products": [], "qty": 1, "selectedDate": 1, "sortOrder": 1, "status": "b", "weekNumber": 1 } ]
目前使用$filter在投影阶段过滤数组时,必须手动枚举所有需要返回的字段,代码过于冗长,希望找到无需逐个指定字段、自动返回所有字段的方法。
解决方案
使用MongoDB的聚合管道,通过$set(或$addFields)操作符可以保留所有原有字段,仅修改products数组,无需手动枚举其他字段:
db.collection.aggregate([ // 匹配包含标签'a'的文档 { $match: { "products.tags": "a" } }, // 过滤products数组,仅保留不包含标签'a'的元素 { $set: { products: { $filter: { input: "$products", cond: { $not: { $in: ["a", "$$this.tags"] } } } } } } ])
说明
$match阶段:筛选出包含标签a的products的文档,和原查询的匹配条件一致。$set阶段:替换products字段为过滤后的数组,文档中其他所有字段会自动保留,不需要手动列出。如果使用MongoDB 4.2之前的版本,$addFields操作符效果相同(字段存在时会替换,不存在时添加)。$filter的cond条件:使用$not和$in组合,过滤掉包含a标签的products元素,符合预期结果要求。
执行该聚合查询后,会自动返回所有字段,同时products数组仅保留不包含a的元素,完全符合需求。
内容的提问来源于stack exchange,提问作者Harpinder Singh
相关产品推荐
相关产品推荐

