为何MongoDB查询数组同时包含两个值的两条语句一条生效一条不生效
MongoDB两条查询结果不一致原因解析
核心原因是 BSON对象的重复键覆盖规则 导致第二条查询的实际生效条件和预期不符:
- MongoDB的查询条件本质是BSON结构,同一对象层级下如果出现重复的键,只有最后出现的键值对会生效,前面的会被直接覆盖。
两条查询的执行逻辑差异
- 第一条正确查询的逻辑:
使用$and把两个products字段的校验条件拆成了独立的判断项,两个条件需要同时满足才会命中:
- 校验1:
products数组中至少存在一个元素的productType匹配value1 - 校验2:
products数组中至少存在一个元素的productType匹配value2
刚好符合你要求的「数组同时包含两个值」的查询需求,因此返回的474是正确结果。
- 第二条错误查询的逻辑:
你把两个$elemMatch操作符都放在了同一个products字段的对象值中,相当于对products字段重复定义了两次$elemMatch规则:
- 实际执行时,前面的
$elemMatch: { productType: /value1/i }会被后面的$elemMatch: { productType: /value2/i }完全覆盖 - 最终生效的查询条件仅要求
segment匹配正则、且products数组存在至少一个元素匹配value2,会把只包含value2、以及同时包含两个值的文档全部统计进去,因此返回的698结果大于正确值。
拓展:更简洁的正确写法
你还可以用$all操作符简化查询,不用多次写$elemMatch:
db.person.find({ segment: /a/i, "products.productType": { $all: [/value1/i, /value2/i] } }).count()
这个写法和第一条正确查询的效果完全等价。
内容的提问来源于stack exchange,提问作者Everton
相关产品推荐
相关产品推荐

