MongoDB聚合管道中如何根据数组所有元素添加自定义字段
MongoDB聚合:添加suppliersPaid字段判断所有供应商缴费状态
问题场景
原始集合包含如下文档:
[ { "_id": { "$oid": "63f06283b80a395adf27780d" }, "suppliers": [ { "name": "S1", "duesPaid": true }, { "name": "S2", "duesPaid": true } ] }, { "_id": { "$oid": "63f06283b80a395adf27780e" }, "suppliers": [ { "name": "S1", "duesPaid": true }, { "name": "S2", "duesPaid": false } ] } ]
需要为每个文档添加自定义字段suppliersPaid,规则是:当suppliers数组至少包含1个元素,且所有元素的duesPaid字段值为true时,该字段设为true,否则设为false。期望输出如下:
[ { "_id": { "$oid": "63f06283b80a395adf27780d" }, "suppliers": [ { "name": "S1", "duesPaid": true }, { "name": "S2", "duesPaid": true } ], "suppliersPaid": true }, { "_id": { "$oid": "63f06283b80a395adf27780e" }, "suppliers": [ { "name": "S1", "duesPaid": true }, { "name": "S2", "duesPaid": false } ], "suppliersPaid": false } ]
错误尝试分析
- 第一次尝试使用
$elemMatch作为聚合表达式,报错Invalid $addFields :: caused by :: Unrecognized expression '$elemMatch',因为$elemMatch是查询操作符,不能直接在聚合表达式中使用。 - 第二次移除
$elemMatch后的写法,MongoDB无法正确解析条件,导致所有文档的suppliersPaid都被错误设为true。
正确聚合实现方案
方案一:使用$map + $allElementsTrue
[ { "$addFields": { "suppliersPaid": { "$and": [ // 判断suppliers数组非空 { "$gte": [ { "$size": "$suppliers" }, 1 ] }, // 将suppliers数组转换为duesPaid的布尔数组,再检查所有元素是否为true { "$allElementsTrue": [ { "$map": { "input": "$suppliers", "as": "s", "in": "$$s.duesPaid" } } ] } ] } } } ]
方案二:使用$reduce遍历数组
[ { "$addFields": { "suppliersPaid": { "$and": [ // 判断suppliers数组非空 { "$gte": [ { "$size": "$suppliers" }, 1 ] }, // 遍历数组,累计判断所有duesPaid是否为true { "$reduce": { "input": "$suppliers", "initialValue": true, "in": { "$and": [ "$$value", "$$this.duesPaid" ] } }} ] } } } ]
两种方案逻辑一致:先通过$size确保数组非空,再通过聚合表达式校验数组中所有duesPaid的状态,只要有一个为false,最终结果就为false。
内容的提问来源于stack exchange,提问作者CodeoftheWarrior
相关产品推荐
相关产品推荐

