MongoDB如何查询数组长度符合条件的数据?

作者:袖梨 2026-08-06

$size只能匹配数组长度等于某具体数值;要实现大于、小于等条件,必须用$expr配合$size,因$size语法强制要求数字字面量,不支持操作符。

直接用 $size 只能查「长度等于某值」;要查「大于」「小于」或带类型安全的条件,必须用 $expr + $size 组合,$where 已不推荐且多数云服务禁用。

为什么 $size 不能写 {$gt: 2}

$size 是硬性限制操作符,语法只接受数字字面量,不是表达式。写成 {"tags": {"$size": {"$gt": 2}}} 会立刻报错:errmsg: "size operator must be followed by a number"

常见误用场景:

  1. 想查「至少 3 个标签」却写了 {"tags": {"$size": {"$gte": 3}}}
  2. 嵌套字段用错路径,比如 {"comments.authors": {"$size": 0}} 但实际字段是 comments.authorIds
  3. 忽略字段缺失行为:若文档没有 tags 字段,或该字段为 null/undefined,它不会被匹配(不是返回空数组)

用 $expr 实现「长度大于 N」或「长度在范围内」

$expr 允许你在查询中使用聚合表达式,支持 $size$gt$isArray 等,且不执行 JS,性能可控。

正确写法示例:

  1. tags 长度 > 2:{"$expr": {"$gt": [{"$size": "$tags"}, 2]}}
  2. tags 长度 ≥ 1 且 ≤ 5:{"$expr": {"$and": [{"$gte": [{"$size": "$tags"}, 1]}, {"$lte": [{"$size": "$tags"}, 5]}]}}
  3. 加类型校验防崩溃:{"$expr": {"$and": [{"$isArray": "$tags"}, {"$gt": [{"$size": "$tags"}, 2]}]}}

⚠️ 注意:$expr 中所有字段引用必须带 $ 前缀(如 "$tags"),不能写 "tags";否则整个条件静默失效。

替代技巧:用字段存在性模拟「最小长度」

当只需快速判断「至少 N+1 个元素」且不想用 $expr,可用数组索引存在性代替(适用于简单场景):

  1. tags 至少有 3 个元素 → 检查第 2 个位置是否存在:{"tags.2": {"$exists": true}}
  2. tags 至少有 1 个元素 → {"tags.0": {"$exists": true}}

这个方法快、可走索引,但有明显限制:

  1. 无法区分 ["a"]["a", null](后者 tags.1 存在但值为 null
  2. 不能用于「最大长度」或「精确范围」
  3. 字段为非数组类型(如字符串)时可能误匹配("abc".2 合法)

真正上线前必须检查的三件事

数组长度查询容易在生产环境翻车,尤其数据结构不统一时:

  1. 确认目标字段是否始终为数组类型——用 $isArray 显式校验比依赖业务逻辑更可靠
  2. 评估是否值得建「预计算字段」:比如存一个 tagsCount 整数并建索引,比每次算 $size 快得多
  3. 避免在大集合上无索引使用 $expr:它无法高效利用复合索引,{tags: 1} 索引对 $expr 中的 $size 几乎无效

相关文章

精彩推荐