$exists: false 是唯一精准判断字段缺失的方式,$type 只作用于已存在字段,对缺失字段无感知;查 null 值或缺失需用 $or 组合 "$eq": null 和 "$exists": false。

直接用 $exists: false,别碰 $type。
为什么 $type 查不到缺失字段?
$type 只作用于**已存在字段**,对缺失字段完全无感知。它不是“查类型”,而是“查已有字段的类型值”。文档里压根没这个字段,$type 连参与判断的机会都没有,自然返回空结果——这不是匹配失败,是根本没进筛选逻辑。
常见错误写法:{"field": {"$type": "null"}} 或 {"field": {"$type": 10}},它们只匹配 {"field": null},不匹配 {} 或 {"other": "x"}(即 field 完全不存在)。
-
{"field": null}实际等效于{"$or": [{"field": {"$type": 10}}, {"field": {"$exists": false}}]},语义混杂 -
{"field": {"$exists": false}}才是唯一精准表达“字段不存在”的方式 - 所有 MongoDB 版本都支持
$exists: false,无兼容性风险
聚合管道里 $match 遇到缺失字段会怎样?
$match 阶段对缺失字段的处理非常明确:直接过滤掉。比如写 {"$match": {"price": {"$gt": 100}}},任何不含 price 字段的文档都会被剔除,不会进入后续阶段。
这常导致意外丢数据,尤其当你想“保留缺失 price 的文档做 fallback 处理”时。
- 若需保留缺失字段的文档,必须显式写出
{"$or": [{"price": {"$gt": 100}}, {"price": {"$exists": false}}]} - 不能依赖
price: null或price: {"$type": "null"}来兜底 - 在
$project中用$ifNull也无效——它只认“字段存在但值为 null/undefined”,对缺失字段静默跳过
如何安全地组合 null 和缺失字段查询?
要同时捕获 {"field": null} 和 {}(field 缺失),必须用 $or 显式并列条件,不能偷懒。
例如查所有 “price 为 null 或根本没 price 字段” 的文档:
{ "$match": { "$or": [ { "price": { "$eq": null } }, { "price": { "$exists": false } } ] } }
-
"$eq": null精准命中值为 BSON null 的字段(注意不是 JavaScriptnull,驱动层已自动转换) -
"$exists": false精准命中字段完全不存在的文档 - 二者缺一不可;漏掉任一个,就会漏掉一类真实数据
- 不要用
"price": null简写——它在$match中行为等价于上面的$or,但语义模糊、可读性差、易引发协作误解
真正容易被忽略的是:BSON null 和字段缺失,在存储、索引、聚合各阶段都是严格区分的两个状态。硬凑 $type 去覆盖缺失场景,轻则结果不准,重则升级后行为突变——因为底层语义根本不同。


















