MongoDB $exists查询结果不符预期的技术咨询
MongoDB查询结果差异原因解析
两个核心问题导致第三个查询结果异常
1. BSON重复键的覆盖问题
你写的第三个查询:
{"veicolo.nazione.isoAlpha3":{$exists:1}, "veicolo.nazione.isoAlpha3":{$ne:"ITA"}}
在MongoDB使用的BSON格式中,同一个键不能重复出现,解析时后面的键值对会直接覆盖前面的。也就是说,这个查询实际执行的是:
{"veicolo.nazione.isoAlpha3":{$ne:"ITA"}}
$exists:1的条件完全没有生效,这是结果超出预期的第一个原因。
2. $ne操作符的匹配规则
MongoDB中$ne操作符的逻辑是:
- 匹配字段值不等于指定值的文档;
- 同时匹配该字段完全不存在的文档(因为不存在的字段会被视为
null,而null != "ITA")。
所以当执行{"veicolo.nazione.isoAlpha3":{$ne:"ITA"}}时:
- 会包含所有
veicolo.nazione.isoAlpha3存在且不等于"ITA"的文档(也就是前两个查询里的29条); - 还会包含所有没有
veicolo字段、或者有veicolo但没有nazione子字段、或者有nazione但没有isoAlpha3子字段的文档——这些文档中veicolo.nazione.isoAlpha3都不存在,被视为null,满足null != "ITA"的条件,所以全部被返回,最终结果变成500多条。
前两个查询为什么结果正常
前两个查询都通过额外的条件限制了上层字段的存在:
- 第一个查询用
"veicolo":{$exists:1}确保必须有veicolo字段; - 第二个查询用
"veicolo.nazione":{$exists:1}确保必须有veicolo.nazione字段;
这两个条件先过滤掉了所有缺失上层字段的文档,再筛选isoAlpha3不等于"ITA"的记录,所以结果只有符合要求的29条。
正确的查询写法(如果想同时满足字段存在且不等于指定值)
如果要实现“veicolo.nazione.isoAlpha3存在且不等于"ITA"”,应该把两个条件合并到同一个字段的查询对象里:
{"veicolo.nazione.isoAlpha3":{$exists: true, $ne: "ITA"}}
这样既会过滤掉字段不存在的文档,又会筛选出字段值不等于"ITA"的记录,结果就会和前两个查询一致。
内容的提问来源于stack exchange,提问作者Danio Quero
相关产品推荐
相关产品推荐

