MongDB 更新
基本
语法
db.collection.update(query, update, options)
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string>, // Added in MongoDB 4.2
let: <document> // Added in MongoDB 5.0
}
)
-
query:查询条件
-
update:要更新的对象和一些更新操作符
-
字段
操作符 语法 含义 $set { $set: { : , ... } } 用指定的值替换字段的值。 $inc { $inc: { : , : , ... } } 将字段按指定值递增 $unset { $unset: { : , ... } } 删除一个特定的字段。 $rename {$rename: { : , : , ... } } 更新字段的名称 $min { $min: { : , ... } } 仅当指定值小于现有字段值时才更新该字段。如果该字段不存在,则将字段设置为指定的值。 $currentDate { $currentDate: { : , ... } } 将字段的值设置为当前日 期,可以是date,也可以是timestamp。默认类型为Date。 $max { $max: { : , ... } } 仅当指定值大于现有字段值时才更新该字段。如果该字段不存在,则将字段设置为指定的值。 $mul { $mul: { : , ... } } 将字段的值乘以一个数字 $setOnInsert 在upsert过程中,在创建文档时设置字段的值。 对修改现有文档的更新操作没有影响。 -
数组
操作符 含义 $ 标识数组中要更新的元素,而不显式指定元素在数组中的位置。(有时候你根本不知道元素具体位置;见案例篇) $[] 充当占位符,为匹配查询条件的文档更新数组中的所有元素。 $[ ] 充当占位符,为匹配查询条件的文档更新与arrayFilters条件匹配的所有元素。 $addToSet 仅在集合中不存在元素时才将元素添加到数组中。 $push $push可以向已有数组末尾追加元素,要是不存在就创建一个数组。 $pop 删除数组中的数据;1表示从comments数组的末尾删除一条数据,-1表示从comments数组的开头删除一条数据。 $pull 按条件删除数组中的某个元素 $pullAll 按条件删除数组中的全部元素 -
修饰符
操作符 含义 $each 将多个值追加到数组字段; $position 限制数组元素的数量。配合$each使用; $slice 对数组中的元 素排序。配合$each使用; $sort 指定插入元素的位置。配合$each使用。
-
-
options:额外选项
-
upsert:bool,若不存在 query 的记录时,是否插入新的文档
db.books.update(
{ item: "ZZZ135" }, // Query parameter
{ // Replacement document
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
} ,
{ upsert: true } // Options
) -
multi:bool,是否更新所有符合查询条件的记录,默认 false
db.books.update(
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{ multi: true }
) -
writeConcern:写入安全机制,用于控制写入安全的级别。它指定了在写操作完成之前,MongoDB需要接收到的确认数。writeConcern级别越高,写操作的确认就越安全,但也会影响写的性能。
- writeConcern有三种级别,分别是
- 1:表示写操作需要写入主节点的内存中,但不需要确认写操作是否成功。这是默认级别。
- majority:表示写操作需要写入大多数节点的内存中,并且需要确认写操作是否成功。
<number>
:表示写操作需要写入指定数量的节点的内存中,并且需要确认写操作是否成功。
- writeConcern有三种级别,分别是
-
arrayFilters
-
用于更新嵌套数组中满足指定条件的元素。它可以在更新语句中使用,以指定需要更新的嵌套数组元素的条件。
-
arrayFilters 可以包含多个条件,每个条件都是一个对象,用于指定需要更新的数组元素的查询条件。
db.collection.update(
{ <query conditions> },
{ <update operator>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } ] }
)
// <identifier> 用来充当数组字段中与 arrayFilters 中指定的条件匹配的所有元素的占位符,必须以小写字母开头,且只能包含字母数字字符。db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] )
db.students.updateMany(
{ },
{ $set: { "grades.$[element]" : 100 } },
{ arrayFilters: [ { "element": { $gte: 100 } } ] }
)
-
-
返回:WriteResult
- 执行成功时
- nMatched:匹配查询条件的文档数量
- nUpserted:更新插入的文档数量
- nModified:修改的文档数量
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 执行失败时
- 除了成功哪些字段之外,还包含writeConcernError
WriteResult({
"nMatched" : 1,
"nUpserted" : 0,
"nModified" : 1,
"writeConcernError": {
"code" : 64,
"errmsg" : "waiting for replication timed out",
"errInfo" : {
"wtimeout" : true,
"writeConcern" : {
"w" : "majority",
"wtimeout" : 100,
"provenance" : "getLastErrorDefaults"
}
}
})
更新操作符
字段更新操作符
$se
用来修改指定字段的值;如果指定字段不存在,则创建它。
{ $set: { <field1>: <value1>, ... } }
用例
db.products.insertOne(
{
_id: 100,
quantity: 250,
instock: true,
reorder: false,
details: { model: "14QQ", make: "Clothes Corp" },
tags: [ "apparel", "clothing" ],
ratings: [ { by: "Customer007", rating: 4 } ]
}
)
更新普通字段/嵌套字段
db.products.updateOne(
{ _id: 100 },
{ $set:
{
quantity: 500,
details: { model: "2600", make: "Fashionaires" },
tags: [ "coats", "outerwear", "clothing" ],
"details.make": "Kustom Kidz"
}
}
)
更新数组字段(按索引)
db.products.updateOne(
{ _id: 100 },
{ $set:
{
"tags.1": "rain gear",
"ratings.0.rating": 2
}
}
)
如果是要按条件更新的话,就用 arrayFilter 吧
$inc
用来增加已有键的值
{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }
用例
db.products.insertOne(
{
_id: 1,
sku: "abc123",
quantity: 10,
metrics: { orders: 2, ratings: 3.5 }
}
)
db.products.update(
{ sku: "abc123" },
{ $inc: { quantity: -2, "metrics.orders": 1 } }
)
$rename
用于更新字段的名称,新字段的名字不能与已有的字段名字重名;如果要修改嵌入文档名称使用 .
db.students.update({}, { $rename: { "nmae": "name" } }, { multi: true })
// or
db.students.updateMany({}, { $rename: { "nmae": "name" } })
$unset
用于删除特定字段
{ $unset: { <field1>: "", ... } }
删除 sku=unknown
中的 quantity
和 instock
字段
db.products.update(
{ sku: "unknown" },
{ $unset: { quantity: "", instock: "" } }
)
数组更新操作符
添加字段
$addToSet
如果元素不存在数组中则添加,如果存在则不添加;可使用 $each
修饰来添加多个元素。
{ $addToSet: { <field1>: <value1>, ... } }
用例
db.inventory.insertOne(
{ _id: 1, item: "polarizing_filter", tags: [ "electronics", "camera" ] })
添加单个元素
db.inventory.updateOne(
{ _id: 1 },
{ $addToSet: { tags: "accessories" } }
)
用 $each
添加多个元素
db.inventory.updateOne(
{ _id: 2 },
{ $addToSet: { tags: { $each: [ "camera", "electronics", "accessories" ] } } }
)
$push
添加指定值到数组中,可重复。可修饰符有:
$each
: 将多个值追加到数组字段$slice
: 限制数组元素的数量。配合$each
使用$sort
:对数组中的元素排序。配合$each
使用$position
:指定插入元素的位置。配合$each
使用。若为空,则默认添加到末尾。
{ $push: { <field1>: <value1>, ... } }
用例
db.students.insertOne( { _id: 1, scores: [ 44, 78, 38, 80 ] } )
db.students.updateOne(
{ _id: 1 },
{ $push: { scores: 89 } }
)
添加多个值
db.students.updateOne(
{ name: "joe" },
{ $push: { scores: { $each: [ 90, 92, 85 ] } } }
)
使用多个修饰符。用例
db.students.insertOne(
{
"_id" : 5,
"quizzes" : [
{ "wk": 1, "score" : 10 },
{ "wk": 2, "score" : 8 },
{ "wk": 3, "score" : 5 },
{ "wk": 4, "score" : 6 }
]
}
)
下面的语句首先添加 { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 }
到 quizzes
中,然后根据 score
进行降序排序,最后保留前三个元素
db.students.updateOne(
{ _id: 5 },
{
$push: {
quizzes: {
$each: [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ],
$sort: { score: -1 },
$slice: 3
}
}
}
)
修改字段
$
标识数组中要更新的元素,而不显式指定元素在数组中的位置。
{ "<array>.$" : value }
更新数组中的值
db.students.insertMany( [
{ "_id" : 1, "grades" : [ 85, 80, 80 ] },
{ "_id" : 2, "grades" : [ 88, 90, 92 ] },
{ "_id" : 3, "grades" : [ 85, 100, 90 ] }
] )
如果我们要更新 id=1
的 grades
中第一个 80 为 82。此时并不知道 grades 数组中 80 的具体位置:
db.students.updateOne(
{ _id: 1,grades: 80 },
{ $set: { "grades.$" : 82 } }
)
更新数组中的文档
db.students.insert({
_id: 4,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 85, std: 8 }
]
})
修改该文档 grades
中 grade
为 85 的 std
为 6
db.students.updateOne(
{ _id: 4, "grades.grade": 85 },
{ $set: { "grades.$.std" : 6 } }
)
使用多个数组匹配更新
db.students_deans_list.insertMany( [
{
_id: 8,
activity_ids: [ 1, 2 ],
grades: [ 90, 95 ],
deans_list: [ 2021, 2020 ]
}
] )
前几个字段用于查询条件查询,deans_list
作为 $set
占位符使用
db.students_deans_list.updateOne(
{ activity_ids: 1, grades: 95, deans_list: 2021 },
{ $set: { "deans_list.$": 2022 } }
)
$[]
{ <update operator>: { "<array>.$[]" : value } }
用例
db.students.insertMany( [
{ "_id" : 1, "grades" : [ 85, 80, 80 ] },
{ "_id" : 2, "grades" : [ 88, 90, 92 ] },
{ "_id" : 3, "grades" : [ 85, 100, 90 ] }
] )
下面将所有数组 grades
增加 10
db.students.updateMany(
{ },
{ $inc: { "grades.$[]": 10 } },
)
$[<identifier>]
给数组筛选提供个过滤器,配合 option 中的 arrayFilters 使用,如果是嵌套文档还是使用 .
db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] )
更新所有grades数组大于等于100的记录,将其设置为100
db.students.updateMany(
{ },
{ $set: { "grades.$[element]" : 100 } },
{ arrayFilters: [ { "element": { $gte: 100 } } ] }
)
删除字段
$pop
删除数组中第一个或者最后一个元素;-1
删除第一个元素,1
表示删除最后一个元素
{ $pop: { <field>: <-1 | 1>, ... } }
例子
db.students.insertOne( { _id: 1, scores: [ 8, 9, 10 ] } )
以下语句删除students中scores中第一个元素
db.students.updateOne( { _id: 1 }, { $pop: { scores: -1 } } )
$pull
条件匹配删除值
从现有数组中删除一个或多个与指定条件匹配的值的所有实例。
{ $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }
用例
db.stores.insertMany( [
{
_id: 1,
fruits: [ "apples", "pears", "oranges", "grapes", "bananas" ],
vegetables: [ "carrots", "celery", "squash", "carrots" ]
},
{
_id: 2,
fruits: [ "plums", "kiwis", "oranges", "bananas", "apples" ],
vegetables: [ "broccoli", "zucchini", "carrots", "onions" ]
}
] )
下面的操作将移除:
- 所有文档
fruits
数组中"apples"
和"oranges"
- 所有文档
vegetables
数组中"carrots"
db.stores.updateMany(
{ },
{ $pull: { fruits: { $in: [ "apples", "oranges" ] }, vegetables: "carrots" } }
)
删除所有匹配指定 $pull 条件的项
db.profiles.insertOne( { _id: 1, votes: [ 3, 5, 6, 7, 7, 8 ] } )
删除所有 votes
大于等于6的元素
db.profiles.updateOne( { _id: 1 }, { $pull: { votes: { $gte: 6 } } } )
$pullAll
精确匹配删除所有值
从数组中删除所有指定值;只能精确匹配,无法条件匹配
{ $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }
用例
db.survey.insertOne( { _id: 1, scores: [ 0, 2, 5, 5, 1, 0 ] } )
下面的例子将删除scores
中所有0
,5
的元素
db.survey.updateOne( { _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } } )
等价于:
db.survey.updateOne( { _id: 1 }, { $pull: { scores: {$in:[ 0, 5 ]} } } )