如何编写Mongo查询筛选数组元素全满足指定条件的文档?
解决MongoDB数组全元素匹配查询问题
问题分析
你当前使用的查询条件{a : {b : true}}会返回所有包含至少一个{b:true}元素的数组文档,这就是为何_id为2的文档也被返回——它的数组里确实存在一个符合条件的元素。而你需要的是**数组中所有元素都满足b:true**的文档。
正确查询方法
方法1:使用$not + $elemMatch
通过排除数组中存在b:false的文档,间接得到所有元素b均为true的结果:
db.collection.find({ a: { $not: { $elemMatch: { b: false } } } })
原理:$elemMatch: {b:false}会匹配数组中存在至少一个b:false的文档,加上$not后就会排除这些文档,剩下的就是所有元素b都为true的目标文档。
方法2:使用聚合表达式$expr结合$allElementsTrue
如果你的MongoDB版本在3.2及以上,可以用聚合函数直接判断数组所有元素是否满足条件:
db.collection.find({ $expr: { $allElementsTrue: { $map: { input: "$a", as: "item", in: "$$item.b" } } } })
原理:$map会把数组a的每个元素转换成对应的b字段值,生成一个布尔数组;$allElementsTrue则判断这个布尔数组里的所有值是否都是true,只有满足该条件的文档才会被返回。
为什么$all不适用?
$all的作用是匹配数组中同时包含所有指定元素,比如{a: {$all: [{b:true}]}}其实和{a:{b:true}}效果一致,只要数组里有至少一个{b:true}就会匹配,无法保证所有元素都符合要求。
内容的提问来源于stack exchange,提问作者Max Friederichs
相关产品推荐
相关产品推荐

