$size只能匹配数组长度等于某具体数值;要实现大于、小于等条件,必须用$expr配合$size,因$size语法强制要求数字字面量,不支持操作符。
直接用 $size 只能查「长度等于某值」;要查「大于」「小于」或带类型安全的条件,必须用 $expr + $size 组合,$where 已不推荐且多数云服务禁用。
$size 是硬性限制操作符,语法只接受数字字面量,不是表达式。写成 {"tags": {"$size": {"$gt": 2}}} 会立刻报错:errmsg: "size operator must be followed by a number"。
常见误用场景:
{"tags": {"$size": {"$gte": 3}}}
{"comments.authors": {"$size": 0}} 但实际字段是 comments.authorIds
tags 字段,或该字段为 null/undefined,它不会被匹配(不是返回空数组)$expr 允许你在查询中使用聚合表达式,支持 $size、$gt、$isArray 等,且不执行 JS,性能可控。
正确写法示例:
tags 长度 > 2:{"$expr": {"$gt": [{"$size": "$tags"}, 2]}}
tags 长度 ≥ 1 且 ≤ 5:{"$expr": {"$and": [{"$gte": [{"$size": "$tags"}, 1]}, {"$lte": [{"$size": "$tags"}, 5]}]}}
{"$expr": {"$and": [{"$isArray": "$tags"}, {"$gt": [{"$size": "$tags"}, 2]}]}}
⚠️ 注意:$expr 中所有字段引用必须带 $ 前缀(如 "$tags"),不能写 "tags";否则整个条件静默失效。
当只需快速判断「至少 N+1 个元素」且不想用 $expr,可用数组索引存在性代替(适用于简单场景):
tags 至少有 3 个元素 → 检查第 2 个位置是否存在:{"tags.2": {"$exists": true}}
tags 至少有 1 个元素 → {"tags.0": {"$exists": true}}
这个方法快、可走索引,但有明显限制:
["a"] 和 ["a", null](后者 tags.1 存在但值为 null)"abc".2 合法)数组长度查询容易在生产环境翻车,尤其数据结构不统一时:
$isArray 显式校验比依赖业务逻辑更可靠tagsCount 整数并建索引,比每次算 $size 快得多$expr:它无法高效利用复合索引,{tags: 1} 索引对 $expr 中的 $size 几乎无效