首页/数据/NoSQL 速查/$regex 正则查询
MongoDB99 条

$regex 正则查询

字符串正则匹配:预编译正则对象或 $regex/$options 表达式都可;只有锚定前缀(^)且区分大小写时才有机会走索引。

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

$regex 与索引的关系

$regex 用正则匹配字符串字段,可以写成查询时的正则字面量,也可以用操作符形式声明模式与选项。使用时最需要记住的是性能规则:只有以 ^ 锚定前缀、且不启用忽略大小写的模式,索引才能利用前缀范围缩小扫描;其余写法一律退化为全集合逐文档匹配。

基本信息

写法一{ name: /alice/i } 正则字面量,可带标志
写法二{ name: { $regex: "^alice", $options: "i" } }
可走索引以 ^ 锚定前缀且不使用 i 选项
常用选项i 忽略大小写、m 多行、s 让点号匹配换行、x 忽略空白
适用版本MongoDB 3.6+ 行为一致

示例

示例
// 前缀锚定:索引可用(注意没有 i 选项)
db.users.find({ name: { $regex: "^张" } })

// 前缀加忽略大小写:即使有 ^ 也会退化为全集合扫描
db.users.find({ name: { $regex: "^zhang", $options: "i" } })

// 子串匹配:没有 ^,必然全集合扫描
db.users.find({ email: { $regex: "example\\.com" } })

// $in 里只接受正则字面量,不接受 $regex 表达式对象
db.users.find({ name: { $in: [ /^zhang/, /^wang/ ] } })

// 用 explain 确认扫描文档数与 nReturned 的比例
db.users.find({ name: /alice/i }).explain("executionStats")

典型使用场景

  • 前缀过滤:按姓名、单号、路径前缀筛选,能吃到索引
  • 模糊包含:备注、日志文本的子串检索,需接受扫描代价
  • 大小写不敏感:邮箱、产品名等场景
  • 数据清洗:用正则定位格式异常记录再批量修正
  • 反向筛选:$not 包正则排除测试账号与脏数据

模式与扫描行为

写法扫描行为建议
/^abc/可用索引前缀范围扫描优先使用这种形态
/^abc/i忽略大小写,全集合扫描数据量大时改用规范化字段
/abc/全集合扫描配合其他可索引条件缩小范围
/abc$/后缀匹配,无索引可用考虑反向存储或外部检索
把用户输入直接拼进正则有两个风险:语义被用户左右(词注入),以及嵌套量词触发的灾难性回溯让服务端 CPU 飙高、请求堆积。入库前应校验输入长度与字符集,必要时改用固定模式匹配。
正则对数组字段会逐个元素匹配,命中任一元素即返回整个文档;正则也不做类型转换,数字、日期字段要用范围条件而不是正则匹配。

易错点

  • $in 数组里只接受 JavaScript 正则字面量,写成 $regex 表达式对象不被支持,多模式匹配要么用字面量要么拆成 $or
  • 不用 ^ 锚定或带上 i 选项,索引无法缩小边界,退化为全集合扫描
  • 用户输入直接拼入正则存在注入与灾难性回溯风险,必须先校验再构造模式
  • 正则不会做类型转换,对数字或日期字段使用正则等于扫全表且匹配不到预期结果
  • 后缀匹配无法走索引,高频场景要考虑额外存储反向字符串或改用外部检索引擎

数据来源与参考

  • MongoDB Manual: $regex
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌