带驱动程序的 MongoDB
定义
db.collection.findOneAndReplace( filter, replacement, options )根据指定的过滤器,替换单个文档。
兼容性
此方法可用于以下环境中托管的部署:
- MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
注意
所有 MongoDB Atlas 集群都支持此命令。有关 Atlas 对所有命令的支持的信息,请参阅不支持的命令。
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
The findOneAndReplace() method has the following form:
db.collection.findOneAndReplace( <filter>, <replacement>, { writeConcern: <document>, projection: <document>, sort: <document>, maxTimeMS: <number>, upsert: <boolean>, returnDocument: <string>, returnNewDocument: <boolean>, collation: <document> } )
字段和选项
The findOneAndReplace() method takes the following fields and options:
字段 | 类型 | 说明 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
文档 | ||||||||||||
文档 | ||||||||||||
| 文档 | |||||||||||
文档 | 可选。待返回字段的子集。 要返回匹配文档中的所有字段,请省略此字段。 如果投影参数不是文档,则操作会出错。 | |||||||||||
文档 | ||||||||||||
| 数字 | 可选。指定操作必须完成的时间限制(以毫秒为单位)。如果超出此限制,则会返回错误。 | ||||||||||
布尔 | Optional. When
如果 要避免多次更新或插入,请确保 默认值为 | |||||||||||
字符串 | 可选。从
| |||||||||||
布尔 | 可选。为 默认值为 | |||||||||||
文档 | 可选。 可选。指定用于操作的排序规则。 排序规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音符号规则。 排序规则选项的语法如下: 指定排序规则时, 如果未指定排序规则,但集合具有默认排序规则(请参阅 如果没有为收集或操作指定排序规则,MongoDB 将使用先前版本中使用的简单二进制比较来进行字符串比较。 您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果执行带排序的查找,则不能使用一种排序规则进行查找而另一种排序规则进行排序。 |
返回:
Returns the original document by default. Returns the updated document if returnDocument is set to after or returnNewDocument is set to true.
行为
文档匹配
db.collection.findOneAndReplace() replaces the first matching document in the collection that matches the filter. The sort field can be used to influence which document is modified.
投射
重要
语言一致性
在调整 find() 和 findAndModify() 投影以便与聚合的 $project 阶段保持一致的过程中:
find()和findAndModify()投影可以接受聚合表达式和事务语法。MongoDB 对投影执行额外的限制。有关详细信息,请参阅投影限制。
projection 字段采用以下格式的文档:
{ field1: <value>, field2: <value> ... }
投射 | 说明 |
|---|---|
| 指定包含字段。如果为投影值指定非零整数,则该操作会将该值视为 |
| 指定排除某个字段。 |
| |
| 使用数组投影操作符( 不可用于视图。 |
| 指定投影字段的值。 通过使用聚合表达式和语法(包括使用文本和聚合变量),可以投影新字段或使用新值投影现有字段。
|
嵌入式字段规范
对于嵌入文档中的字段,您可以使用以下任一方式指定字段:
点符号,例如
"field.nestedfield": <value>嵌套表单,例如
{ field: { nestedfield: <value> } }
_id 字段投影
默认情况下,返回的文档中包含 _id 字段,除非您在投影中显式指定 _id: 0 来隐藏该字段。
包括或排除
projection 不能同时包含包含和排除规范,但 _id 字段除外:
在显式包含字段的投影中,
_id字段是您可以显式排除的唯一字段。在明确排除字段的投影中,
_id字段是您可以明确包含的唯一字段;但是,默认情况下包含_id字段。
有关投影的更多信息,另请参阅:
分片集合
分片集合中的文档可能缺少分片键字段。要定位缺失分片键的文档,可将 null 等值匹配与其他过滤条件(例如针对 _id 字段)结合使用。例如:
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
分片键修改
您可以更新文档的分片键值,除非分片键字段是不可变的 _id 字段。
警告
分片集合中的文档可能缺少分片键字段。采取预防措施,避免在更改文档的分片键值时意外删除分片键。
To modify the existing shard key value with db.collection.findOneAndReplace():
必须在
mongos上运行。请勿直接对分片发出此操作。必须在完整分片键上包含相等筛选器。
缺少分片键
Documents in a sharded collection can be missing the shard key fields. To use db.collection.findOneAndReplace() to set the document's missing shard key,
必须在
mongos上运行。请勿直接对分片发出此操作。必须在完整分片键上包含相等筛选器。
提示
由于缺失的键值是作为 null 相等匹配的一部分返回的,因此为避免更新空值键,请酌情纳入其他查询条件(例如 _id 字段)。
另请参阅:
事务
db.collection.findOneAndReplace() can be used inside distributed transactions.
重要
在大多数情况下,与单文档写入操作相比,分布式事务会产生更高的性能成本,并且分布式事务的可用性不应取代有效的模式设计。在许多情况下,非规范化数据模型(嵌入式文档和数组)仍然是数据和使用案例的最佳选择。换言之,对于许多场景,适当的数据建模将最大限度地减少对分布式事务的需求。
有关其他事务使用注意事项(如运行时间限制和 oplog 大小限制),另请参阅生产注意事项。
在 ACID 事务中进行更新或插入 (upsert)
如果分布式事务不是跨分片写入事务,则可以在该事务中创建集合和索引。
db.collection.findOneAndReplace() with upsert: true can be run on an existing collection or a non-existing collection. If run on a non-existing collection, the operation creates the collection.
写关注和事务
如果是在事务中运行,则请勿显式设置此操作的写关注。要将写关注与事务一起使用,请参阅事务和写关注。
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,则操作将返回替换文档。
Although multiple documents meet the filter criteria, db.collection.findOneAndReplace() replaces only one document.
对文档进行排序和替换
使用以下文档创建示例 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 } ]);
By including an ascending sort on the score field, the following example replaces the document with the lowest score among those documents that match the filter:
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 } ])
The following operation uses projection to only display the team field in the returned document:
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" }