On this page
findAndModify
在本页面
Definition
findAndModify
- findAndModify命令修改并返回单个文档。默认情况下,返回的文档不包括对更新所做的修改。要返回对更新进行了修改的文档,请使用
new
选项。
- findAndModify命令修改并返回单个文档。默认情况下,返回的文档不包括对更新所做的修改。要返回对更新进行了修改的文档,请使用
该命令具有以下语法:
{
findAndModify: <collection-name>,
query: <document>,
sort: <document>,
remove: <boolean>,
update: <document>,
new: <boolean>,
fields: <document>,
upsert: <boolean>,
bypassDocumentValidation: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: <array>
}
findAndModify命令具有以下字段:
Field | Type | Description |
---|---|---|
query |
document | 可选的。修改的选择标准。 query 字段采用的是与db.collection.find()方法中相同的query selectors。尽管查询可能匹配多个文档,但findAndModify 将仅选择一个文档进行修改 。 |
如果未指定,则默认为空文档。
从 MongoDB 3.6.14(和 3.4.23)开始,如果查询参数不是文档,则操作错误。
| sort
|文档|可选。确定如果查询选择多个文档,则操作将修改哪个文档。 findAndModify以此参数指定的排序 Sequences 修改第一个文档。
从 MongoDB 3.6.14(和 3.4.23)开始,如果 sort 参数不是文档,则操作错误。
| remove
|布尔值|必须指定remove
或update
字段。删除在query
字段中指定的文档。将此设置为true
以删除所选的文档。默认值为false
。
| update
| document |必须指定remove
或update
字段。执行所选文档的更新。 update
字段采用相同的update operators或field: value
规范来修改所选文档。
| new
|布尔值|可选。 true
时,返回修改后的文档而不是原始文档。 findAndModify方法忽略remove
操作的new
选项。默认值为false
。
| fields
|文档|可选。要返回的字段子集。 fields
文档指定包含1
的字段,如fields: { <field1>: 1, <field2>: 1, ... }
。参见projection。
从 MongoDB 3.6.14(和 3.4.23)开始,如果 fields 参数不是文档,则操作错误。
| upsert
|布尔值|可选。与update
字段结合使用。
当true
,findAndModify()时:
如果没有文档与query
相匹配,则创建一个新文档。有关更多详细信息,请参见upsert behavior。
更新与query
匹配的单个文档。
为避免多次更新,请确保query
字段为uniquely indexed。
默认为false
。
| bypassDocumentValidation
|布尔值|可选。使findAndModify
在操作过程中绕过文档验证。这使您可以更新不满足验证要求的文档。
版本 3.2 中的新功能。
| writeConcern
|文档|可选。表示write concern的文档。省略使用默认的写关注。
版本 3.2 中的新功能。
| maxTimeMS
|整数|可选。指定用于处理操作的时间限制(以毫秒为单位)。
| findAndModify
| string |要针对其运行命令的集合。
| collation
|文档|可选。
指定用于操作的collation。
Collation允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。
排序规则选项具有以下语法:
collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}
指定排序规则时,locale
字段为必填字段;所有其他排序规则字段都是可选的。有关字段的说明,请参见Collation Document。
如果未指定排序规则,但是集合具有默认排序规则(请参见db.createCollection()),则该操作将使用为集合指定的排序规则。
如果没有为集合或操作指定排序规则,则 MongoDB 使用先前版本中使用的简单二进制比较进行字符串比较。
您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果对排序执行查找,则不能对查找使用一种排序规则,而对排序使用另一种排序规则。
3.4 版中的新功能。
| arrayFilters
| array |可选。筛选器文档数组,用于确定要对数组字段进行更新操作要修改的数组元素。
在更新文档中,使用$[<identifier>]过滤的位置运算符定义标识符,然后在数组过滤器文档中引用该标识符。如果更新文档中未包含标识符,则不能具有数组过滤器文档作为标识符。
Note
<identifier>
必须以小写字母开头,并且只能包含字母数字字符。
您可以在更新文档中多次包含相同的标识符;但是,对于更新文档中的每个唯一标识符($[identifier]
),您必须指定**完全对应的数组过滤器文档。即,您不能为同一标识符指定多个数组过滤器文档。例如,如果更新语句包含标识符x
(可能多次),则不能为arrayFilters
指定以下内容,其中包括x
的 2 个单独的过滤器文档:
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
br]
但是,您可以在单个过滤器文档中的同一标识符上指定复合条件,例如以下示例:
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
[
{ "x.a": { $gt: 85 },“ x.b”:{ $gt: 80 }}
br]
有关示例,请参见为阵列更新操作指定 arrayFilters。
3.6 版中的新功能。
Output
findAndModify命令返回包含以下字段的文档:
Field | Type | Description |
---|---|---|
value |
document | 包含命令的返回值。有关详情,请参见value。 |
lastErrorObject |
document | 包含有关更新文档的信息。有关详情,请参见lastErrorObject。 |
ok |
number | 包含命令的执行状态。成功则1 ,如果发生错误则0 。 |
lastErrorObject
lastErrorObject
嵌入式文档包含以下字段:
Field | Type | Description |
---|---|---|
updatedExisting |
boolean | 如果update 操作修改了现有文档,则包含true 。 |
upserted |
document | 如果对upsert: true 的update 操作导致了新文档,则包含所插入文档的ObjectId。 |
value
对于remove
操作,如果查询与文档匹配,则value
包含已删除的文档。如果查询与要删除的文档不匹配,则value
包含null
。
对于update
操作,嵌入value
的文档包含以下内容:
如果未设置
new
或false
:如果查询与文档匹配,则为修改前文档;
- 否则为
null
。
- 否则为
如果
new
是true
:如果查询返回匹配项,则修改后的文档;
如果
upsert: true
并且没有文档与查询匹配,则插入文档;否则为
null
。
在版本 3.0 中进行了更改:在以前的版本中,如果要进行更新,则指定sort
,并且指定upsert: true
,并且未设置new
选项或new: false
,则findAndModify在value
字段而不是null
中返回空文档{}
。
Behavior
Upsert 和唯一索引
当findAndModify命令包含upsert: true
选项 并且 查询字段未唯一索引时,该命令在某些情况下可以多次插入文档。
考虑一个示例,其中不存在名称为Andy
的文档,并且多个 Client 端发出以下命令:
db.runCommand(
{
findAndModify: "people",
query: { name: "Andy" },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
}
)
如果所有命令在任何命令开始modify
阶段之前完成query
阶段,并且name
字段上没有唯一索引,则每个命令都可能执行 upsert,从而创建多个重复文档。
为防止创建多个重复的文档,请在name
字段上创建一个unique index。有了唯一索引后,多个findAndModify命令将表现出以下行为之一:
恰好一个findAndModify成功插入了一个新文档。
零个或多个findAndModify命令将更新新插入的文档。
零个或多个findAndModify命令尝试插入重复项时失败。如果该命令由于唯一索引约束冲突而失败,则可以重试该命令。如果没有删除文档,重试应该不会失败。
Sharded Collections
Document Validation
findAndModify命令增加了对bypassDocumentValidation
选项的支持,该选项使您可以在使用验证规则在集合中插入或更新文档时绕过document validation。
与更新方法的比较
更新文档时,findAndModify和update()方法的操作不同:
默认情况下,这两个操作都将修改单个文档。但是,带有
multi
选项的update()方法可以修改多个文档。如果多个文档符合findAndModify的更新条件,则可以指定
sort
以提供对要更新的文档的某种控制措施。
使用update()方法的默认行为,您无法指定多个文档匹配时要更新的单个文档。
- 默认情况下,findAndModify返回一个对象,该对象包含文档的预修改版本以及操作状态。要获取更新的文档,请使用
new
选项。
update()方法返回包含操作状态的WriteResult对象。要返回更新的文档,请使用find()方法。但是,其他更新可能已在您的更新和文档检索之间修改了文档。同样,如果更新仅修改了一个文档,但匹配了多个文档,则您将需要使用其他逻辑来标识更新的文档。
修改单个文档时,findAndModify和update()方法都从原子上*更新该文档。有关这些方法的交互作用和操作 Sequences 的更多详细信息,请参见原子性和 Transaction。
Examples
更新并返回
以下命令更新people
集合中与query
条件匹配的现有文档:
db.runCommand(
{
findAndModify: "people",
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
}
)
该命令执行以下操作:
query
在people
集合中找到一个文档,其中name
字段的值为Tom
,state
字段的值为active
,而rating
字段的值为greater than
10.sort
以升序对查询结果进行排序。如果多个文档满足query
条件,该命令将按sort
的 Sequences 选择第一个文档进行修改。update
increments
score
字段的值加 1.该命令返回包含以下字段的文档:
包含命令详细信息的
lastErrorObject
字段,包括true
的字段updatedExisting
,以及包含为此更新选择的原始(即预先修改)文档的
value
字段:
{
"lastErrorObject" : {
"connectionId" : 1,
"updatedExisting" : true,
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
value" : {
"_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
"name" : "Tom",
"state" : "active",
"rating" : 100,
"score" : 5
},
"ok" : 1
}
要在value
字段中返回修改后的文档,请将new:true
选项添加到命令中。
如果没有任何文档符合query
条件,则该命令将返回value
字段中包含null
的文档:
{ "value" : null, "ok" : 1 }
mongo shell 和许多drivers提供了findAndModify()辅助方法。使用 shell 帮助器,此先前的操作可以采用以下形式:
db.people.findAndModify( {
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
} );
但是,findAndModify() shell 帮助程序方法仅返回未修改的文档,或者new
是true
,则返回修改后的文档。
{
"_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
"name" : "Tom",
"state" : "active",
"rating" : 100,
"score" : 5
}
upsert: true
以下findAndModify命令包含update
操作的upsert: true
选项,以更新匹配的文档,或者如果不存在匹配的文档,则创建新文档:
db.runCommand(
{
findAndModify: "people",
query: { name: "Gus", state: "active", rating: 100 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
}
)
如果该命令找到匹配的文档,则该命令将执行更新。
如果该命令“找不到**”找到匹配的文档,则update
和upsert: true操作将导致插入并返回包含以下字段的文档:
包含命令详细信息的
lastErrorObject
字段,包括包含新插入的文档的_id
值的字段upserted
,以及包含
null
的value
字段。
{
"value" : null,
"lastErrorObject" : {
"updatedExisting" : false,
"n" : 1,
"upserted" : ObjectId("54f62c8bc85d4472eadea26f")
},
"ok" : 1
}
返回新文件
以下findAndModify命令同时包含upsert: true
选项和new:true
选项。该命令或者更新匹配的文档并返回更新的文档,或者,如果不存在匹配的文档,则插入文档并在value
字段中返回新插入的文档。
在下面的示例中,people
集合中没有任何文档与query
条件匹配:
db.runCommand(
{
findAndModify: "people",
query: { name: "Pascal", state: "active", rating: 25 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true,
new: true
}
)
该命令在value
字段中返回新插入的文档:
{
"lastErrorObject" : {
"connectionId" : 1,
"updatedExisting" : false,
"upserted" : ObjectId("54f62bbfc85d4472eadea26d"),
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62bbfc85d4472eadea26d"),
"name" : "Pascal",
"rating" : 25,
"state" : "active",
"score" : 1
},
"ok" : 1
}
排序并删除
通过在rating
字段中包含sort
规范,以下示例从people
集合中删除state
值为active
且匹配文件中最低rating
的单个文档:
db.runCommand(
{
findAndModify: "people",
query: { state: "active" },
sort: { rating: 1 },
remove: true
}
)
该命令返回已删除的文档:
{
"lastErrorObject" : {
"connectionId" : 1,
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62a6785e4be1f982b9c9b"),
"name" : "XYZ123",
"score" : 1,
"state" : "active",
"rating" : 3
},
"ok" : 1
}
Specify Collation
3.4 版的新功能。
Collation允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。
集合myColl
具有以下文档:
{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }
以下操作包括collation选项:
db.runCommand(
{
findAndModify: "myColl",
query: { category: "cafe", status: "a" },
sort: { category: 1 },
update: { $set: { status: "Updated" } },
collation: { locale: "fr", strength: 1 }
}
)
该操作返回以下文档:
{
"lastErrorObject" : {
"updatedExisting" : true,
"n" : 1
},
"value" : {
"_id" : 1,
"category" : "café",
"status" : "A"
},
"ok" : 1
}
为阵列更新操作指定 arrayFilters
3.6 版的新功能。
从 MongoDB 3.6 开始,在更新数组字段时,您可以指定arrayFilters
来确定要更新的数组元素。
更新元素匹配 arrayFilters 条件
创建包含以下文档的集合students
:
db.students.insert([
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
])
要修改grades
数组中所有大于或等于100
的元素,请使用带有arrayFilters
选项的位置$[<identifier>]运算符:
db.runCommand(
{
findAndModify: "students",
query: { grades: { $gte: 100 } },
update: { $set: { "grades.$[element]" : 100 } },
arrayFilters: [ { "element": { $gte: 100 } } ]
}
)
该操作更新单个文档的grades
字段,并且在操作之后,该集合具有以下文档:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
更新一系列文档的特定元素
创建包含以下文档的集合students2
:
db.students2.insert([
{
"_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 }
]
}
])
要为grades
数组中评分大于或等于85
的所有元素修改mean
字段的值,请对arrayFilters
使用位置$[<identifier>]运算符:
db.runCommand(
{
findAndModify: "students2",
query: { },
update: { $set: { "grades.$[elem].mean" : 100 } },
arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
}
)
该操作更新单个文档的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 }
]
}
See also