MongoDB聚合运算符:$regexMatch
$regexMatch
执行正则表达式 (regex) 模式匹配并返回:
- 如果存在匹配项返回true
- 如果不存在匹配项返回false
在MongoDB 4.2 之前,聚合管道只能在$match
阶段使用查询操作符 $regex
。
语法
{ $regexMatch: { input: <expression> , regex: <expression>, options: <expression> } }
$regexMatch
可以用来比较任何类型的值,针对不同的类型使用特定的BSON比较顺序。
字段说明
-
input
:要应用正则表达式模式的字符串。可以是字符串或任何解析为字符串的有效表达式。 -
regex
:要应用的正则表达式模式。可以是任何解析为字符串或正则表达式模式/<pattern>/
的有效表达式。使用regex/<pattern>/
时,还可以指定regex选项i
和m
(但不能指定s
或x
选项):"pattern"
/<pattern>/
/<pattern>/<options>
或者,也可以使用选项字段指定regex
选项。要指定s
或x
选项,必须使用选项字段。
不能同时在regex
和optioins
字段中指定选项。
-
options
:可选字段,以下<options>
可与正则表达式一起使用。i
:大小写不敏感,可同时匹配大写和小写,可以在选项字段中指定该选项,也可以将其作为 regex 字段的一部分。m
:对于包含锚点(即:^
表示开始,$
表示结束)的模式,如果字符串有多行值,则匹配每行的开头或结尾。如果不使用该选项,这些锚点将匹配字符串的开头或结尾。如果模式中不包含锚点,或者字符串值中没有换行符(如\n
),则m
选项不起作用。x
:"Extended"功能可忽略模式中的所有空白字符,除非转义或包含在字符类中。此外,它会忽略中间的字符,包括未转义的井号/井号 (#
) 字符和下一个新行,以便在复杂的模式中包含注释。这只适用于数据字符;空白字符永远不会出现在模式的特殊字符序列中。x
选项不影响VT字符(即代码11
)的处理。- 允许点字符(即
.
)匹配包括换行符在内的所有字符。只能在options
字段中指定选项。
返回值
该运算符返回一个布尔值:
- 如果存在匹配项返回true
- 如果不存在匹配项返回false
[ { "match" : <string>, "idx" : <num>, "captures" : <array of strings> }, ... ]
使用
PCRE库
从 6.1 版开始,MongoDB 使用 PCRE2(Perl 兼容正则表达式)库来实现正则表达式模式匹配。
$regexMatch和排序规则
$regexMatch
忽略为集合、db.collection.aggregate()和索引(如果使用)指定的排序规则。
例如,创建一个排序规则强度为 1
的示例集合(即仅比较基本字符并忽略其他差异,例如大小写和变音符号):
db.createCollection( "myColl", { collation: { locale: "fr", strength: 1 } } )
插入以下文档:
db.myColl.insertMany([
{ _id: 1, category: "café" },
{ _id: 2, category: "cafe" },
{ _id: 3, category: "cafE" }
])
使用集合的排序规则,以下操作执行不区分大小写和不区分变音符号的匹配:
db.myColl.aggregate( [ { $match: { category: "cafe" } } ] )
该操作返回以下 3 个文档:
{ "_id" : 1, "category" : "café" }
{ "_id" : 2, "category" : "cafe" }
{ "_id" : 3, "category" : "cafE" }
但是,聚合表达式 $regexMatch
忽略排序规则;也就是说,以下正则表达式模式匹配示例区分大小写和变音符号:
db.myColl.aggregate( [ { $addFields: { results: { $regexMatch: { input: "$category", regex: /cafe/ } } } } ] )
db.myColl.aggregate(
[ { $addFields: { results: { $regexMatch: { input: "$category", regex: /cafe/ } } } } ],
{ collation: { locale: "fr", strength: 1 } } // 在$regexMatch中被忽略
)
两个操作都会返回以下内容:
{ "_id" : 1, "category" : "café", "results" : false }
{ "_id" : 2, "category" : "cafe", "results" : true }
{ "_id" : 3, "category" : "cafE", "results" : false }
要执行不区分大小写的正则表达式模式匹配,可改用 i
选项。
举例
$regexMatch及其选项
使用脚本创建products
集合:
db.products.insertMany([
{ _id: 1, description: "Single LINE description." },
{ _id: 2, description: "First lines\nsecond line" },
{ _id: 3, description: "Many spaces before line" },
{ _id: 4, description: "Multiple\nline descriptions" },
{ _id: 5, description: "anchors, links and hyperlinks" },
{ _id: 6, description: "métier work vocation" }
])
默认情况下,$regexMatch
执行区分大小写的匹配。例如,以下聚合对描述字段执行区分大小写的 $regexMatch
。正则表达式模式 /line/
未指定任何分组:
db.products.aggregate([
{ $addFields: { returnObject: { $regexMatch: { input: "$description", regex: /line/ } } } }
])
操作返回下面的结果:
{ "_id" : 1, "description" : "Single LINE description.", "result" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before line", "result" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : false }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }
以下正则表达式模式 /lin(e|k)/
指定模式中的分组 (e|k)
:
db.products.aggregate([
{ $addFields: { result: { $regexMatch: { input: "$description", regex: /lin(e|k)/ } } } }
])
操作返回下面的结果:
{ "_id" : 1, "description" : "Single LINE description.", "result" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before line", "result" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : true }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }
**注意:**不能在 regex 和选项字段中同时指定选项。
i 选项
要执行不区分大小写的模式匹配,要将i
选项包含在正则表达式字段或选项字段中:
//将 i 指定为正则表达式字段的一部分
{ $regexMatch: { input: "$description", regex: /line/i } }
//在选项字段中指定 i
{ $regexMatch: { input: "$description", regex: /line/, options: "i" } }
{ $regexMatch: { input: "$description", regex: "line", options: "i" } }
例如,以下聚合对描述字段执行不区分大小写的 $regexMatch
。正则表达式模式 /line/
不指定任何分组:
db.products.aggregate([
{ $addFields: { result: { $regexMatch: { input: "$description", regex: /line/i } } } }
])
操作返回下面的结果:
{ "_id" : 1, "description" : "Single LINE description.", "result" : true }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before line", "result" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : false }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }
m 选项
要匹配多行字符串的每一行的指定锚点(例如 ^
、$
),请将 m
选项包含在正则表达式字段或选项字段中:
// 将 m 指定为正则表达式字段的一部分
{ $regexMatch: { input: "$description", regex: /line/m } }
// 在选项字段中指定 m
{ $regexMatch: { input: "$description", regex: /line/, options: "m" } }
{ $regexMatch: { input: "$description", regex: "line", options: "m" } }
以下示例同时包含 i
和 m
选项,用于匹配以字母 s或
S` 开头的多行字符串的行:
db.products.aggregate([
{ $addFields: { result: { $regexMatch: { input: "$description", regex: /^s/im } } } }
])
操作返回下面的结果:
{ "_id" : 1, "description" : "Single LINE description.", "result" : true }
{ "_id" : 2, "description" : "First lines\nsecond line", "result" : true }
{ "_id" : 3, "description" : "Many spaces before line", "result" : false }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "result" : false }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "result" : false }
{ "_id" : 6, "description" : "métier work vocation", "result" : false }
x 选项
要忽略模式中所有未转义的空白字符和注释(由未转义的哈希 #
字符和下一个换行符表示),需在选项字段中包含 s
选项:
// 在选项字段中指定 x
{ $regexMatch: { input: "$description", regex: /line/, options: "x" } }
{ $regexMatch: { input: "$description", regex: "line", options: "x" } }
以下示例包含用于跳过未转义空格和注释的 x
选项:
db.products.aggregate([
{ $addFields: { returns: { $regexMatch: { input: "$description", regex: /lin(e|k) # matches line or link/, options:"x" } } } }
])
操作返回下面的结果:
{ "_id" : 1, "description" : "Single LINE description.", "returns" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "returns" : true }
{ "_id" : 3, "description" : "Many spaces before line", "returns" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returns" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returns" : true }
{ "_id" : 6, "description" : "métier work vocation", "returns" : false }
s 选项
要允许模式中的点字符(即 .
)匹配包括换行符在内的所有字符,需在选项字段中包含 s
选项:
// 在选项字段中指定 s
{ $regexMatch: { input: "$description", regex: /m.*line/, options: "s" } }
{ $regexMatch: { input: "$description", regex: "m.*line", options: "s" } }
以下示例包含 s
选项以允许点字符(即 .
)匹配包括换行符在内的所有字符,以及 i
选项以执行不区分大小写的匹配:
db.products.aggregate([
{ $addFields: { returnObject: { $regexMatch: { input: "$description", regex:/m.*line/, options: "si" } } } }
])
操作返回下面的结果:
{ "_id" : 1, "description" : "Single LINE description.", "returns" : false }
{ "_id" : 2, "description" : "First lines\nsecond line", "returns" : false }
{ "_id" : 3, "description" : "Many spaces before line", "returns" : true }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returns" : true }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returns" : false }
{ "_id" : 6, "description" : "métier work vocation", "returns" : false }
使用 $regexMatch 检查电子邮件地址
使用下面的脚本创建feedback
集合:
db.feedback.insertMany([
{ "_id" : 1, comment: "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com" },
{ "_id" : 2, comment: "I wanted to concatenate a string" },
{ "_id" : 3, comment: "How do I convert a date to string? cam@mongodb.com" },
{ "_id" : 4, comment: "It's just me. I'm testing. fred@MongoDB.com" }
])
以下聚合使用 $regexMatch
检查comment
字段是否包含带有 @mongodb.com
的电子邮件地址,并将反馈分类为Employee
或External
:
db.feedback.aggregate( [
{ $addFields: {
"category": { $cond: { if: { $regexMatch: { input: "$comment", regex: /[a-z0-9_.+-]+@mongodb.com/i } },
then: "Employee",
else: "External" } }
} },
操作返回下面的结果:
{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "category" : "External" }
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "category" : "External" }
{ "_id" : 3, "comment" : "How do I convert a date to string? Contact me at either cam@mongodb.com or c.dia@mongodb.com", "category" : "Employee" }
{ "_id" : 4, "comment" : "It's just me. I'm testing. fred@MongoDB.com", "category" : "Employee" }