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"]});使用 $regex 操作符
Section titled “使用 $regex 操作符”以下查询查找所有 post_text 包含子字符串 “w3” 的帖子。
// 使用 $regex 操作符db.posts.find({ post_text: { $regex: "w3" } });
// 简写语法(通常在 shell 中为方便起见使用)db.posts.find({ post_text: /w3/ });不区分大小写匹配
Section titled “不区分大小写匹配”要使搜索不区分大小写,请使用 i 选项。这将匹配 w3、TutorialsPoint、TUTORIALSPOINT 等。
// 使用 $options 参数db.posts.find({ post_text: { $regex: "w3", $options: "i" } });
// 带有 'i' 标志的简写语法db.posts.find({ post_text: /w3/i });在数组元素上使用 Regex
Section titled “在数组元素上使用 Regex”您可以将 regex 应用于数组中的元素。这对于搜索标签非常有用。以下查询查找任何标签以单词 “mongo” 开头的帖子。
// '^' 字符将匹配锚定到字符串的开头db.posts.find({ tags: { $regex: "^mongo", $options: "i" } });Regex 查询的性能和索引
Section titled “Regex 查询的性能和索引”这是在 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)或进行索引优化的前缀搜索时。
- 使用 文本搜索 进行自然语言查询,搜索任意位置的单词或短语,按相关性排序,并利用特定语言的词干提取。它几乎总是搜索人工编写文本的更好选择。