db.collection.findOneAndReplace()
带驱动程序的 MongoDB
本页面提供 mongosh
方法的相关信息。要查看 MongoDB 驱动程序中的等效方法,请参阅编程语言的相应页面:
定义
db.collection.findOneAndReplace( filter, replacement, options )
根据指定的过滤器,替换单个文档。
语法
findOneAndReplace()
方法采用以下形式:
db.collection.findOneAndReplace( <filter>, <replacement>, { writeConcern: <document>, projection: <document>, sort: <document>, maxTimeMS: <number>, upsert: <boolean>, returnDocument: <string>, returnNewDocument: <boolean>, collation: <document> } )
字段和选项
findOneAndReplace()
方法采用以下字段和选项:
字段 | 类型 | 说明 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
文档 | ||||||||||||
文档 | ||||||||||||
writeConcern | 文档 | |||||||||||
文档 | 可选。待返回字段的子集。 要返回匹配文档中的所有字段,请省略此字段。 如果投影参数不是文档,则操作会出错。 | |||||||||||
文档 | ||||||||||||
maxTimeMS | 数字 | 可选。指定操作必须完成的时间限制(以毫秒为单位)。如果超出此限制,则会返回错误。 | ||||||||||
布尔 | 可选。当为
如果 要避免多次更新或插入,请确保 默认值为 | |||||||||||
字符串 | 可选。从
| |||||||||||
布尔 | 可选。为 默认值为 | |||||||||||
文档 | 可选。 指定用于操作的排序规则。 排序规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音符号规则。 排序规则选项的语法如下:
指定排序规则时, 如果未指定排序规则,但集合具有默认排序规则(请参阅 如果没有为收集或操作指定排序规则,MongoDB 将使用先前版本中使用的简单二进制比较来进行字符串比较。 您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果执行带排序的查找,则不能使用一种排序规则进行查找而另一种排序规则进行排序。 |
返回:
默认返回原始文档。如果将 returnDocument 设为 after
或将 returnNewDocument 设为 true
,则返回更新后的文档。
行为
文档匹配
db.collection.findOneAndReplace()
替换集合中与 filter
匹配的第一份文档。sort
字段可用于影响修改哪个文档。
投射
重要
语言一致性
在调整 find()
和 findAndModify()
投影以便与聚合的 $project
阶段保持一致的过程中:
find()
和findAndModify()
投影可以接受聚合表达式和事务语法。MongoDB 对投影执行额外的限制。有关详细信息,请参阅投影限制。
projection
字段采用以下格式的文档:
{ field1: <value>, field2: <value> ... }
投射 | 说明 |
---|---|
<field>: <1 or true> | 指定包含字段。如果为投影值指定非零整数,则该操作会将该值视为 true 。 |
<field>: <0 or false> | 指定排除某个字段。 |
"<field>.$": <1 or true> | |
<field>: <array projection> | 使用数组投影操作符( 不可用于视图。 |
<field>: <aggregation expression> | 指定投影字段的值。 通过使用聚合表达式和语法(包括使用文本和聚合变量),可以投影新字段或使用新值投影现有字段。
|
嵌入式字段规范
对于嵌入文档中的字段,您可以使用以下任一方式指定字段:
点符号,例如
"field.nestedfield": <value>
嵌套表单,例如
{ field: { nestedfield: <value> } }
_id
字段投影
默认情况下,返回的文档中包含 _id
字段,除非您在投影中显式指定 _id: 0
来隐藏该字段。
包括或排除
projection
不能同时包含包含和排除规范,但 _id
字段除外:
在显式包含字段的投影中,
_id
字段是您可以显式排除的唯一字段。在明确排除字段的投影中,
_id
字段是您可以明确包含的唯一字段;但是,默认情况下包含_id
字段。
有关投影的更多信息,另请参阅:
分片集合
要在分片集合上使用 db.collection.findOneAndReplace()
,查询过滤器 必须在分片键上包含相等条件。
分片集合中的文档可能缺少分片键字段。要定位缺失分片键的文档,可将 null
等值匹配与其他过滤条件(例如针对 _id
字段)结合使用。例如:
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
分片键修改
您可以更新文档的分片键值,除非分片键字段是不可变的 _id
字段。
警告
分片集合中的文档可能缺少分片键字段。采取预防措施,避免在更改文档的分片键值时意外删除分片键。
要修改现有的分片键值(使用db.collection.findOneAndReplace()
):
缺少分片键
分片集合中的文档可能 缺少分片键字段。 要使用 db.collection.findOneAndReplace()
设置文档缺失的分片键,
提示
由于缺失的键值是作为 null 相等匹配的一部分返回的,因此为避免更新空值键,请酌情纳入其他查询条件(例如 _id
字段)。
另请参阅:
事务
db.collection.findOneAndReplace()
可以在分布式事务中使用。
重要
在大多数情况下,与单文档写入操作相比,分布式事务会产生更高的性能成本,并且分布式事务的可用性不应取代有效的模式设计。在许多情况下,非规范化数据模型(嵌入式文档和数组)仍然是数据和使用案例的最佳选择。换言之,对于许多场景,适当的数据建模将最大限度地减少对分布式事务的需求。
有关其他事务使用注意事项(如运行时间限制和 oplog 大小限制),另请参阅生产注意事项。
在 ACID 事务中进行更新或插入 (upsert)
如果分布式事务不是跨分片写入事务,则可以在该事务中创建集合和索引。
具有 upsert: true
的 db.collection.findOneAndReplace()
可以在现有集合或不存在的集合上运行。如果在不存在的集合上运行,该操作将创建集合。
写关注和事务
如果是在事务中运行,则请勿显式设置此操作的写关注。要将写关注与事务一起使用,请参阅事务和写关注。
Oplog 条目
如果 db.collection.findOneAndReplace()
操作成功替换了文档,则该操作会为 oplog(操作日志)添加一个条目。如果操作失败或未找到要替换的文档,则该操作不会为 oplog 添加条目。
示例
替换文档
使用以下文档创建示例 scores
集合:
db.scores.insertMany([ { "_id" : 1, "team" : "Fearful Mallards", "score" : 25000 }, { "_id" : 2, "team" : "Tactful Mooses", "score" : 23500 }, { "_id" : 3, "team" : "Aquatic Ponies", "score" : 19250 }, { "_id" : 4, "team" : "Cuddly Zebras", "score" : 15235 }, { "_id" : 5, "team" : "Garrulous Bears", "score" : 18000 } ]);
以下操作将查找score
小于 20000
的文档并将其替换:
db.scores.findOneAndReplace( { "score" : { $lt : 20000 } }, { "team" : "Observant Badgers", "score" : 20000 } )
此操作会返回被替换的原始文档:
{ "_id" : 3, "team" : "Aquatic Ponies", "score" : 19250 }
如果 returnNewDocument 为 true,则操作将返回替换文档。
虽有多个文档符合过滤条件,但 db.collection.findOneAndReplace()
仅会替换一个文档。
对文档进行排序和替换
使用以下文档创建示例 scores
集合:
db.scores.insertMany([ { "_id" : 1, "team" : "Fearful Mallards", "score" : 25000 }, { "_id" : 2, "team" : "Tactful Mooses", "score" : 23500 }, { "_id" : 3, "team" : "Aquatic Ponies", "score" : 19250 }, { "_id" : 4, "team" : "Cuddly Zebras", "score" : 15235 }, { "_id" : 5, "team" : "Garrulous Bears", "score" : 18000 } ]);
通过对 score
字段加入升序排序,以下示例会将该文件替换为与此过滤条件匹配的文档中分数最低的文档:
db.scores.findOneAndReplace( { "score" : { $lt : 20000 } }, { "team" : "Observant Badgers", "score" : 20000 }, { sort: { "score" : 1 } } )
此操作会返回被替换的原始文档:
{ "_id" : 4, "team" : "Cuddly Zebras", "score" : 15235 }
请参阅替换文档以了解此命令的非排序结果。
返回文档中的项目特定字段
使用以下文档创建示例 scores
集合:
db.scores.insertMany([ { "_id" : 1, "team" : "Fearful Mallards", "score" : 25000 }, { "_id" : 2, "team" : "Tactful Mooses", "score" : 23500 }, { "_id" : 3, "team" : "Aquatic Ponies", "score" : 19250 }, { "_id" : 4, "team" : "Cuddly Zebras", "score" : 15235 }, { "_id" : 5, "team" : "Garrulous Bears", "score" : 18000 } ])
以下操作使用投影,仅显示返回文档中的 team
字段:
db.scores.findOneAndReplace( { "score" : { $lt : 22250 } }, { "team" : "Therapeutic Hamsters", "score" : 22250 }, { sort : { "score" : 1 }, projection: { "_id" : 0, "team" : 1 } } )
该操作返回仅包含 team
字段的原始文档:
{ "team" : "Cuddly Zebras" }
用 Time Limit 替换文档
以下操作设置了 5ms 的完成时间限制:
try { db.scores.findOneAndReplace( { "score" : { $gt : 25000 } }, { "team" : "Emphatic Rhinos", "score" : 25010 }, { maxTimeMS: 5 } ); } catch(e){ print(e); }
如果操作超过时间限制,将会返回:
Error: findAndModifyFailed failed: { "ok" : 0, "errmsg" : "operation exceeded time limit", "code" : 50 }
使用更新插入操作替换文档
如果没有与 filter 匹配的文档,以下操作将使用 upsert 字段插入替换文档:
try { db.scores.findOneAndReplace( { "team" : "Fortified Lobsters" }, { "_id" : 6019, "team" : "Fortified Lobsters" , "score" : 32000}, { upsert : true, returnDocument: "after" } ); } catch (e){ print(e); }
该操作返回以下内容:
{ "_id" : 6019, "team" : "Fortified Lobsters", "score" : 32000 }
如果设置了 returnDocument: "before"
,此操作则会返回 null
,因为没有要返回的原始文档。
指定排序规则。
排序规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音符号规则。
使用以下文档创建示例 myColl
集合:
db.myColl.insertMany([ { _id: 1, category: "café", status: "A" }, { _id: 2, category: "cafe", status: "a" }, { _id: 3, category: "cafE", status: "a" } ]);
以下操作包含排序规则选项:
db.myColl.findOneAndReplace( { category: "cafe", status: "a" }, { category: "cafÉ", status: "Replaced" }, { collation: { locale: "fr", strength: 1 } } );
该操作将返回以下文档:
{ "_id" : 1, "category" : "café", "status" : "A" }