$exists: true用于检查字段是否存在(含null),$type可限定字段值类型(如"object"),$size能校验对象键数量,但精确结构匹配需组合操作符或应用层处理。

用 $exists 查特定键存在但不关心值
想确认文档里有没有某个字段(比如 status),不管它是不是 null、空字符串或数字,只要字段名出现过就行——这时候 $exists: true 是最直接的。但要注意:它对 undefined 和缺失字段都返回 true,MongoDB 本身不存 undefined,所以实际等价于“字段被显式写入过”。
-
{ status: { $exists: true } }匹配{ status: "active" }、{ status: null }、{ status: "" } - 不匹配
{}或{ name: "a" }(字段完全没出现) - 如果业务上需要排除
null,得额外加$ne: null
用 $type 防止字段存在但类型错乱
光有键不够,有时你还得确保它的值是对象(比如 address 必须是嵌套文档,不能是字符串或数组)。$type 能锁死类型,避免下游解析崩溃。
-
{ address: { $exists: true, $type: "object" } }只匹配{ address: { city: "Beijing" } } - 会跳过
{ address: "Beijing" }(字符串)、{ address: [] }(数组)、{ address: null } - 注意:
"object"对应 BSON 类型3,不是 JavaScript 的typeof结果;数组是"array"(类型4)
用 $eq + $size 做对象“精确结构”校验(谨慎!)
真正想表达“这个字段必须是一个且仅有一个键的对象”,比如只允许 { role: "admin" },不允许多一个 scope 或少一个 role——MongoDB 没有原生的“对象结构精确匹配”操作符,得组合绕行。
-
{ "meta": { $exists: true, $type: "object", $size: 1 } }可以筛出单字段对象,但前提是meta里没有数组或嵌套对象($size只算顶层键) - 如果
meta: { a: 1, b: [1,2] },$size仍返回2,无法识别b是数组 - 更严苛的校验(如键名必须是
role且不能有其他键)只能靠应用层过滤,或用聚合管道$objectToArray+$setIsSubset,但性能差、不支持索引
为什么 $eq: {} 不等于“字段是空对象”
新手常写 { config: { $eq: {} } } 想找空对象,结果查不到任何文档——因为 MongoDB 的 $eq 对对象做的是**字段名+值的全量深度比对**,而空对象 {} 在查询中会被解释为“任意对象都满足”,实际行为等价于 { config: { $exists: true } }。
- 真正匹配空对象要用
{ config: { $size: 0 } }(前提是字段存在且是对象) - 或者更稳妥:
{ config: { $exists: true, $type: "object", $size: 0 } } - 如果
config可能是null或缺失,$size会报错,必须先用$exists过滤










