用 $regex 模糊查询必须显式创建 regexp 对象,字符串直接传无效;数组字段需用 $elemmatch;仅前缀正则(如 /^keyword/)可走索引;多字段 or 查询须逐个加 $options: 'i' 并转义用户输入。

用 $regex 做模糊查询时,必须显式构造 RegExp 对象
直接传字符串给 $regex 不会生效,比如 { name: { $regex: '未来' } } 实际查不到任何结果。MongoDB 驱动在 Node.js 中不支持字符串自动转正则,必须用 new RegExp() 显式创建。
-
new RegExp('未来')等价于 MongoDB shell 中的/未来/,但不带修饰符 - 要忽略大小写,得加
"i":new RegExp('未来', 'i') - 如果用户输入含特殊字符(如
.、*、+),必须先转义,否则会触发意外匹配或报错 - Mongoose 模型调用
.find()时,字段值为RegExp实例才被正确识别为正则条件
数组字段模糊匹配要用 $elemMatch + $regex
对数组字段(如 tags: ['mongodb', 'nodejs'])直接写 { tags: /mongo/ } 是无效的——它会尝试把整个数组对象当字符串去匹配,而不是检查每个元素。
ZenHeart zenlink 与 zenlink-mcp 为 OpenClaw,涵盖安装、MCP 注册、钩子接线、入站轮询及升级维护。
- 正确写法是:
{ tags: { $elemMatch: { $regex: /mongo/, $options: 'i' } } } - 如果不加
$elemMatch,MongoDB 会把数组整体转成字符串(如"['mongodb','nodejs']")再匹配,逻辑完全错误 - 若只需任意一个元素匹配,
$elemMatch是必须的;若需所有元素都满足某条件,则用$all配合多个正则(极少用)
性能差的根源常在正则写法和索引缺失
模糊查询慢,90% 是因为用了全表扫描。MongoDB 只对「前缀正则」能走索引,比如 /^mongodb/;而 /mongodb/ 或 /^.*mongodb/ 无法利用索引。
- 能走索引的写法:
new RegExp('^' + keyword)(用户搜“mongo”,匹配“mongodb”“mongoDB”等开头词) - 不能走索引的写法:
new RegExp(keyword)(任意位置匹配)、new RegExp('.*' + keyword)(等同于无前缀) - 已有文本索引(
text索引)时,优先用$text: { $search: 'keyword' }替代$regex,速度快且支持分词、权重、停用词 - 复合查询中,把
$regex条件和其他高选择性条件(如status: 'published')组合,并确保非正则字段已建索引,可大幅缩小扫描范围
多字段 or 查询别漏掉 $options 和安全转义
常见需求是「在 title、desc、author 任一字段中匹配关键词」,用 $or 很自然,但容易踩两个坑:大小写敏感、注入风险。
- 每个
$regex子句都要单独加$options: 'i',写成{ $or: [{ title: { $regex: reg, $options: 'i' } }, { desc: { $regex: reg, $options: 'i' } }] } - 用户输入必须转义正则元字符,可用简单函数:
keyword.replace(/[.*+?^${}()|[]\]/g, '\$&') - 避免拼接字符串生成正则,例如
new RegExp('.*' + userInput + '.*')—— 一旦userInput是.*,就变成全量匹配 - 前端传空字符串或空白符时,应提前拦截,否则
new RegExp('')会匹配所有文档










