MongoDB聚合运算符:$regexFind

MongoDB聚合运算符:$regexFind

$regexFind在聚合表达式中提供正则表达式(regex)模式匹配功能。如果找到匹配,则返回包含第一个匹配信息的文档。如果未找到匹配,则返回空值。

在MongoDB 4.2 之前,聚合管道只能在$match阶段使用查询操作符 $regex

语法

{ $regexFind: { input: <expression> , regex: <expression>, options: <expression> } }

$regexFind可以用来比较任何类型的值,针对不同的类型使用特定的BSON比较顺序。

字段说明

  • input:要应用正则表达式模式的字符串。可以是字符串或任何解析为字符串的有效表达式。

  • regex:要应用的正则表达式模式。可以是任何解析为字符串或正则表达式模式/<pattern>/的有效表达式。使用regex /<pattern>/时,还可以指定regex选项 im(但不能指定 sx 选项):

    • "pattern"
    • /<pattern>/
    • /<pattern>/<options>
      或者,也可以使用选项字段指定 regex 选项。要指定 s 或 x 选项,必须使用选项字段。
      不能同时在 regex 和选项字段中指定选项。
  • options:可选字段,以下<options>可与正则表达式一起使用。

    • i:大小写不敏感,可同时匹配大写和小写,可以在选项字段中指定该选项,也可以将其作为 regex 字段的一部分。
    • m:对于包含锚点(即:^ 表示开始,$ 表示结束)的模式,如果字符串有多行值,则匹配每行的开头或结尾。如果不使用该选项,这些锚点将匹配字符串的开头或结尾。如果模式中不包含锚点,或者字符串值中没有换行符(如 \n),则 m 选项不起作用。
    • x:"Extended"功能可忽略模式中的所有空白字符,除非转义或包含在字符类中。此外,它会忽略中间的字符,包括未转义的井号/井号 (#) 字符和下一个新行,以便在复杂的模式中包含注释。这只适用于数据字符;空白字符永远不会出现在模式的特殊字符序列中。x选项不影响VT字符(即代码 11)的处理。
    • 允许点字符(即.)匹配包括换行符在内的所有字符。只能在options字段中指定选项。

返回值

如果运算符没有找到匹配项,则运算符的结果为空。

如果运算符找到了匹配项,运算符的结果就是包含以下内容的文档:

  • 输入中的第一个匹配字符串,
  • 输入中匹配字符串的代码点索引(不是字节索引),以及
  • 与匹配字符串捕获的组相对应的字符串数组。捕获组在正则表达式模式中使用未转义的括号 () 指定。
{ "match" : <string>, "idx" : <num>, "captures" : <array of strings> }

使用

PCRE库

从 6.1 版开始,MongoDB 使用 PCRE2(Perl 兼容正则表达式)库来实现正则表达式模式匹配。

$regexFind和排序规则

$regexFind 忽略为集合、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" }

但是,聚合表达式 $regexFind 忽略排序规则;也就是说,以下正则表达式模式匹配示例区分大小写和变音符号:

db.myColl.aggregate( [ { $addFields: { resultObject: { $regexFind: { input: "$category", regex: /cafe/ }  } } } ] )
db.myColl.aggregate([ { $addFields: { resultObject: { $regexFind: { input: "$category", regex: /cafe/ }  } } } ],{ collation: { locale: "fr", strength: 1 } }           // 在$regexFind中被忽略
)

两个操作都会返回以下内容:

{ "_id" : 1, "category" : "café", "resultObject" : null }
{ "_id" : 2, "category" : "cafe", "resultObject" : { "match" : "cafe", "idx" : 0, "captures" : [ ] } }
{ "_id" : 3, "category" : "cafE", "resultObject" : null }

要执行不区分大小写的正则表达式模式匹配,可改用 i 选项。

捕获输出

如果正则表达式模式包含捕获组并且该模式在输入中找到匹配项,则结果中的捕获数组对应于匹配字符串捕获的组。捕获组在正则表达式模式中使用未转义的括号 () 指定。捕获数组的长度等于模式中捕获组的数量,并且数组的顺序与捕获组出现的顺序匹配。

使用下面的脚本创建contacts集合:

db.contacts.insertMany([{ "_id": 1, "fname": "Carol", "lname": "Smith", "phone": "718-555-0113" },{ "_id": 2, "fname": "Daryl", "lname": "Doe", "phone": "212-555-8832" },{ "_id": 3, "fname": "Polly", "lname": "Andrews", "phone": "208-555-1932" },{ "_id": 4, "fname": "Colleen", "lname": "Duncan", "phone": "775-555-0187" },{ "_id": 5, "fname": "Luna", "lname": "Clarke", "phone": "917-555-4414" }
])

以下管道将正则表达式模式 /(C(ar)*)ol/ 应用于 fname 字段:

db.contacts.aggregate([{$project: {returnObject: {$regexFind: { input: "$fname", regex: /(C(ar)*)ol/ }}}}
])

正则表达式模式找到与 fnameCarolColleen 的匹配项:

{ "_id" : 1, "returnObject" : { "match" : "Carol", "idx" : 0, "captures" : [ "Car", "ar" ] } }
{ "_id" : 2, "returnObject" : null }
{ "_id" : 3, "returnObject" : null }
{ "_id" : 4, "returnObject" : { "match" : "Col", "idx" : 0, "captures" : [ "C", null ] } }
{ "_id" : 5, "returnObject" : null }

该模式包含捕获组 (C(ar)*),其中包含嵌套组 (ar),捕获数组中的元素对应于两个捕获组,如果某个组(例如 Colleen 和组 (ar))未捕获匹配的文档,则 $regexFind 会用空占位符替换该组。

如前面的示例所示,捕获数组包含每个捕获组的一个元素(对于非捕获使用 null)。下面的示例通过将捕获组的逻辑或应用到电话字段来搜索具有纽约市区号的电话号码。每组代表纽约市的一个区号:

db.contacts.aggregate([{$project: {nycContacts: {$regexFind: { input: "$phone", regex: /^(718).*|^(212).*|^(917).*/ }}}}
])

对于与正则表达式模式匹配的文档,捕获数组包含匹配的捕获组,并将任何非捕获组替换为 null

{ "_id" : 1, "nycContacts" : { "match" : "718-555-0113", "idx" : 0, "captures" : [ "718", null, null ] } }
{ "_id" : 2, "nycContacts" : { "match" : "212-555-8832", "idx" : 0, "captures" : [ null, "212", null ] } }
{ "_id" : 3, "nycContacts" : null }
{ "_id" : 4, "nycContacts" : null }
{ "_id" : 5, "nycContacts" : { "match" : "917-555-4414", "idx" : 0, "captures" : [ null, null, "917" ] } }

举例

$regexFind及其选项

使用脚本创建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" }
])

默认情况下,$regexFind 执行区分大小写的匹配。例如,以下聚合对描述字段执行区分大小写的 $regexFind。正则表达式模式 /line/ 未指定任何分组:

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex: /line/ } } } }
])

操作返回下面的结果:

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : null }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : { "match" : "line", "idx" : 6, "captures" : [ ] } }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : { "match" : "line", "idx" : 23, "captures" : [ ] } }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : { "match" : "line", "idx" : 9, "captures" : [ ] } }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : null }
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : null }

以下正则表达式模式 /lin(e|k)/ 指定模式中的分组 (e|k)

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex: /lin(e|k)/ } } } }
])

操作返回下面的结果:

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : null }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : { "match" : "line", "idx" : 6, "captures" : [ "e" ] } }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : { "match" : "line", "idx" : 23, "captures" : [ "e" ] } }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : { "match" : "line", "idx" : 9, "captures" : [ "e" ] } }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : { "match" : "link", "idx" : 9, "captures" : [ "k" ] } }
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : null }

在返回选项中,idx 字段是代码点索引,而不是字节索引。可以使用正则表达式模式 /tier/

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex: /tier/ } } } }
])

该操作返回以下内容,其中只有最后一条记录与模式匹配,并且返回的 idx2(如果使用字节索引则为 3

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : null }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : null }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : null }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : null }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : null }
{ "_id" : 6, "description" : "métier work vocation","returnObject" : { "match" : "tier", "idx" : 2, "captures" : [ ] } }

**注意:**不能在 regex 和选项字段中同时指定选项。

i 选项

要执行不区分大小写的模式匹配,要将i选项包含在正则表达式字段或选项字段中:

//将 i 指定为正则表达式字段的一部分
{ $regexFind: { input: "$description", regex: /line/i } }
//在选项字段中指定 i
{ $regexFind: { input: "$description", regex: /line/, options: "i" } }
{ $regexFind: { input: "$description", regex: "line", options: "i" } }

例如,以下聚合对描述字段执行不区分大小写的 $regexFind。正则表达式模式 /line/ 不指定任何分组:

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex: /line/i } } } }
])

操作返回下面的结果:

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : { "match" : "LINE", "idx" : 7, "captures" : [ ] } }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : { "match" : "line", "idx" : 6, "captures" : [ ] } }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : { "match" : "line", "idx" : 23, "captures" : [ ] } }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : { "match" : "line", "idx" : 9, "captures" : [ ] } }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : null }
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : null }
m 选项

要匹配多行字符串的每一行的指定锚点(例如 ^$),请将 m 选项包含在正则表达式字段或选项字段中:

// 将 m 指定为正则表达式字段的一部分
{ $regexFind: { input: "$description", regex: /line/m } }
// 在选项字段中指定 m
{ $regexFind: { input: "$description", regex: /line/, options: "m" } }
{ $regexFind: { input: "$description", regex: "line", options: "m" } }

以下示例同时包含 im 选项,用于匹配以字母 sS` 开头的多行字符串的行:

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex: /^s/im } } } }
])

操作返回下面的结果:

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : { "match" : "S", "idx" : 0, "captures" : [ ] } }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : { "match" : "s", "idx" : 12, "captures" : [ ] } }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : null }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : null }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : null }
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : null }
x 选项

要忽略模式中所有未转义的空白字符和注释(由未转义的哈希 # 字符和下一个换行符表示),需在选项字段中包含 s 选项:

// 在选项字段中指定 x
{ $regexFind: { input: "$description", regex: /line/, options: "x" } }
{ $regexFind: { input: "$description", regex: "line", options: "x" } }

以下示例包含用于跳过未转义空格和注释的 x 选项:

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex: /lin(e|k) # matches line or link/, options:"x" } } } }
])

操作返回下面的结果:

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : null }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : { "match" : "line", "idx" : 6, "captures" : [ "e" ] } }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : { "match" : "line", "idx" : 23, "captures" : [ "e" ] } }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : { "match" : "line", "idx" : 9, "captures" : [ "e" ] } }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : { "match" : "link", "idx" : 9, "captures" : [ "k" ] } }
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : null }
s 选项

要允许模式中的点字符(即 .)匹配包括换行符在内的所有字符,需在选项字段中包含 s 选项:

// 在选项字段中指定 s
{ $regexFind: { input: "$description", regex: /m.*line/, options: "s" } }
{ $regexFind: { input: "$description", regex: "m.*line", options: "s" } }

以下示例包含 s 选项以允许点字符(即 .)匹配包括换行符在内的所有字符,以及 i 选项以执行不区分大小写的匹配:

db.products.aggregate([{ $addFields: { returnObject: { $regexFind: { input: "$description", regex:/m.*line/, options: "si"  } } } }
])

操作返回下面的结果:

{ "_id" : 1, "description" : "Single LINE description.", "returnObject" : null }
{ "_id" : 2, "description" : "First lines\nsecond line", "returnObject" : null }
{ "_id" : 3, "description" : "Many spaces before     line", "returnObject" : { "match" : "Many spaces before     line", "idx" : 0, "captures" : [ ] } }
{ "_id" : 4, "description" : "Multiple\nline descriptions", "returnObject" : { "match" : "Multiple\nline", "idx" : 0, "captures" : [ ] } }
{ "_id" : 5, "description" : "anchors, links and hyperlinks", "returnObject" : null }
{ "_id" : 6, "description" : "métier work vocation", "returnObject" : null }

使用 $regexFind 从字符串中解析电子邮件

使用下面的脚本创建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" }
])

以下聚合使用$regexFind从评论字段中提取电子邮件(不区分大小写):

db.feedback.aggregate( [{ $addFields: {"email": { $regexFind: { input: "$comment", regex: /[a-z0-9_.+-]+@[a-z0-9_.+-]+\.[a-z0-9_.+-]+/i } }} },{ $set: { email: "$email.match"} }
] )
阶段1

该阶段使用 $addFields 向文档添加新的字段电子邮件。新字段包含对评论字段执行 $regexFind 的结果:

{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "email" : { "match" : "aunt.arc.tica@example.com", "idx" : 38, "captures" : [ ] } }
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "email" : null }
{ "_id" : 3, "comment" : "I can't find how to convert a date to string. cam@mongodb.com", "email" : { "match" : "cam@mongodb.com", "idx" : 46, "captures" : [ ] } }
{ "_id" : 4, "comment" : "It's just me. I'm testing.  fred@MongoDB.com", "email" : { "match" : "fred@MongoDB.com", "idx" : 28, "captures" : [ ] } }
阶段2

该阶段使用 $addFields 向文档添加新的字段电子邮件。新字段包含对评论字段执行 $regexFind 的结果:

{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "email" : { "match" : "aunt.arc.tica@example.com", "idx" : 38, "captures" : [ ] } }
{ "_id" : 2, "comment" : "I wanted to concatenate a string", "email" : null }
{ "_id" : 3, "comment" : "I can't find how to convert a date to string. cam@mongodb.com", "email" : { "match" : "cam@mongodb.com", "idx" : 46, "captures" : [ ] } }
{ "_id" : 4, "comment" : "It's just me. I'm testing.  fred@MongoDB.com", "email" : { "match" : "fred@MongoDB.com", "idx" : 28, "captures" : [ ] } }
阶段3

该阶段使用 $set 将电子邮件重置为当前的"$email.match"值。如果 email 的当前值为 null,则 email 的新值将设置为 null

{ "_id" : 1, "comment" : "Hi, I'm just reading about MongoDB -- aunt.arc.tica@example.com", "email" : "aunt.arc.tica@example.com" }
{ "_id" : 2, "comment" : "I wanted to concatenate a string" }
{ "_id" : 3, "comment" : "I can't find how to convert a date to string. cam@mongodb.com", "email" : "cam@mongodb.com" }
{ "_id" : 4, "comment" : "It's just me. I'm testing.  fred@MongoDB.com", "email" : "fred@MongoDB.com" }

将 $regexFind 应用于数组的字符串元素

使用下面的脚本创建contacts集合:

db.contacts.insertMany([{ "_id" : 1, name: "Aunt Arc Tikka", details: [ "+672-19-9999", "aunt.arc.tica@example.com" ] },{ "_id" : 2, name: "Belle Gium",  details: [ "+32-2-111-11-11", "belle.gium@example.com" ] },{ "_id" : 3, name: "Cam Bo Dia",  details: [ "+855-012-000-0000", "cam.bo.dia@example.com" ] },{ "_id" : 4, name: "Fred", details: [ "+1-111-222-3333" ] }
])

以下聚合使用 $regexFind 将详细信息数组转换为包含电子邮件和电话字段的嵌入文档:

db.contacts.aggregate( [{ $unwind: "$details" },{ $addFields: {"regexemail": { $regexFind: { input: "$details", regex: /^[a-z0-9_.+-]+@[a-z0-9_.+-]+\.[a-z0-9_.+-]+$/, options: "i" } },"regexphone": { $regexFind: { input: "$details", regex: /^[+]{0,1}[0-9]*\-?[0-9_\-]+$/ } }} },{ $project: { _id: 1, name: 1, details: { email: "$regexemail.match", phone: "$regexphone.match" } } },{ $group: { _id: "$_id", name: { $first: "$name" }, details: { $mergeObjects: "$details"} } },{ $sort: { _id: 1 } }
])
阶段1

阶段 $unwinds 将数组展开到单独的文档中:

{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : "+672-19-9999" }
{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : "aunt.arc.tica@example.com" }
{ "_id" : 2, "name" : "Belle Gium", "details" : "+32-2-111-11-11" }
{ "_id" : 2, "name" : "Belle Gium", "details" : "belle.gium@example.com" }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : "+855-012-000-0000" }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : "cam.bo.dia@example.com" }
{ "_id" : 4, "name" : "Fred", "details" : "+1-111-222-3333" }
阶段2

该阶段使用 $addFields 将新字段添加到包含电话号码和电子邮件的 $regexFind 结果的文档中:

{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : "+672-19-9999", "regexemail" : null, "regexphone" : { "match" : "+672-19-9999", "idx" : 0, "captures" : [ ] } }
{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : "aunt.arc.tica@example.com", "regexemail" : { "match" : "aunt.arc.tica@example.com", "idx" : 0, "captures" : [ ] }, "regexphone" : null }
{ "_id" : 2, "name" : "Belle Gium", "details" : "+32-2-111-11-11", "regexemail" : null, "regexphone" : { "match" : "+32-2-111-11-11", "idx" : 0, "captures" : [ ] } }
{ "_id" : 2, "name" : "Belle Gium", "details" : "belle.gium@example.com", "regexemail" : { "match" : "belle.gium@example.com", "idx" : 0, "captures" : [ ] }, "regexphone" : null }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : "+855-012-000-0000", "regexemail" : null, "regexphone" : { "match" : "+855-012-000-0000", "idx" : 0, "captures" : [ ] } }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : "cam.bo.dia@example.com", "regexemail" : { "match" : "cam.bo.dia@example.com", "idx" : 0, "captures" : [ ] }, "regexphone" : null }
{ "_id" : 4, "name" : "Fred", "details" : "+1-111-222-3333", "regexemail" : null, "regexphone" : { "match" : "+1-111-222-3333", "idx" : 0, "captures" : [ ] } }
阶段3

该阶段使用$project输出带有_id字段、name字段和details字段的文档。详细信息字段设置为包含电子邮件和电话字段的文档,其值分别由 regexemailregexphone 字段:

{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : { "phone" : "+672-19-9999" } }
{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : { "email" : "aunt.arc.tica@example.com" } }
{ "_id" : 2, "name" : "Belle Gium", "details" : { "phone" : "+32-2-111-11-11" } }
{ "_id" : 2, "name" : "Belle Gium", "details" : { "email" : "belle.gium@example.com" } }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : { "phone" : "+855-012-000-0000" } }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : { "email" : "cam.bo.dia@example.com" } }
{ "_id" : 4, "name" : "Fred", "details" : { "phone" : "+1-111-222-3333" } }
阶段4

该阶段使用 $group 根据输入文档的 _id 值对输入文档进行分组。该阶段使用 $mergeObjects 表达式来合并详细信息文档:

{ "_id" : 3, "name" : "Cam Bo Dia", "details" : { "phone" : "+855-012-000-0000", "email" : "cam.bo.dia@example.com" } }
{ "_id" : 4, "name" : "Fred", "details" : { "phone" : "+1-111-222-3333" } }
{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : { "phone" : "+672-19-9999", "email" : "aunt.arc.tica@example.com" } }
{ "_id" : 2, "name" : "Belle Gium", "details" : { "phone" : "+32-2-111-11-11", "email" : "belle.gium@example.com" } }
阶段5

该阶段使用 $sort_id 字段对文档进行排序:

{ "_id" : 1, "name" : "Aunt Arc Tikka", "details" : { "phone" : "+672-19-9999", "email" : "aunt.arc.tica@example.com" } }
{ "_id" : 2, "name" : "Belle Gium", "details" : { "phone" : "+32-2-111-11-11", "email" : "belle.gium@example.com" } }
{ "_id" : 3, "name" : "Cam Bo Dia", "details" : { "phone" : "+855-012-000-0000", "email" : "cam.bo.dia@example.com" } }
{ "_id" : 4, "name" : "Fred", "details" : { "phone" : "+1-111-222-3333" } }

使用捕获的分组来解析用户名

使用下面的脚本创建employees集合:

db.employees.insertMany([{ "_id" : 1, name: "Aunt Arc Tikka", "email" : "aunt.tica@example.com" },{ "_id" : 2, name: "Belle Gium", "email" : "belle.gium@example.com" },{ "_id" : 3, name: "Cam Bo Dia", "email" : "cam.dia@example.com" },{ "_id" : 4, name: "Fred"  }
])

员工电子邮件的格式为 <firstname>.<lastname>@example.com,使用 $regexFind 结果中返回的捕获字段,可以解析出员工的用户名:

db.employees.aggregate( [{ $addFields: {"username": { $regexFind: { input: "$email", regex: /^([a-z0-9_.+-]+)@[a-z0-9_.+-]+\.[a-z0-9_.+-]+$/, options: "i" } },} },{ $set: { username: { $arrayElemAt:  [ "$username.captures", 0 ] } } }
] )
阶段1

该阶段使用 $addFields 将新字段username添加到文档中,新字段包含对email字段执行 $regexFind 的结果:

{ "_id" : 1, "name" : "Aunt Arc Tikka", "email" : "aunt.tica@example.com", "username" : { "match" : "aunt.tica@example.com", "idx" : 0, "captures" : [ "aunt.tica" ] } }
{ "_id" : 2, "name" : "Belle Gium", "email" : "belle.gium@example.com", "username" : { "match" : "belle.gium@example.com", "idx" : 0, "captures" : [ "belle.gium" ] } }
{ "_id" : 3, "name" : "Cam Bo Dia", "email" : "cam.dia@example.com", "username" : { "match" : "cam.dia@example.com", "idx" : 0, "captures" : [ "cam.dia" ] } }
{ "_id" : 4, "name" : "Fred", "username" : null }
阶段2

该阶段使用 $setusername重置为"$username.captures"数组的第零个元素。如果 username 的当前值为 null,则将 username 的新值设置为 null

{ "_id" : 1, "name" : "Aunt Arc Tikka", "email" : "aunt.tica@example.com", "username" : "aunt.tica" }
{ "_id" : 2, "name" : "Belle Gium", "email" : "belle.gium@example.com", "username" : "belle.gium" }
{ "_id" : 3, "name" : "Cam Bo Dia", "email" : "cam.dia@example.com", "username" : "cam.dia" }
{ "_id" : 4, "name" : "Fred", "username" : null }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python中CSRF攻击是什么

CSRF&#xff08;跨站请求伪造&#xff0c;Cross-Site Request Forgery&#xff09;攻击是一种网络攻击方法&#xff0c;它迫使终端用户在当前已认证的Web应用中执行非授权的命令。攻击者利用用户的信任&#xff0c;诱导或通过其他方式使用户的浏览器产生对受信任站点的恶意请求…

【Python】如何在Ubuntu上设置Python脚本开机自启

你不知道我为什么狠下心 盘旋在你看不见的高空里 多的是 你不知道的事 蝴蝶眨几次眼睛 才学会飞行 夜空洒满了星星 但几颗会落地 我飞行 但你坠落之际 很靠近 还听见呼吸 对不起 我却没捉紧你 &#x1f3b5; 王力宏《你不知道的事》 前置要求 确保你的Ub…

和鲸科技将参与第五届空间数据智能学术会议并于应急减灾与可持续发展专题论坛做报告分享

ACM SIGSPATIAL中国分会致力于推动空间数据的研究范式及空间智能理论与技术在时空大数据、智慧城市、交通科学、社会治理等领域的创新与应用。ACM SIGSPATIAL中国分会创办了空间数据智能学术会议&#xff08;SpatialDI&#xff09;&#xff0c;分会将于2024年4月25日-27日在南京…

javaWeb项目-快捷酒店管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Spring Boot框架 …

PSCAD|应用于输电线路故障测距的行波波速仿真分析

1 主要内容 该程序参考文献《应用于输电线路故障测距的行波波速仿真分析》&#xff0c;利用线路内部故障产生的初始行波浪涌达线路两端测量点的绝对时间之差值计算故障点到两端测量点之间的距离&#xff0c;并利用小波变换得到初始行波波头准确到达时刻&#xff0c;从而精准定…

富文本在线编辑器 - tinymce

tinymce 项目是一个比较好的富文本编辑器. 这里有个小demo, 下载下来尝试一下, 需要配置个本地服务器才能够访问, 我这里使用的nginx, 下面是我的整个操作过程: git clone gitgitee.com:chick1993/layui-tinymce.git cd layui-tinymcewget http://nginx.org/download/nginx-1.…

JavaEE:JVM

基本介绍 JVM&#xff1a;Java虚拟机&#xff0c;用于解释执行Java字节码 jdk&#xff1a;Java开发工具包 jre&#xff1a;Java运行时环境 C语言将写入的程序直接编译成二进制的机器语言&#xff0c;而java不想重新编译&#xff0c;希望能直接执行。Java先通过javac把.java…

RK3568 学习笔记 : 更改 u-boot spl 中的 emmc 的启动次序

环境 开发板&#xff1a; 【正点原子】 的 RK3568 开发板 ATK-DLRK3568 u-boot 版本&#xff1a;来自 【正点原子】 的 RK3568 开发板 Linux SDK&#xff0c;单独复制出来一份&#xff0c;手动编译 编译环境&#xff1a;VMware 虚拟机 ubuntu 20.04 问题描述 RK3568 默认 …

浅谈线程的生命周期

Java线程的生命周期是一个从创建到终止的过程&#xff0c;经历了多种状态的转变。在Java中&#xff0c;线程的生命周期可以划分为以下几个主要状态&#xff1a; 新建&#xff08;New&#xff09;&#xff1a; 当使用 new Thread() 创建一个新的线程对象但尚未调用 start() 方法…

CSS基础之伪元素选择器(如果想知道CSS的伪元素选择器知识点,那么只看这一篇就足够了!)

前言&#xff1a;我们已经知道了在CSS中&#xff0c;选择器有基本选择器、复合选择器、伪类选择器、那么选择器学习完了吗&#xff1f;显然是没有的&#xff0c;这篇文章讲解最后一种选择器——伪元素选择器。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我…

【linux】mobaterm如何kill pycharm进程

【linux】mobaterm如何kill pycharm进程 【先赞后看养成习惯】求点赞关注收藏&#x1f600; 使用云服务器时&#xff0c;pycharm在打开状态下&#xff0c;不小心关了mobaxterm&#xff0c;然后再输入pycharm.sh就会打不开pycharm&#xff0c;显示已经打开报错&#xff1a;Com…

软考131-上午题-【软件工程】-软件可靠性、可用性、可维护性

可靠性、可用性和可维护性是软件的质量属性&#xff0c;软件工程中&#xff0c;用 0-1 之间的数来度量。 0.66 66% 1、 可靠性 可靠性是指一个系统对于给定的时间间隔内、在给定条件下无失效运作的概率。 可以用 MTTF/ (1MTTF) 来度量&#xff0c;其中 MTTF 为平均无故障时间…

Java单源最短路径知识点(含面试大厂题和源码)

单源最短路径问题是指在加权图中&#xff0c;找到从单个源点到其他所有点的最短路径的问题。这是图论和网络优化中的一个经典问题&#xff0c;具有广泛的应用&#xff0c;如网络路由、交通规划、社交网络分析等。解决单源最短路径问题的算法有很多&#xff0c;其中最著名的包括…

PHP一句话木马

一句话木马 PHP 的一句话木马是一种用于 Web 应用程序漏洞利用的代码片段。它通常是一小段 PHP 代码&#xff0c;能够在目标服务器上执行任意命令。一句话木马的工作原理是利用 Web 应用程序中的安全漏洞&#xff0c;将恶意代码注入到服务器端的 PHP 脚本中。一旦执行&#xf…

Java 分页查询

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Docker Container (容器) 常见命令

Docker 容器的生命周期 什么是容器&#xff1f; 通俗地讲&#xff0c;容器是镜像的运行实体。镜像是静态的只读文件&#xff0c;而容器带有运行时需要的可写文件层&#xff0c;并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容 器有初建、运行、停止、暂停和删除…

OpenXR API概览与核心组件解析

在虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;领域&#xff0c;OpenXR API提供了一个重要的开放标准&#xff0c;使得开发者能够跨多种硬件和软件平台创建兼容的应用。本文将详细解释OpenXR中的核心组件和数据结构&#xff0c;并探讨它们如何共同…

智能商品计划系统如何提升鞋服零售品牌的竞争力

国内鞋服零售企业经过多年的发展&#xff0c;已经形成了众多知名品牌&#xff0c;然而近年来一些企业频频受到库存问题的困扰&#xff0c;这一问题不仅影响了品牌商自身&#xff0c;也给长期合作的经销商带来了困扰。订货会制度在初期曾经有效地解决了盲目生产的问题&#xff0…

蓝桥杯刷题-计算系数

本文自用&#xff0c;用作记录。 211. 计算系数 - AcWing题库 #include <bits/stdc.h>using namespace std;int a, b, k ,n ,m; const int mod 10007; int qmi(int a, int k) {a % mod;int res 1;while (k){if (k & 1) res res * a % mod;a a * a % mod;k >…

机器学习方法在测井解释上的应用-以岩性分类为例

机器学习在测井解释上的应用越来越广泛&#xff0c;主要用于提高油气勘探和开发的效率和精度。通过使用机器学习算法&#xff0c;可以从测井数据中自动识别地质特征&#xff0c;预测岩石物理性质&#xff0c;以及优化油气储层的评估和管理。 以下是机器学习在测井解释中的一些…