MongoDB聚合:空数组更新为[{}],非空数组保留原值异常问题
MongoDB聚合查询异常问题解决
问题背景
现有MongoDB文档结构如下:
[ { "name": "demo", "data": [ { "isvalid": true, "mdata": [{"name": "hello"}] }, { "isvalid": false, "mdata": [] }, { "isvalid": true, "mdata": [{"name": "hello"}] } ] } ]
需求:
- 基于
data.isvalid字段执行聚合操作,仅保留匹配条件的数组元素 - 对保留的元素,若
mdata为空数组则更新为[{}],非空则保留原值
原查询中,匹配data.isvalid: false的逻辑正常运行,但匹配data.isvalid: true时,非空的mdata被重复追加,不符合预期。
问题原因分析
原查询的$addFields阶段直接操作data.mdata,此时data是过滤后的数组,data.mdata会生成一个包含所有元素mdata的二维数组(例如[[{"name":"hello"}], [{"name":"hello"}]])。当用$size判断长度时,该二维数组长度为2,触发else分支,直接将整个二维数组赋值给每个元素的mdata,最终导致重复追加问题。
修正后的聚合查询
需遍历data数组的每个元素,单独处理每个元素的mdata,通过$map配合$filter实现需求:
匹配data.isvalid: true的查询
db.collection.aggregate([ { "$match": { "data.isvalid": true } }, { "$set": { "data": { "$map": { "input": { "$filter": { "input": "$data", "cond": { "$eq": ["$$this.isvalid", true] } } }, "as": "item", "in": { "isvalid": "$$item.isvalid", "mdata": { "$cond": { "if": { "$eq": [{ "$size": "$$item.mdata" }, 0] }, "then": [{}], "else": "$$item.mdata" } } } } } } } ])
匹配data.isvalid: false的查询(统一逻辑)
db.collection.aggregate([ { "$match": { "data.isvalid": false } }, { "$set": { "data": { "$map": { "input": { "$filter": { "input": "$data", "cond": { "$eq": ["$$this.isvalid", false] } } }, "as": "item", "in": { "isvalid": "$$item.isvalid", "mdata": { "$cond": { "if": { "$eq": [{ "$size": "$$item.mdata" }, 0] }, "then": [{}], "else": "$$item.mdata" } } } } } } } ])
逻辑说明
- 先用
$filter筛选出符合isvalid条件的data元素 - 通过
$map遍历筛选后的元素,对每个元素的mdata单独判断:空数组则替换为[{}],非空则保留原值 - 统一逻辑后,两种匹配场景都能正确处理,避免了二维数组赋值导致的重复问题
内容的提问来源于stack exchange,提问作者Raghava Ch
相关产品推荐
相关产品推荐

