$regex带括号通常失效,因括号多出现在非前缀结构(如/^(abc|def)/或/a(bc)/),破坏mongodb对「确定性左锚定前缀」的识别;仅^abc等纯字面量开头、无分支无捕获无中间通配符的模式才可能走b-tree索引。

为什么$regex带括号就失效了?
不是括号本身导致索引失效,而是括号常出现在非前缀结构里,比如/^(abc|def)/或/a(bc)/——这些写法破坏了 MongoDB 对「确定性左锚定前缀」的识别。它只认得形如^abc这种字面量开头、无分支、无捕获、无中间通配符的模式。
$regex前缀匹配的硬性条件
必须同时满足以下全部条件,才可能触发 B-tree 索引扫描(IXSCAN):
-
$regex值必须是字符串字面量或正则字面量,且以^开头(不能是变量拼接,也不能是^.*abc) - 不能含
i、m、s、x等$options,除非索引和查询都显式声明一致的collation - 不能有分组
(...)、选择|、重复量词+?{n}或任意字符.出现在前缀之后(例如^ab.c中.中断了确定性) - 字段上必须已存在对应方向的普通索引,如
{name: 1},且未被其他条件(如类型不匹配)绕过
常见带括号但能走索引的例外写法
极少数括号用法仍可被识别为前缀,前提是它们不改变「从开头严格匹配固定字符串」的本质:
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
-
^abc(?:def)?:?:是非捕获组,MongoDB 可能将其折叠为^abcdef?,但不保证所有版本支持,慎用 -
^abc(?=xyz):先行断言不消耗字符,但 MongoDB 实际不支持该语法,会直接报错或退化为全表扫 - 真正安全的写法只有
^abc、^abcd这类纯字面量前缀;所有括号建议先在应用层做逻辑拆分,再转成多个$or+ 独立^查询
怎么快速验证是否走索引?
别猜,用explain("executionStats")看真实执行计划:
- 如果
"stage": "COLLSCAN",说明没走索引,无论你写了多“规范”的正则 - 如果
"stage": "IXSCAN"但"nReturned"远小于"nReturned",可能是通配符索引在瞎扫,不是有效命中 - 检查
"indexName"字段是否为你预期的索引名;若为空或为$**,说明用了通配符索引而非目标字段索引
真正难的不是写出^开头的正则,而是让业务接受「搜索必须输入前几个确定字符」这个约束——否则就得换$text或预处理字段。










