On this page
db.collection.findOneAndUpdate()
在本页面
Definition
db.collection.
findOneAndUpdate
(* filter , update , options *)- 3.2 版中的新功能。
根据filter
和sort
标准更新单个文档。
findOneAndUpdate()方法具有以下形式:
在版本 3.6 中更改。
db.collection.findOneAndUpdate(
<filter>,
<update>,
{
projection: <document>,
sort: <document>,
maxTimeMS: <number>,
upsert: <boolean>,
returnNewDocument: <boolean>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
findOneAndUpdate()方法采用以下参数:
Parameter | Type | Description |
---|---|---|
filter |
document | 更新的选择标准。与find()方法中相同的query selectors可用。 |
指定一个空文档{ }
以更新集合中返回的第一个文档。
如果未指定,则默认为空文档。
从 MongoDB 3.6.14(和 3.4.23)开始,如果查询参数不是文档,则操作错误。
| update
|文档|更新文档。
必须仅包含update operators。
| projection
|文档|可选。要返回的字段子集。
要返回返回文档中的所有字段,请省略此参数。
从 MongoDB 3.6.14(和 3.4.23)开始,如果 projection 参数不是文档,则操作错误。
| sort
|文档|可选。指定与filter
匹配的文档的排序 Sequences。
从 MongoDB 3.6.14(和 3.4.23)开始,如果 sort 参数不是文档,则操作错误。
See cursor.sort().|
| maxTimeMS
|数字|可选。指定必须在其内完成操作的时间限制(以毫秒为单位)。如果超出限制,则会引发错误。
| upsert
|布尔值|可选。当true
,findOneAndUpdate()时:
如果没有文档与filter
相匹配,则创建一个新文档。有关更多详细信息,请参见upsert behavior。插入新文档后返回null
,除非returnNewDocument
是true
。
更新与filter
匹配的单个文档。
为避免多次更新,请确保filter
字段为uniquely indexed。
默认为false
。
| returnNewDocument
|布尔值|可选。当true
时,返回更新的文档而不是原始文档。
默认为false
。
| 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 版中的新功能。
Returns: | 返回原始文档,如果返回returnNewDocument: true ,则返回更新的文档。 |
---|
Behavior
findOneAndUpdate()更新集合中与filter
匹配的第一个匹配文档。 sort
参数可用于影响哪个文档被更新。
projection
参数采用以下格式的文档:
{ field1 : < boolean >, field2 : < boolean> ... }
<boolean>
值可以是以下任意值:
1
或true
以包括该字段。即使未在 projection 参数中明确声明_id
字段,该方法也会返回_id
字段。0
或false
以排除该字段。可以在任何字段(包括_id
)上使用。
Examples
更新文件
grades
集合包含类似于以下内容的文档:
{ _id: 6305, name : "A. MacDyver", "assignment" : 5, "points" : 24 },
{ _id: 6308, name : "B. Batlock", "assignment" : 3, "points" : 22 },
{ _id: 6312, name : "M. Tagnum", "assignment" : 5, "points" : 30 },
{ _id: 6319, name : "R. Stiles", "assignment" : 2, "points" : 12 },
{ _id: 6322, name : "A. MacDyver", "assignment" : 2, "points" : 14 },
{ _id: 6234, name : "R. Stiles", "assignment" : 1, "points" : 10 }
以下操作在name : R. Stiles
处找到第一个文档,并将分数增加5
:
db.grades.findOneAndUpdate(
{ "name" : "R. Stiles" },
{ $inc: { "points" : 5 } }
)
该操作返回更新之前的原始文档:
{ _id: 6319, name: "R. Stiles", "assignment" : 2, "points" : 12 }
如果returnNewDocument
为 true,则该操作将返回更新的文档。
排序和更新文档
grades
集合包含类似于以下内容的文档:
{ _id: 6305, name : "A. MacDyver", "assignment" : 5, "points" : 24 },
{ _id: 6308, name : "B. Batlock", "assignment" : 3, "points" : 22 },
{ _id: 6312, name : "M. Tagnum", "assignment" : 5, "points" : 30 },
{ _id: 6319, name : "R. Stiles", "assignment" : 2, "points" : 12 },
{ _id: 6322, name : "A. MacDyver", "assignment" : 2, "points" : 14 },
{ _id: 6234, name : "R. Stiles", "assignment" : 1, "points" : 10 }
以下操作将更新文档name : "A. MacDyver"
。该操作以points
升序对匹配的文档进行排序,以用最少的点更新匹配的文档。
db.grades.findOneAndUpdate(
{ "name" : "A. MacDyver" },
{ $inc : { "points" : 5 } },
{ sort : { "points" : 1 } }
)
该操作返回更新之前的原始文档:
{ _id: 6322, name: "A. MacDyver", "assignment" : 2, "points" : 14 }
投影返回的文档
以下操作使用投影仅在返回的文档中显示_id
,points
和assignment
字段:
db.grades.findOneAndUpdate(
{ "name" : "A. MacDyver" },
{ $inc : { "points" : 5 } },
{ sort : { "points" : 1 }, projection: { "assignment" : 1, "points" : 1 } }
)
该操作仅返回projection
文档中指定的字段和_id
字段的原始文档,因为在projection document中未显式禁止(_id: 0
)。
{ "_id" : 6322, "assignment" : 2, "points" : 14 }
带时间限制更新文档
以下操作将 5ms 的时间限制设置为完成更新:
try {
db.grades.findOneAndUpdate(
{ "name" : "A. MacDyver" },
{ $inc : { "points" : 5 } },
{ sort: { "points" : 1 }, maxTimeMS : 5 };
);
}
catch(e){
print(e);
}
如果操作超过时间限制,则返回:
Error: findAndModifyFailed failed: { "ok" : 0, "errmsg" : "operation exceeded time limit", "code" : 50 }
使用 Upsert 更新文档
如果没有与filter
匹配的内容,以下操作将使用upsert
字段插入更新文档:
try {
db.grades.findOneAndUpdate(
{ "name" : "A.B. Abracus" },
{ $set: { "name" : "A.B. Abracus", "assignment" : 5}, $inc : { "points" : 5 } },
{ sort: { "points" : 1 }, upsert:true, returnNewDocument : true }
);
}
catch (e){
print(e);
}
该操作返回以下内容:
{
"_id" : ObjectId("5789249f1c49e39a8adc479a"),
"name" : "A.B. Abracus",
"assignment" : 5,
"points" : 5
}
如果returnNewDocument
为假,则该操作将返回null
,因为没有原始文档要返回。
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.myColl.findOneAndUpdate(
{ category: "cafe" },
{ $set: { status: "Updated" } },
{ collation: { locale: "fr", strength: 1 } }
);
该操作返回以下文档:
{ "_id" : 1, "category" : "café", "status" : "A" }
为阵列更新操作指定 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
的元素,请在db.collection.findOneAndUpdate方法中将过滤后的位置运算符$[<identifier>]与arrayFilters
选项一起使用:
db.students.findOneAndUpdate(
{ grades: { $gte: 100 } },
{ $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
字段的值,请在db.collection.findOneAndUpdate方法中将过滤后的位置运算符$[<identifier>]与arrayFilters
一起使用:
db.students2.findOneAndUpdate(
{ },
{ $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 }
]
}