On this page本页内容
db.collection.findAndModify(document)
This is a mongosh
method. This is not the documentation for Node.js
or other programming language specific driver methods.
In most cases, mongosh
methods work the same way as the legacy mongo
shell methods. However, some legacy methods are unavailable in mongosh
.
For the legacy mongo
shell documentation, refer to the documentation for the corresponding MongoDB Server release:
For MongoDB API drivers, refer to the language specific MongoDB driver documentation.
Modifies and returns a single document. 修改并返回单个文档。By default, the returned document does not include the modifications made on the update. 默认情况下,返回的文档不包含更新时所做的修改。To return the document with the modifications made on the update, use the 要返回更新时所做修改的文档,请使用new
option. new
选项。The findAndModify()
method is a shell helper around the findAndModify
command.findAndModify()
方法是findAndModify
命令周围的shell助手。
Changed in version 5.0.在版本5.0中更改。
The findAndModify()
method has the following form:findAndModify()
方法具有以下形式:
db.collection.findAndModify({ query: <document>, sort: <document>, remove: <boolean>, update: <document or aggregation pipeline>, // Changed in MongoDB 4.2 new: <boolean>, fields: <document>, upsert: <boolean>, bypassDocumentValidation: <boolean>, writeConcern: <document>, collation: <document>, arrayFilters: [ <filterdocument1>, ... ], let: <document> // Added in MongoDB 5.0 });
The db.collection.findAndModify()
method takes a document parameter with the following embedded document fields:db.collection.findAndModify()
方法接受一个包含以下嵌入文档字段的文档参数:
query | document |
|
| document |
|
remove | boolean | remove or the update field. remove 或update 字段。query field. query 字段中指定的文档。true to remove the selected document . true 可删除所选文档。false .false 。
|
update | document or array |
|
new | boolean | true , returns the modified document rather than the original. true ,则返回修改后的文档,而不是原始文档。db.collection.findAndModify() method ignores the new option for remove operations. db.collection.findAndModify() 方法忽略remove 操作的新选项。false .false 。
|
fields | document |
|
upsert | boolean |
|
bypassDocumentValidation | boolean | db.collection.findAndModify() to bypass document validation during the operation. db.collection.findAndModify() 在操作期间绕过文档验证。 |
writeConcern | document |
|
maxTimeMS | integer | |
collation | document |
collation: { locale: <string>, caseLevel: <boolean>, caseFirst: <string>, strength: <int>, numericOrdering: <boolean>, alternate: <string>, maxVariable: <string>, backwards: <boolean> }
|
arrayFilters | array |
// INVALID [ { "x.a": { $gt: 85 } }, { "x.b": { $gt: 80 } } ]
// Example 1 [ { $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] } ] // Example 2 [ { $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] } ] // Example 3 [ { "x.a": { $gt: 85 }, "x.b": { $gt: 80 } } ]
|
let | document | Optional.
{ <variable_name_1>: <expression_1>, ..., <variable_name_n>: <expression_n> }
|
For remove operations, if the query matches a document, 对于删除操作,如果查询与文档匹配,findAndModify()
returns the removed document. findAndModify()
将返回删除的文档。If the query does not match a document to remove, 如果查询与要删除的文档不匹配,findAndModify()
returns null
.findAndModify()
将返回null
。
For update operations, 对于更新操作,findAndModify()
returns one of the following:findAndModify()
返回以下值之一:
If the 如果new
parameter is not set or is false
:new
参数未设置或为false
:
null
.null
。If 如果new
is true
:new
为true
:
upsert: true
and no document matches the query;upsert:true
,且没有与查询匹配的文档则插入的文档null
.null
。fields
ProjectionStarting in MongoDB 4.4, as part of making 从MongoDB 4.4开始,作为使find()
and findAndModify()
projection consistent with aggregation's $project
stage,find()
和findAndModify()
投影与聚合的 $project
阶段一致的一部分,
find()
and findAndModify()
projection can accept aggregation expressions and syntax.find()
和findAndModify()
投影可以接受聚合表达式和语法。The fields
option takes a document in the following form:fields
选项采用以下格式的文档:
{ field1: <value>, field2: <value> ... }
<field>: <1 or true> | true .true 。 |
<field>: <0 or false> | |
"<field>.$": <1 or true> | $ array projection operator, you can specify the projection to return the first element that match the query condition on the array field; e.g. "arrayField.$" : 1 . $ 数组投影运算符,可以指定投影以返回与数组字段上的查询条件匹配的第一个元素;例如"arrayField.$" : 1 。true .true 。 |
<field>: <array projection> | $elemMatch , $slice , specifies the array element(s) to include, thereby excluding those elements that do not meet the expressions. $elemMatch ,$slice 指定要包含的数组元素,从而排除那些不符合表达式的元素。 |
<field>: <aggregation expression> |
|
For fields in an embedded documents, you can specify the field using either:对于嵌入文档中的字段,可以使用以下方法之一指定字段:
"field.nestedfield": <value>
{ field: { nestedfield: <value> } }
_id
The 默认情况下,_id
field is included in the returned documents by default unless you explicitly specify _id: 0
in the projection to suppress the field._id
字段包含在返回的文档中,除非您在投影中明确指定_id:0
以抑制该字段。
A projection
cannot contain both include and exclude specifications, with the exception of the _id
field:projection
不能同时包含包含和排除规范,_id
字段除外:
_id
field is the only field that you can explicitly exclude._id
字段是唯一可以显式排除的字段。_id
field is the only field that you can explicitly include; however, the _id
field is included by default._id
字段是唯一可以显式包含的字段;然而,默认情况下包含_id
字段。For more information on projection, see also:有关投影的详细信息,另请参见:
When using the 在将upsert: true
option with the findOneAndUpdate()
method, and not using a unique index on the query field(s), multiple instances of a findOneAndUpdate()
operation with similar query field(s) could result in duplicate documents being inserted in certain circumstances.upsert:true
选项与findOneAndUpdate()
方法一起使用时,如果不对查询字段使用唯一索引,则具有类似查询字段的findOneAndUpdate()
操作的多个实例可能会导致在某些情况下插入重复的文档。
Consider an example where no document with the name 考虑一个示例,其中不存在名为Andy
exists and multiple clients issue the following command at roughly the same time:Andy
的文档,并且多个客户端大致同时发出以下命令:
db.people.findAndModify( { query: { name: "Andy" }, update: { $inc: { score: 1 } }, upsert: true } )
If all 如果所有findOneAndUpdate()
operations finish the query phase before any client successfully inserts data, and there is no unique index on the name
field, each findOneAndUpdate()
operation may result in an insert, creating multiple documents with name: Andy
.findOneAndUpdate()
操作都在任何客户端成功插入数据之前完成了查询阶段,并且name
字段上没有唯一索引,则每个findOneAndUpdate()
操作都可能导致插入,从而创建多个name: Andy
的文档。
To ensure that only one such document is created, and the other 为了确保只创建一个这样的文档,而其他findOneAndUpdate()
operations update this new document instead, create a unique index on the name
field. findOneAndUpdate()
操作会更新这个新文档,请在name
字段上创建一个唯一索引。This guarantees that only one document with 这保证了集合中只允许一个name: Andy
is permitted in the collection.name: Andy
的文档。
With this unique index in place, the multiple 有了这个唯一的索引,多个findOneAndUpdate()
operations now exhibit the following behavior:findOneAndUpdate()
操作现在表现出以下行为:
findOneAndUpdate()
operation will successfully insert a new document.findOneAndUpdate()
操作即可成功插入新文档。findOneAndUpdate()
operations will update the newly-inserted document, incrementing the score
value.findOneAndUpdate()
操作都将更新新插入的文档,并增加score
值。When using 对分片集合使用findAndModify
against a sharded collection, the query
must contain an equality condition on shard key.findAndModify
时,query
必须包含分片键上的相等条件。
Starting in version 4.4, documents in a sharded collection can be missing the shard key fields. 从4.4版开始,分片集合中的文档可能会缺少分片键字段。To target a document that is missing the shard key, you can use the 要将缺少分片键的文档作为目标,可以将null
equality match in conjunction with another filter condition (such as on the _id
field). null
等式匹配与另一个筛选条件(如_id
字段)结合使用。For example:例如:
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
Starting in MongoDB 4.2, you can update a document's shard key value unless the shard key field is the immutable 从MongoDB 4.2开始,您可以更新文档的分片键值,除非分片键区是不可变的_id
field. _id
字段。In MongoDB 4.2 and earlier, a document's shard key field value is immutable.在MongoDB4.2及更早版本中,文档的分片键字段值是不可变的。
Starting in version 4.4, documents in sharded collections can be missing the shard key fields. 从4.4版开始,分片集合中的文档可能会缺少分片键字段。Take precaution to avoid accidentally removing the shard key when changing a document's shard key value.在更改文档的分片键值时,请采取预防措施,以避免意外删除分片键。
To modify the existing shard key value with 要使用db.collection.findAndModify()
:db.collection.findAndModify()
修改现有的共享密钥值,请执行以下操作:
mongos
. mongos
上。Starting in version 4.4, documents in a sharded collection can be missing the shard key fields. 从4.4版开始,分片集合中的文档可能会缺少分片键字段。To use 要使用db.collection.findAndModify()
to set the document's missing shard key:db.collection.findAndModify()
设置文档缺少的分片键,请执行以下操作:
mongos
. mongos
上。null
.Since a missing key value is returned as part of a null equality match, to avoid updating a null-valued key, include additional query conditions (such as on the 由于缺少的键值作为_id
field) as appropriate.null
相等匹配的一部分返回,为了避免更新null
值键值,请酌情包括其他查询条件(例如在_id
字段上)。
See also:另请参见:
The db.collection.findAndModify()
method adds support for the bypassDocumentValidation
option, which lets you bypass document validation when inserting or updating documents in a collection with validation rules.db.collection.findAndModify()
方法添加了对绕过bypassDocumentValidation
选项的支持,该选项允许您在使用验证规则插入或更新集合中的文档时绕过文档验证。
update
Methodupdate
方法的比较When updating a document, 更新文档时,db.collection.findAndModify()
and the updateOne()
method operate differently:db.collection.findAndModify()
和updateOne()
方法的操作方式不同:
If multiple documents match the update criteria, for 如果多个文档符合更新条件,那么对于db.collection.findAndModify()
, you can specify a sort
to provide some measure of control on which document to update.db.collection.findAndModify()
,您可以指定一种排序,以提供对要更新的文档的某种控制措施。
updateOne()
updates the first document that matches.更新第一个匹配的文档。
By default, 默认情况下,db.collection.findAndModify()
returns the pre-modified version of the document. db.collection.findAndModify()
返回文档的预修改版本。To obtain the updated document, use the 要获取更新的文档,请使用new
option.new
选项。
The updateOne()
method returns a WriteResult()
object that contains the status of the operation.updateOne()
方法返回包含操作状态的WriteResult()
对象。
To return the updated document, use the 要返回更新后的文档,请使用find()
method. find()
方法。However, other updates may have modified the document between your update and the document retrieval. 但是,其他更新可能在更新和文档检索之间修改了文档。Also, if the update modified only a single document but multiple documents matched, you will need to use additional logic to identify the updated document.此外,如果更新只修改了一个文档,但匹配了多个文档,则需要使用其他逻辑来标识更新的文档。
When modifying a single document, both 修改单个文档时,db.collection.findAndModify()
and the updateOne()
method atomically update the document. db.collection.findAndModify()
和updateOne()
方法都会自动更新文档。See Atomicity and Transactions for more details about interactions and order of operations of these methods.有关这些方法的交互和操作顺序的更多详细信息,请参阅原子性和事务。
db.collection.findAndModify()
can be used inside multi-document transactions.可以在多文档事务中使用。
In most cases, multi-document transaction incurs a greater performance cost over single document writes, and the availability of multi-document transactions should not be a replacement for effective schema design. 在大多数情况下,与单文档写入相比,多文档事务会带来更大的性能成本,并且多文档事务的可用性不应取代有效的模式设计。For many scenarios, the denormalized data model (embedded documents and arrays) will continue to be optimal for your data and use cases. 对于许多场景,非规范化的数据模型(嵌入式文档和数组)将继续是您的数据和用例的最佳选择。That is, for many scenarios, modeling your data appropriately will minimize the need for multi-document transactions.也就是说,对于许多场景,适当地建模数据将最小化多文档事务的需要。
For additional transactions usage considerations (such as runtime limit and oplog size limit), see also Production Considerations.有关其他事务使用注意事项(如运行时限制和oplog大小限制),请参阅生产注意事项。
Starting in MongoDB 4.4, you can create collections and indexes inside a multi-document transaction if the transaction is not a cross-shard write transaction从MongoDB 4.4开始,如果事务不是跨分片写入事务,则可以在多文档事务内创建集合和索引.
Specifically, in MongoDB 4.4 and greater, 具体来说,在MongoDB 4.4及更高版本中,带有db.collection.findAndModify()
with upsert: true
can be run on an existing collection or a non-existing collection. upsert:true
的db.collection.findAndModify()
可以在现有集合或不存在的集合上运行。If run on a non-existing collection, the operation creates the collection.如果在不存在的集合上运行,则该操作将创建集合。
In MongoDB 4.2 and earlier, the operation must be run on an existing collection.在MongoDB 4.2及更早版本中,操作必须在现有集合上运行。
Do not explicitly set the write concern for the operation if run in a transaction. 如果在事务中运行,请不要显式设置操作的写入关注点。To use write concern with transactions, see Transactions and Write Concern.要对事务使用写关注点,请参阅事务和写关注点。
The following method updates and returns an existing document in the people collection where the document matches the query criteria:以下方法更新并返回人员集合中与查询条件匹配的现有文档:
db.people.findAndModify({ query: { name: "Tom", state: "active", rating: { $gt: 10 } }, sort: { rating: 1 }, update: { $inc: { score: 1 } } })
This method performs the following actions:此方法执行以下操作:
query
finds a document in the people
collection where the name
field has the value Tom
, the state
field has the value active
and the rating
field has a value greater than
10.query
在people
集合中查找一个文档,其中name
字段的值为Tom
,state
字段的值是active
,而rating
字段的值大于10
。sort
orders the results of the query in ascending order. sort
将按升序对查询结果进行排序。query
condition, the method will select for modification the first document as ordered by this sort
.query
条件,该方法将选择按此sort
顺序修改第一个文档。increments
the value of the score
field by 1.score
字段的值增加1
。The method returns the original (i.e. pre-modification) document selected for this update:该方法返回为此更新选择的原始(即修改前)文档:
{ "_id" : ObjectId("50f1e2c99beb36a0f45c6453"), "name" : "Tom", "state" : "active", "rating" : 100, "score" : 5 }
To return the modified document, add the 要返回修改过的文档,请将new:true
option to the method.new:true
选项添加到方法中。
If no document matched the 如果没有与query
condition, the method returns null
.query
条件匹配的文档,该方法将返回null
。
The following method includes the 以下方法包括upsert: true
option for the update
operation to either update a matching document or, if no matching document exists, create a new document:upsert:true
选项,用于update
操作以更新匹配文档,或者如果不存在匹配文档,则创建新文档:
db.people.findAndModify({ query: { name: "Gus", state: "active", rating: 100 }, sort: { rating: 1 }, update: { $inc: { score: 1 } }, upsert: true })
If the method finds a matching document, the method performs an update.如果该方法找到匹配的文档,该方法将执行更新。
If the method does not find a matching document, the method creates a new document. 如果该方法未找到匹配的文档,则该方法将创建一个新文档。Because the method included the 因为该方法包含sort
option, it returns an empty document { }
as the original (pre-modification) document:sort
选项,所以它返回一个空文档{}
作为原始(修改前)文档:
{ }
If the method did not include a 如果该方法不包括sort
option, the method returns null
.sort
选项,则该方法返回null
。
null
The following method includes both the 以下方法包括upsert: true
option and the new:true
option. upsert:true
选项和new:true
。The method either updates a matching document and returns the updated document or, if no matching document exists, inserts a document and returns the newly inserted document in the 该方法更新匹配的文档并返回更新的文档,或者,如果不存在匹配的文档,则插入文档并在value
field.value
字段中返回新插入的文档。
In the following example, no document in the 在下面的示例中,people
collection matches the query
condition:people
集合中没有与query
条件匹配的文档:
db.people.findAndModify({ query: { name: "Pascal", state: "active", rating: 25 }, sort: { rating: 1 }, update: { $inc: { score: 1 } }, upsert: true, new: true })
The method returns the newly inserted document:该方法返回新插入的文档:
{ "_id" : ObjectId("50f49ad6444c11ac2448a5d6"), "name" : "Pascal", "rating" : 25, "score" : 1, "state" : "active" }
By including a 通过在sort
specification on the rating
field, the following example removes from the people
collection a single document with the state
value of active
and the lowest rating
among the matching documents:rating
字段中包含sort
规范,以下示例从people
集合中删除state
值为active
且在匹配文档中rating
最低的单个文档:
db.people.findAndModify( { query: { state: "active" }, sort: { rating: 1 }, remove: true } )
The method returns the deleted document:该方法返回已删除的文档:
{ "_id" : ObjectId("52fba867ab5fdca1299674ad"), "name" : "XYZ123", "score" : 1, "state" : "active", "rating" : 3 }
Collation allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks.排序规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音标记的规则。
A collection 集合myColl
has the following documents:myColl
包含以下文档:
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
The following operation includes the collation option:以下操作包括collation
选项:
db.myColl.findAndModify({ query: { category: "cafe", status: "a" }, sort: { category: 1 }, update: { $set: { status: "Updated" } }, collation: { locale: "fr", strength: 1 } });
The operation returns the following document:该操作返回以下文档:
{ "_id" : 1, "category" : "café", "status" : "A" }
arrayFilters
for an Array Update OperationsarrayFilters
arrayFilters
is not available for updates that use an aggregation pipeline.不可用于使用聚合管道的更新。
Starting in MongoDB 3.6, when updating an array field, you can specify 从MongoDB 3.6开始,在更新数组字段时,可以指定arrayFilters
that determine which array elements to update.arrayFilters
来确定要更新的数组元素。
arrayFilters
CriteriaarrayFilters
条件arrayFilters
is not available for updates that use an aggregation pipeline.不可用于使用聚合管道的更新。
Create a collection 使用以下文档创建集合students
with the following documents:students
:
db.students.insertMany( [ { "_id" : 1, "grades" : [ 95, 92, 90 ] }, { "_id" : 2, "grades" : [ 98, 100, 102 ] }, { "_id" : 3, "grades" : [ 95, 110, 100 ] } ] )
To modify all elements that are greater than or equal to 要修改100
in the grades
array, use the filtered positional operator $[<identifier>]
with the arrayFilters
option in the db.collection.findAndModify()
method:grades
数组中大于或等于100
的所有元素,请在db.collection.findAndModify()
方法中使用带arrayFilters
选项的筛选位置运算符$[<identifier>]
:
db.students.findAndModify({ query: { grades: { $gte: 100 } }, update: { $set: { "grades.$[element]" : 100 } }, arrayFilters: [ { "element": { $gte: 100 } } ] })
The operation updates the 该操作将更新单个文档的grades
field for a single document, and after the operation, the collection has the following documents:grades
字段,操作完成后,集合将包含以下文档:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 110, 100 ] }
arrayFilters
is not available for updates that use an aggregation pipeline.不可用于使用聚合管道的更新。
Create a collection 使用以下文档创建一个集合students2
with the following documents:students2
:
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
The following operation finds a document where the 以下操作查找_id
field equals 1
and uses the filtered positional operator $[<identifier>]
with the arrayFilters
to modify the mean
for all elements in the grades
array where the grade is greater than or equal to 85
._id
字段等于1
的文档,并使用带arrayFilters
的筛选位置运算符$[<identifier>]
修改分数大于或等于85
的grades
数组中所有元素的mean
值。
db.students2.findAndModify({ query: { _id : 1 }, update: { $set: { "grades.$[elem].mean" : 100 } }, arrayFilters: [ { "elem.grade": { $gte: 85 } } ] })
The operation updates the 该操作将更新单个文档的grades
field for a single document, and after the operation, the collection has the following documents:grades
字段,操作完成后,集合将包含以下文档:
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 100, "std" : 4 }, { "grade" : 85, "mean" : 100, "std" : 6 } ] } { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] }
Starting in MongoDB 4.2, 从MongoDB 4.2开始,db.collection.findAndModify()
can accept an aggregation pipeline for the update. db.collection.findAndModify()
可以接受更新的聚合管道。The pipeline can consist of the following stages:管道可包括以下阶段:
$addFields
$set
$project
$unset
$replaceRoot
$replaceWith
.Using the aggregation pipeline allows for a more expressive update statement, such as expressing conditional updates based on current field values or updating one field using the value of another field(s).使用聚合管道可以使用更具表现力的更新语句,例如基于当前字段值表达条件更新,或使用另一个字段的值更新一个字段。
For example, create a collection 例如,使用以下文档创建一个集合students2
with the following documents:students2
:
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
The following operation finds a document where the 以下操作查找_id
field equals 1
and uses an aggregation pipeline to calculate a new field total
from the grades
field:_id
字段等于1
的文档,并使用聚合管道从grades
字段计算新的字段total
:
db.students2.findAndModify( { query: { "_id" : 1 }, update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage new: true } )
The operation returns the updated document:操作返回更新后的文档:
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ], "total" : 250 }
let
let
中使用变量New in version 5.0.在版本5.0中新增。
To define variables that you can access elsewhere in the command, use the let option.要定义可以在命令的其他地方访问的变量,请使用let
选项。
Create a collection 创建集合cakeFlavors
:cakeFlavors
:
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
The following example defines a 下面的示例在targetFlavor
variable in let
and uses the variable to change the cake flavor from cherry to orange:let
中定义了一个targetFlavor
变量,并使用该变量将蛋糕口味从樱桃更改为橙色:
db.cakeFlavors.findAndModify( { query: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, update: { flavor: "orange" }, let: { targetFlavor: "cherry" } } )