正则表达式(Regular Expression,简称为 Regex 或 RegExp)是一种用于描述模式的表达式。它可以用于在文本中进行搜索、匹配、替换和验证等操作。
正则表达式由字符和特殊字符组成,可以用来定义一种模式,然后用这个模式去匹配文本。以下是一些常见的正则表达式特殊字符和其含义:
字符类:
• [abc]:匹配字符 a、b 或 c。
• [^abc]:匹配除了字符 a、b 和 c 之外的任意字符。
• [a-z]:匹配任意小写字母。
• [A-Z]:匹配任意大写字母。
• [0-9]:匹配任意数字。
元字符:
• .:匹配除换行符以外的任意字符。
• ^:匹配字符串的开头。
• $:匹配字符串的结尾。
• \b:匹配单词的边界。
• \d:匹配任意数字。
• \w:匹配任意字母、数字或下划线。
• \s:匹配任意空白字符。
量词:
• *:匹配前面的字符零次或多次。
• +:匹配前面的字符一次或多次。
• ?:匹配前面的字符零次或一次。
• {n}:匹配前面的字符恰好 n 次。
• {n,}:匹配前面的字符至少 n 次。
• {n,m}:匹配前面的字符至少 n 次,但不超过 m 次。
除了上述特殊字符外,正则表达式还支持一些其他的特性,如分组、捕获和反向引用等。在使用正则表达式时,可以使用各种编程语言或工具提供的正则表达式引擎来进行匹配和处理。
在 MongoDB 中,可以使用正则表达式对文档中的字段进行模式匹配和查询。MongoDB 使用 PCRE(Perl Compatible Regular Expressions)作为其正则表达式引擎。正则表达式不同于全文检索,使用正则表达式不需要做任何配置。
在查询中使用正则表达式时,可以使用 $regex 操作符指定正则表达式模式,并将其作为查询条件的一部分。以下是一个示例:
> db.users.find({ name:{ $regex:/B.+/ } }) { "_id" : ObjectId("6503b13ef470730f2bb4433f"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b141f470730f2bb44fc9"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b142f470730f2bb454f4"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b143f470730f2bb4598e"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb46189"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb461bc"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b145f470730f2bb4672c"), "name" : "Bname", "age" : 100 } ...
在上述示例中,users 是集合的名称,name 是要匹配的字段,pattern 是正则表达式模式。
除了直接使用正则表达式对象,还可以使用字符串形式的正则表达式,并在模式字符串前后加上 /,如 /pattern/。例如:
> db.users.find({ name: /B.+/ }) { "_id" : ObjectId("6503b13ef470730f2bb4433f"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b141f470730f2bb44fc9"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b142f470730f2bb454f4"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b143f470730f2bb4598e"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb46189"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb461bc"), "name" : "Bname", "age" : 100 } ...
ngoDB 还提供了一些选项来控制正则表达式的匹配行为,可以作为第二个参数传递给 $regex 操作符。常用的选项包括:
i:忽略大小写。
m:多行模式,使^和$匹配每一行的开头和结尾。
s:单行模式,使.匹配任意字符,包括换行符。
x:忽略空白字符,可以在模式中使用空格、制表符和换行符,以提高可读性。
以下是一个示例,演示如何使用正则表达式进行模式匹配,并且忽略大小写,例如:
> db.users.find({ name: /b.+/i }) { "_id" : ObjectId("6503b13ef470730f2bb4433f"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b141f470730f2bb44fc9"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b142f470730f2bb454f4"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b143f470730f2bb4598e"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb46189"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb461bc"), "name" : "Bname", "age" : 100 } ...
上述示例将匹配 name 字段以 B 字符开头的所有用户,不区分大小写。
另一种写法,如下:
> db.users.find({ name:{ $regex:"b", $options:"$i" } }) { "_id" : ObjectId("6503b13ef470730f2bb4433f"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b141f470730f2bb44fc9"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b142f470730f2bb454f4"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b143f470730f2bb4598e"), "name" : "Bname", "age" : 100 } { "_id" : ObjectId("6503b144f470730f2bb46189"), "name" : "Bname", "age" : 100 } ...
注意:正则表达式查询可能会对性能产生一定的影响,特别是在大型集合和复杂的正则表达式模式下。因此,在使用正则表达式查询时,需要权衡查询的复杂性和性能需求。
我们还可以在数组字段中使用正则表达式来查找内容。 这在标签的实现上非常有用,如果你需要查找包含以 run 开头的标签数据(ru 或 run 或 runoob), 你可以使用以下代码:
# 准备几条数据 > db.arr.insertOne({ skill:["java","javascript","mongodb","mysql"] }) { "acknowledged" : true, "insertedId" : ObjectId("65040555f470730f2bc38488") } > db.arr.insertOne({ skill:["c#","javascript","redis","mysql"] }) { "acknowledged" : true, "insertedId" : ObjectId("65040563f470730f2bc38489") } > db.arr.insertOne({ skill:["php","javascript","redis","mysql"] }) { "acknowledged" : true, "insertedId" : ObjectId("6504056af470730f2bc3848a") } # 查询 skill 字段中包含 “re” 开头的字符串的文档 > db.arr.find({ skill:/re.+/ }) { "_id" : ObjectId("65040563f470730f2bc38489"), "skill" : [ "c#", "javascript", "redis", "mysql" ] } { "_id" : ObjectId("6504056af470730f2bc3848a"), "skill" : [ "php", "javascript", "redis", "mysql" ] }
如果你的文档中字段设置了索引,那么使用索引相比于正则表达式匹配查找所有的数据查询速度更快。
如果正则表达式是前缀表达式,所有匹配的数据将以指定的前缀字符串为开始。例如:如果正则表达式为 ^tut ,查询语句将查找以 tut 为开头的字符串。
这里面使用正则表达式有两点需要注意:
正则表达式中使用变量。一定要使用 eval 将组合的字符串进行转换,不能直接将字符串拼接后传入给表达式。否则没有报错信息,只是结果为空!实例如下:
var name=eval("/" + 变量值key +"/i");
以下是模糊查询包含 title 关键词, 且不区分大小写:
title:eval("/" + title + "/i") // 等同于 title:{$regex:title,$Option:"$i"}