$replaceOne (聚合查询)
定义
$replaceOne
将输入字符串中搜索字符串的第一个实例替换为替换字符串。
如果没有找到任何实例,
$replaceOne
等于输入字符串。$replaceOne
同时区分大小写和变音符号,并且忽略集合上存在的任何排序。
语法
$replaceOne
操作符有以下操作符表达式语法:
{ $replaceOne: { input: <expression>, find: <expression>, replacement: <expression> } }
操作字段
行为
如果在 input 中未找到 find 的任何实例,则 $replaceOne
的评估结果为输入字符串。
必须评估 input、find 和 replacement 表达式,以字符串或 null
的形式,否则 $replaceOne
将因错误而失败。
$replaceOne
和空值
如果 input 或 find 指向一个缺失的字段,它们将返回 null
。
如果 任何一个 input、find 或 replacement 评估为 null
,整个 $replaceOne
表达式评估为 null
示例 | 结果 |
---|---|
{ $replaceOne: { input: null, find: "abc", replacement: "ABC" } } | null |
{ $replaceOne: { input: "abc", find: null, replacement: "ABC" } } | null |
{ $replaceOne: { input: "abc", find: "abc", replacement: null } } | null |
$replaceOne
和排序规则
对于所有 $replaceOne
表达式,字符串匹配总是区分大小写和变音符号。当使用 $replaceOne
进行字符串比较时,忽略配置的任何 排序规则。
例如,创建一个具有排序规则强度 1
的示例集合
db.createCollection( "myColl", { collation: { locale: "fr", strength: 1 } } )
排序规则强度 1
只比较基本字符,并忽略其他差异,例如大小写和变音符号。
接下来,插入三个示例文档
db.myColl.insertMany([ { _id: 1, name: "cafe" }, { _id: 2, name: "Cafe" }, { _id: 3, name: "café" } ])
以下 $replaceOne
操作尝试在 name
字段中查找并替换 "Cafe" 的第一个实例
db.myColl.aggregate([ { $addFields: { resultObject: { $replaceOne: { input: "$name", find: "Cafe", replacement: "CAFE" } } } } ])
因为 $replaceOne
忽略了此集合配置的排序规则,所以该操作仅匹配文档 2
中的 "Cafe" 实例
{ "_id" : 1, "name" : "cafe", "resultObject" : "cafe" } { "_id" : 2, "name" : "Cafe", "resultObject" : "CAFE" } { "_id" : 3, "name" : "café", "resultObject" : "café" }
尊重排序规则的运算符,如 $match
,由于此集合的排序规则强度为 1
,因此在执行针对 "Cafe" 的字符串比较时将匹配所有三个文档。
$replaceOne
和 Unicode 正规化
$replaceOne
聚合表达式不执行任何 Unicode 正规化。这意味着所有 $replaceOne
表达式的字符串匹配都将考虑在 Unicode 中表示字符时使用的代码点数,以尝试匹配。
例如,字符 é
可以使用一个或两个代码点在 Unicode 中表示
Unicode | 显示为 | 代码点 |
---|---|---|
\xe9 | é | 1 ( \xe9 ) |
e\u0301 | é | 2 ( e + \u0301 ) |
使用带有 $replaceOne
的 find 字符串,其中字符 é
在 Unicode 中用一个代码点表示,将不会匹配任何使用两个代码点在 input 字符串中表示的 é
实例。
以下表格显示了当将 "café" 与 input 字符串进行比较时,是否发生匹配,其中 é
用一个或两个代码点表示。此示例中的 find 字符串使用一个代码点表示 é
字符
示例 | 匹配 |
---|---|
{ $replaceOne: { input: "caf\xe9", find: "café", replacement: "CAFE" } } | yes |
{ $replaceOne: { input: "cafe\u0301", find: "café", replacement: "CAFE" } } | no |
因为 $replaceOne
不执行任何 Unicode 规范化,只有第一次字符串比较匹配,其中 find 和 input 字符串都使用一个码点来表示 é
。
示例
创建一个具有以下文档的 inventory
集合
db.inventory.insertMany([ { "_id" : 1, "item" : "blue paint" }, { "_id" : 2, "item" : "blue and green paint" }, { "_id" : 3, "item" : "blue paint with blue paintbrush" }, { "_id" : 4, "item" : "blue paint with green paintbrush" }, ])
以下示例将 item
字段中 "blue paint" 的第一个实例替换为 "red paint"
db.inventory.aggregate([ { $project: { item: { $replaceOne: { input: "$item", find: "blue paint", replacement: "red paint" } } } } ])
操作返回以下结果
{ "_id" : 1, "item" : "red paint" } { "_id" : 2, "item" : "blue and green paint" } { "_id" : 3, "item" : "red paint with blue paintbrush" } { "_id" : 4, "item" : "red paint with green paintbrush" }
注意,在第 3
个文档中,仅替换了 "blue paint" 的第一个匹配实例。