db.collection.findOneAndUpdate()

在本页面

Definition

根据filtersort标准更新单个文档。

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 |布尔值|可选。当truefindOneAndUpdate()时:
如果没有文档与filter相匹配,则创建一个新文档。有关更多详细信息,请参见upsert behavior。插入新文档后返回null,除非returnNewDocumenttrue
更新与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>值可以是以下任意值:

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 }

投影返回的文档

以下操作使用投影仅在返回的文档中显示_idpointsassignment字段:

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 }
   ]
}
首页