Skip to content

MongoDB - 正则表达式

MongoDB - 正则表达式(Regex)查询

Section titled “MongoDB - 正则表达式(Regex)查询”

MongoDB 在查询中支持正则表达式,用于高级字符串模式匹配。您可以使用 $regex 操作符或简写 /pattern/ 语法。MongoDB 使用 PCRE(Perl 兼容正则表达式)引擎。

与文本搜索不同,您不需要创建特殊索引来使用 regex,但性能是一个关键考量。让我们使用一个样本 posts 集合:

db.posts.insertOne({
"post_text": "enjoy the mongodb articles on w3",
"tags": [
"mongodb",
"w3"
]
});
db.posts.insertOne({
"post_text": "hey! this is my post on TutorialsPoint",
"tags": ["TutorialsPoint"]
});

以下查询查找所有 post_text 包含子字符串 “w3” 的帖子。

// 使用 $regex 操作符
db.posts.find({ post_text: { $regex: "w3" } });
// 简写语法(通常在 shell 中为方便起见使用)
db.posts.find({ post_text: /w3/ });

要使搜索不区分大小写,请使用 i 选项。这将匹配 w3、TutorialsPoint、TUTORIALSPOINT 等。

// 使用 $options 参数
db.posts.find({ post_text: { $regex: "w3", $options: "i" } });
// 带有 'i' 标志的简写语法
db.posts.find({ post_text: /w3/i });

您可以将 regex 应用于数组中的元素。这对于搜索标签非常有用。以下查询查找任何标签以单词 “mongo” 开头的帖子。

// '^' 字符将匹配锚定到字符串的开头
db.posts.find({ tags: { $regex: "^mongo", $options: "i" } });

这是在 MongoDB 中使用 regex 最关键的方面。性能会根据您编写表达式的方式显著不同。

最佳实践:锚定、区分大小写的前缀

Section titled “最佳实践:锚定、区分大小写的前缀”

如果字段上存在常规 B 树索引,MongoDB 可以使用它来优化“前缀表达式”的 regex 查询。这意味着表达式锚定在字符串的开头(^)。

// 首先,在 'post_text' 字段上创建索引
db.posts.createIndex({ post_text: 1 });
// 此查询可以使用索引,因为它是一个前缀表达式。
// 它速度快,因为它只需要扫描索引中以 'enjoy' 开头的部分。
db.posts.find({ post_text: { $regex: "^enjoy" } });

常见陷阱:非锚定或不区分大小写的 Regex

Section titled “常见陷阱:非锚定或不区分大小写的 Regex”

未锚定到字符串开头或使用 i 选项进行不区分大小写匹配的 regex 查询,无法有效使用标准 B 树索引。这些查询将导致集合扫描(COLLSCAN),这在大型集合上会非常慢。

// 警告:性能瓶颈
// 此查询将扫描集合中的每个文档,忽略索引。
db.posts.find({ post_text: { $regex: "articles", $options: "i" } });

专业提示:何时使用 Regex 与文本搜索

Section titled “专业提示:何时使用 Regex 与文本搜索”
  • 使用 Regex 进行精确的、基于模式的匹配,当你需要查找特定的结构模式(例如,电子邮件格式、SKU)或进行索引优化的前缀搜索时。
  • 使用 文本搜索 进行自然语言查询,搜索任意位置的单词或短语,按相关性排序,并利用特定语言的词干提取。它几乎总是搜索人工编写文本的更好选择。