On this page
db.collection.update()
在本页面
Definition
db.collection.
update
(* query , update , options *)- 修改现有文档或集合中的文档。该方法可以修改一个或多个现有文档的特定字段或完全替换一个现有文档,具体取决于update parameter。
默认情况下,update()方法更新一个**文档。设置Multi Parameter以更新所有符合查询条件的文档。
update()方法具有以下形式:
在版本 3.6 中更改。
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
update()方法采用以下参数:
Parameter | Type | Description |
---|---|---|
query |
document | 更新的选择标准。与find()方法中相同的query selectors可用。 |
在版本 3.0 中进行了更改:当您使用upsert: true
执行update()并且查询与现有文档不匹配时,如果查询使用dot notation在_id
字段中指定了条件,则 MongoDB 将拒绝插入新文档。
有关更多信息和示例,请参见upsert:true,带有虚线_id 查询。
| update
| document |要应用的修改。有关详细信息,请参见Update Parameter。
| upsert
|布尔值|可选。如果设置为true
,则在没有文档符合查询条件时创建一个新文档。 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |的缺省值false
不会在没有匹配时插入新文档。
| multi
|布尔值|可选。如果设置为true
,则更新满足query
标准的多个文档。如果设置为false
,则更新一个文档。默认值为false
。有关更多信息,请参见Multi Parameter。
| writeConcern
|文档|可选。表示write concern的文档。省略使用默认的写关注。参见Write Concern。
2.6 版中的新功能。
| 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: | 包含操作状态的WriteResult对象。 |
---|
Behavior
Write Concern
在 2.6 版中进行了更改。
update()方法使用update命令,该命令使用默认的write concern。要指定其他写关注点,请在 options 参数中包含writeConcern
选项。有关示例,请参见覆盖默认写问题。
Update Parameter
update()方法可以修改现有文档中的特定字段,也可以完全替换现有文档。
更新特定字段
如果<update>
文档包含update operator修饰符,例如使用$set修饰符的修饰符,则:
<update>
文档必须包含* only * update operator表达式。update()方法仅更新文档中的相应字段。
要整体更新嵌入式文档或数组,请为该字段指定替换值。要更新嵌入式文档或数组中的特定字段,请使用dot notation指定该字段。
完全替换文档
如果<update>
文档仅包含* field:value
个表达式,则:
Upsert Option
Upsert Behavior
如果upsert
是true
并且没有文档符合查询条件,则update()插入***文档。更新使用以下任一方法创建新文档:
如果
<update>
参数是替换文档(即仅包含字段和值对),则<update>
参数的字段和值。如果<query>
或<update>
文档均未指定_id
字段,则 MongoDB 将_id
字段添加为ObjectId值。如果
<update>
参数包含update operator表达式,则<query>
和<update>
参数的字段和值。此更新通过<query>
参数中的 equals 子句创建基础文档,然后应用<update>
参数中的更新表达式。<query>
中的Comparison操作将不包含在新文档中。
如果upsert
为true
并且存在符合查询条件的文档,则update()执行更新。
See also
使用唯一索引
Warning
为避免多次插入同一文档,如果query
字段已唯一索引,则仅使用upsert: true
。
给定一个名为people
的集合,其中没有文档具有name
字段的值Andy
。考虑多个 Client 端同时使用upsert: true
发出以下* update *的情况:
db.people.update(
{ name: "Andy" },
{
name: "Andy",
rating: 1,
score: 1
},
{ upsert: true }
)
如果所有update()操作都在任何 Client 端成功插入数据之前完成query
部分,并且name
字段上没有唯一索引,则每个更新操作都可能导致插入。
为了防止 MongoDB 多次插入同一文档,请在name
字段上创建unique index。使用唯一索引,如果多个应用程序使用upsert: true
发出相同的更新,正好一个 update()将成功插入新文档。
其余操作将是:
更新新插入的文档,或
当他们尝试插入重复项时失败。
如果操作由于重复的索引键错误而失败,则应用程序可以重试该操作,该操作将作为更新操作成功。
upsert:true,带有点_id 查询
当您使用upsert: true
执行update()并且查询不匹配现有文档时,如果查询使用dot notation在_id
字段中指定条件,则 MongoDB 将拒绝插入新文档。
此限制可确保正确定义_id
文档中嵌入的字段的 Sequences,并且不与查询中指定的 Sequences 绑定
如果您尝试以这种方式插入文档,MongoDB 将引发错误。
例如,考虑以下更新操作。由于更新操作指定upsert:true
且查询使用点表示法在_id
字段上指定条件,因此在构造要插入的文档时,更新将导致错误。
db.collection.update( { "_id.name": "Robert Frost", "_id.uid": 0 },
{ "categories": ["poet", "playwright"] },
{ upsert: true } )
Multi Parameter
如果multi
设置为true
,则update()方法更新所有符合<query>
标准的文档。 multi
更新操作可以与其他操作(读和/或写操作)交织。
如果<update>文档仅包含field:value
个表达式,则update() 不能更新多个文档。
有关示例,请参见更新多个文件。
Sharded Collections
指定justOne
选项的分片集合的所有update()操作必须在查询规范中包含shard key 或 _id
字段。在分片集合中指定justOne
的update()操作不包含shard key或_id
字段都将返回错误。
Examples
更新特定字段
要更新文档中的特定字段,请在<update>
参数中使用update operators。
例如,给定一个具有以下文档的books
集合:
{
_id: 1,
item: "TBD",
stock: 0,
info: { publisher: "1111", pages: 430 },
tags: [ "technology", "computer" ],
ratings: [ { by: "ijk", rating: 4 }, { by: "lmn", rating: 5 } ],
reorder: false
}
以下操作使用:
db.books.update(
{ _id: 1 },
{
$inc: { stock: 5 },
$set: {
item: "ABC123",
"info.publisher": "2222",
tags: [ "software" ],
"ratings.1": { by: "xyz", rating: 3 }
}
}
)
更新后的文档如下:
{
"_id" : 1,
"item" : "ABC123",
"stock" : 5,
"info" : { "publisher" : "2222", "pages" : 430 },
"tags" : [ "software" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "xyz", "rating" : 3 } ],
"reorder" : false
}
See also
Remove Fields
以下操作使用$unset运算符删除tags
字段:
db.books.update( { _id: 1 }, { $unset: { tags: 1 } } )
See also
替换所有字段
鉴于books
集合中的以下文档:
{
_id: 2,
item: "XYZ123",
stock: 15,
info: { publisher: "5555", pages: 150 },
tags: [ ],
ratings: [ { by: "xyz", rating: 5, comment: "ratings and reorder will go away after update"} ],
reorder: false
}
以下操作将传递仅包含字段和值对的<update>
文档。 <update>
文档完全替换了原始文档,但_id
字段除外。
db.books.update(
{ item: "XYZ123" },
{
item: "XYZ123",
stock: 10,
info: { publisher: "2255", pages: 150 },
tags: [ "baking", "cooking" ]
}
)
更新的文档仅包含替换文档中的字段和_id
字段。也就是说,由于更新文档中没有字段ratings
和reorder
,因此它们不在替换文档中。
{
"_id" : 2,
"item" : "XYZ123",
"stock" : 10,
"info" : { "publisher" : "2255", "pages" : 150 },
"tags" : [ "baking", "cooking" ]
}
如果不存在匹配项,则插入新文档
以下更新将upsert选项设置为true
,以便在没有文档与<query>
参数匹配的情况下update()在books
集合中创建一个新文档:
db.books.update(
{ item: "ZZZ135" },
{
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
},
{ upsert: true }
)
如果没有文档与<query>
参数匹配,则更新操作会插入一个文档,其中仅 <update>
文档的字段和值以及_id
字段的新唯一ObjectId
:
{
"_id" : ObjectId("542310906694ce357ad2a1a9"),
"item" : "ZZZ135",
"stock" : 5,
"tags" : [ "database" ]
}
有关upsert
选项和插入的文档Upsert Option的更多信息。
更新多个文档
要更新多个文档,请将multi
选项设置为true
。例如,以下操作将更新stock
小于或等于10
的所有文档:
db.books.update(
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{ multi: true }
)
如果匹配的文档中不存在reorder
字段,则$set运算符将添加具有指定值的字段。有关更多信息,请参见$set。
覆盖默认写问题
对副本集的以下操作指定"w: majority"
的write concern和wtimeout
的 5000 毫秒,从而使该方法在写入传播到大多数有表决权的副本集成员之后返回,或者该方法在 5 秒后超时。
在版本 3.0 中进行了更改:在以前的版本中,majority
引用了副本集的所有成员的大多数,而不是多数投票成员。
db.books.update(
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{
multi: true,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)
组合 upsert 和多个选项
给定一个books
集合,其中包含以下文档:
{
_id: 5,
item: "EFG222",
stock: 18,
info: { publisher: "0000", pages: 70 },
reorder: true
}
{
_id: 6,
item: "EFG222",
stock: 15,
info: { publisher: "1111", pages: 72 },
reorder: true
}
以下操作同时指定了multi
选项和upsert
选项。如果存在匹配的文档,则该操作将更新所有匹配的文档。如果不存在匹配的文档,则该操作将插入一个新文档。
db.books.update(
{ item: "EFG222" },
{ $set: { reorder: false, tags: [ "literature", "translated" ] } },
{ upsert: true, multi: true }
)
该操作将更新所有匹配的文档,并产生以下结果:
{
"_id" : 5,
"item" : "EFG222",
"stock" : 18,
"info" : { "publisher" : "0000", "pages" : 70 },
"reorder" : false,
"tags" : [ "literature", "translated" ]
}
{
"_id" : 6,
"item" : "EFG222",
"stock" : 15,
"info" : { "publisher" : "1111", "pages" : 72 },
"reorder" : false,
"tags" : [ "literature", "translated" ]
}
如果集合没有匹配的文档,则该操作将使用<query>
和<update>
规范中的字段插入文档:
{
"_id" : ObjectId("5423200e6694ce357ad2a1ac"),
"item" : "EFG222",
"reorder" : false,
"tags" : [ "literature", "translated" ]
}
有关upsert
选项和插入的文档Upsert Option的更多信息。
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.update(
{ category: "cafe" },
{ $set: { status: "Updated" } },
{ collation: { locale: "fr", strength: 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.students.update(
{ grades: { $gte: 100 } },
{ $set: { "grades.$[element]" : 100 } },
{
multi: true,
arrayFilters: [ { "element": { $gte: 100 } } ]
}
)
操作后,集合包含以下文档:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 100, 100 ] }
更新一系列文档的特定元素
考虑包含以下文档的集合students2
:
{
"_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
字段的值,请使用过滤后的位置运算符$[<identifier>]和arrayFilters
:
db.students2.update(
{ },
{ $set: { "grades.$[elem].mean" : 100 } },
{
multi: true,
arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
}
)
操作后,集合具有以下文档:
{
"_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" : 100, "std" : 6 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}
WriteResult
在 2.6 版中进行了更改。
Successful Results
update()方法返回包含操作状态的WriteResult对象。成功后,WriteResult对象包含符合查询条件的文档数,更新插入的文档数以及修改的文档数:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
写关注错误
如果update()方法遇到写关注错误,则结果包括WriteResult.writeConcernError字段:
WriteResult({
"nMatched" : 1,
"nUpserted" : 0,
"nModified" : 1,
"writeConcernError" : {
"code" : 64,
"errmsg" : "waiting for replication timed out at shard-a"
}
})
See also
与写入问题无关的错误
如果update()方法遇到非写关注错误,则结果包括WriteResult.writeError字段:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 7,
"errmsg" : "could not contact primary for replica set shard-a"
}
})