首页/数据/NoSQL 速查/数组查询 $all / $size / $elemMatch
MongoDB99 条

数组查询 $all / $size / $elemMatch

数组字段支持等值命中任一元素、$all 全含、$size 精确长度;$elemMatch 要求同一条元素满足多个条件。

NoSQL 速查数据更新于 2026-10-13

数组查询怎么下手

数组字段的查询分几种形态:直接写等值表示「任一元素等于它」,$all 要求全部包含,$size 限定精确长度,$elemMatch 要求同一条元素同时满足多个条件。分清这几种语义是写好数组查询的前提,也是实践中最容易出错的地方。

基本信息

命中任一元素{ tags: "mongo" }
全部包含$all: ["mongo", "index"]
精确长度$size: 3,不能与其他条件共用同一字段
同元素组合$elemMatch: { $gt: 80, $lt: 90 }
索引行为数组字段上的索引是多键索引,$elemMatch 更利于收敛范围

典型使用场景

  • 标签筛选:命中包含某个标签的文档
  • 多重条件:要求同时具备若干标签
  • 区间判定:分数数组里存在落在某区间的元素
  • 长度过滤:找出元素数量不符合预期的脏数据
  • 嵌套数组:数组里存子文档时按子字段过滤

常用写法

常用写法
// 命中任一元素
 db.posts.find({ tags: "mongo" })

// 要求全部包含
 db.posts.find({ tags: { $all: ["mongo", "index"] } })

// 数组内存在落在 80 到 90 之间的元素
 db.posts.find({ scores: { $elemMatch: { $gt: 80, $lt: 90 } } })

// 精确长度过滤:元素个数为 3
 db.posts.find({ tags: { $size: 3 } })

// 嵌套子文档:按子字段过滤,组合条件用 $elemMatch
 db.orders.find({ "items.sku": "A-1" })
 db.orders.find({ items: { $elemMatch: { sku: "A-1", qty: { $gt: 2 } } } })

写法与语义

写法语义常见误用
{ tags: "mongo" }任一元素等于该值当成要求所有元素都等于它
$all必须包含列出的全部值顺序无关,但每个值都要存在
$size: 3元素数量精确等于 3与其他条件共用同一字段时不生效
$elemMatch同一条元素满足全部条件不写时会变成不同元素各自满足
$size 不能与其他条件共用同一个字段表达式,精确长度判断只能单独写;需要长度加其他条件并存时,用聚合管道或预先落一个长度字段。
对数组子文档做组合条件时优先用 $elemMatch:它把条件约束在同一条元素上,与「数组字段加点号」的宽松语义完全不同。

易错点

  • { scores: { $gt: 80, $lt: 90 } } 可能由两个不同元素分别满足,组合条件务必用 $elemMatch
  • $size 与同字段的其他条件写在一条查询里不会按预期收窄范围,需要两者并存时应改用聚合管道
  • 把数组字段的等值查询理解为「全部元素都要匹配」,实际只要有任一元素命中就返回,结果比预期多
  • 多层嵌套数组上同时用点号与 $elemMatch,层级写错不会报错但结果为空,排查前先用 findOne 看一条真实结构

数据来源与参考

  • MongoDB Manual: Query an Array
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌