MongoDB之update
Posted JokerJason
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB之update相关的知识,希望对你有一定的参考价值。
Update操作只作用于集合中存在的文档。MongoDB提供了如下方法来更新集合中的文档:
- db.collection.update()
- db.collection.updateOne() New in version 3.2
- db.collection.updateMany() New in version 3.2
- db.collection.replaceOne() New in version 3.
你可以通过指定criteria或者filter来指定你想更新的文档:
update函数执行数据更新操作,该函数接受3个主要参数:criteria,action,options:
- 参数criteria用于指定一个查询,查询选择将要更新的目标记录。
- 参数action用于指定更新信息,也可以使用操作符来完成。
- 参数options用于指定更新文档时的选项,可选值包括:upsert和multi。upsert可以指定如果数据存在就更新,不存在就创建数据;multi选项指定是否应该更新所有匹配的文档,或者只更新第一个文档(默认行为)。
为了更好的演示,插入数据:
db.users.insertMany(
[
{
_id: 1,
name: "sue",
age: 19,
type: 1,
status: "P",
favorites: { artist: "Picasso", food: "pizza" },
finished: [ 17, 3 ],
badges: [ "blue", "black" ],
points: [
{ points: 85, bonus: 20 },
{ points: 85, bonus: 10 }
]
},
{
_id: 2,
name: "bob",
age: 42,
type: 1,
status: "A",
favorites: { artist: "Miro", food: "meringue" },
finished: [ 11, 25 ],
badges: [ "green" ],
points: [
{ points: 85, bonus: 20 },
{ points: 64, bonus: 12 }
]
},
{
_id: 3,
name: "ahn",
age: 22,
type: 2,
status: "A",
favorites: { artist: "Cassatt", food: "cake" },
finished: [ 6 ],
badges: [ "blue", "Picasso" ],
points: [
{ points: 81, bonus: 8 },
{ points: 55, bonus: 20 }
]
},
{
_id: 4,
name: "xi",
age: 34,
type: 2,
status: "D",
favorites: { artist: "Chagall", food: "chocolate" },
finished: [ 5, 11 ],
badges: [ "Picasso", "black" ],
points: [
{ points: 53, bonus: 15 },
{ points: 51, bonus: 15 }
]
},
{
_id: 5,
name: "xyz",
age: 23,
type: 2,
status: "D",
favorites: { artist: "Noguchi", food: "nougat" },
finished: [ 14, 6 ],
badges: [ "orange" ],
points: [
{ points: 71, bonus: 20 }
]
},
{
_id: 6,
name: "abc",
age: 43,
type: 1,
status: "A",
favorites: { food: "pizza", artist: "Picasso" },
finished: [ 18, 12 ],
badges: [ "black", "blue" ],
points: [
{ points: 78, bonus: 8 },
{ points: 57, bonus: 7 }
]
}
]
)
1. 字段更新操作符
1.1 覆盖更新
下面的例子使用update()函数执行更新数据操作,不包含操作符:
> db.users.find({"name":"xyz"});
{ "_id" : 5, "name" : "xyz", "age" : 23, "type" : 2, "status" : "D", "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 14, 6 ], "badges" : [ "orange" ], "points" : [ { "points" : 71, "bonus" : 20 } ] }
>
修改之后:
> db.users.update({"name":"xyz"}, {name : "xyz", age:25, school : "xidian", type:1, favorites: {artist : "Noguchi", food : "nougat"}, finished : [4, 5] }, {upsert:true});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
>
>
> db.users.find({"name":"xyz"});
{ "_id" : 5, "name" : "xyz", "age" : 25, "school" : "xidian", "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
该例覆写了集合中的文档,并保存更新后的值。
备注
任何忽略的字段都被移除(文档被覆盖)
1.2 upsert
upsert可以指定如果数据存在就更新,不存在就创建数据。
> db.users.find({"name":"yoona"});
>
> db.users.update({"name":"yoona"}, {name : "yoona", age:25, "school" : "xidian", type:1, favorites: {artist : "Noguchi", food : "nougat"}, finished : [4, 5] }, {upsert:false});
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
更新操作之前我们没有查询到yoona的任何信息,然后我们对其进行更新操作,并且upsert设置为false,表示如果更新的数据不存在,不走任何操作。更新之后,我们再次查询一下:
> db.users.find({"name":"yoona"});
>
再次查询还是没有找到相应数据。我们设置upsert为true,表示如果数据存在则更新,如果不存在则创建该数据:
> db.users.update({"name":"yoona"}, {name : "yoona", age:25, "school" : "xidian", type:1, favorites: {artist : "Noguchi", food : "nougat"}, finished : [4, 5] }, {upsert:true});
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("57c3ad26d2cc0133a95bc583")
})
>
> db.users.find({"name":"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 25, "school" : "xidian", "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
1.3 $inc 增加值
操作符$inc可以为指定的键执行(原子)更新操作,如果字段存在,就将该值增加给定的增量,如果该字段不存在,就创建该字段。
> db.users.update({"name":"yoona"}, {$inc:{age:2}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
>
> db.users.find({name:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 27, "school" : "xidian", "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
上面例子中将yoona用户的年龄增加两岁。
1.4 $set 设置字段值
可以使用$set操作符将某个字段设置为指定值。
> db.users.find({name:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 27, "school" : "xidian", "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
>
> db.users.update({"name":"yoona"}, {$set:{school:"Massachusetts Institute of Technology"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
> db.users.find({name:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 27, "school" : "Massachusetts Institute of Technology", "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
>
上面例子将yoona用户的学校改为麻省理工学院。
1.5 $unset删除指定字段
> db.users.find({name:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 27, "school" : "Massachusetts Institute of Technology", "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
>
> db.users.update({"name":"yoona"}, {$unset:{school:"Massachusetts Institute of Technology"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
> db.users.find({name:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 27, "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
上面例子将yoona用户的学校删除。
1.6 $rename 重命名字段名称
格式:
{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }
新字段名称必须不同与已经存在的字段名称
> db.users.find({name:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "name" : "yoona", "age" : 27, "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ] }
>
> db.users.update({"name":"yoona"}, {$rename: {name:"userName", age:"userAge"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
查询:
> db.users.find({name:"yoona"});
> db.users.find({userName:"yoona"});
{ "_id" : ObjectId("57c3ad26d2cc0133a95bc583"), "type" : 1, "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 4, 5 ], "userName" : "yoona", "userAge" : 27 }
>
上面例子中使用$rename将name改为userName,将age改为userAge。
1.7 $min $max数值比较
如果给定值(value1)小于字段的当前值,则更新字段值为给定值。$min运算符可以可以比较不同类型的数字。
格式:
{ $min: { <field1>: <value1>, ... } }
为了演示,添加如下数据:
> db.score.save({_id:1, highScore:90, lowScore: 50});
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 1 })
>
>
> db.score.find();
{ "_id" : 1, "highScore" : 90, "lowScore" : 50 }
给定值与字段当前值进行比较,给定值10小于字段的当前值50,所以更新字段当前值为给定值10:
> db.score.update({_id:1}, {$min : {lowScore : 10}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
> db.score.find();
{ "_id" : 1, "highScore" : 90, "lowScore" : 10 }
给定值40大于字段当前值10,不做任何变化:
> db.score.update({_id:1}, {$min : {lowScore : 40}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
>
> db.score.find();
{ "_id" : 1, "highScore" : 90, "lowScore" : 10 }
>
1.8 $setOnInsert
如果更新操作设置upsert:true,执行insert操作时,$setOnInsert会给给定字段赋值给定值。如果更新操作不会导致插入数据,$setOnInsert不会有任何作用。
格式:
db.collection.update(
<query>,
{ $setOnInsert: { <field1>: <value1>, ... } },
{ upsert: true }
)
举例:
假设集合products中没有任何文档,进行如下操作:
> db.products.find();
>
> db.products.update({_d:1}, {$set : {item : "apple"}, $setOnInsert : {defaultQty : 100}} , {upsert : true});
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("57c43a0ebd7a19639b912212")
})
>
> db.products.find();
{ "_id" : ObjectId("57c43a0ebd7a19639b912212"), "_d" : 1, "item" : "apple", "defaultQty" : 100 }
由于集合中没有任何文档,在对其字段item进行更新时,由于item字段不存在,执行insert操作时,触发setOnInsert操作符,给defaultQty字段赋值为100。
1.9 $currentDate
$curentDate设置字段值为当前日期,可以设置Date类型或者timestamp类型。
格式:
{ $currentDate: { <field1>: <typeSpecification1>, ... } }
为了演示,添加如下数据:
db.student.save({_id:1, name: "yoona", age: 24, college: "计算机学院"});
下面添加一个日期类型的"birthday"字段:
db.student.update({_id:1}, {$currentDate: {birthday: {$type: "date"}}});
最后输出结果:
{
"_id" : 1.0,
"name" : "yoona",
"age" : 24.0,
"college" : "计算机学院",
"birthday" : ISODate("2016-08-30T02:29:24.425Z")
}
2. 数组操作符
2.1 $push 在指定字段中添加某个值
通过$push操作符可以在指定字段中添加某个值。如果该字段是个数组,那么该值将被添加到数组中。如果该字段尚不存在,那么该字段的值将被设置为数组。如果该字段存在,但不是数组,那么将会抛出异常。如果给定的值是个数组,那么该数组被看做是一个元素,添加给定字段中(If the value is an array, $push appends the whole array as a single element)。
格式:
{ $push: { <field1>: <value1>, ... } }
举例:
添加一个分数到成绩数组中:
db.student.update({_id:1}, {$push : {scores: 91}});
输出结果:
{
"_id" : 1.0,
"name" : "yoona",
"age" : 24.0,
"college" : "计算机学院",
"birthday" : ISODate("2016-08-30T02:29:24.425Z"),
"scores" : [
89.0,
91.0
]
}
2.2 $push $each 指定数组中的多个值
格式:
{ $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }
使用$push操作符可以将值添加到指定数组中,扩展指定元素中存储的数据。如果希望在给定的数组中添加多个值,可以使用可选的$each修改操作符。
db.student.update(
{ _id: 1 },
{ $push: { scores: { $each: [ 90, 92, 85 ] } } }
)
输出结果:
{
"_id" : 1.0,
"name" : "yoona",
"age" : 24.0,
"college" : "计算机学院",
"birthday" : ISODate("2016-08-30T02:29:24.425Z"),
"scores" : [
89.0,
91.0,
90.0,
92.0,
85.0
]
}
在使用$each是还可以使用$slice修改操作符,通过这种方式可以限制$push操作符中数组内元素的数量。$slice可以是正数,负数或0。正数将保证数组中的前n个元素会被保留,使用负数将保证数组中的最后n个元素会被保留,而使用0则表示清空数组。注意:操作符$slice必须是$push操作中的第一个修改操作符。
使用0则表示清空数组:
db.student.update(
{ _id: 1 },
{ $push: { scores: { $each: [ 70, 78], $slice: 0 } } }
)
输出结果:
{
"_id" : 1.0,
"name" : "yoona",
"age" : 24.0,
"college" : "计算机学院",
"birthday" : ISODate("2016-08-30T02:29:24.425Z"),
"scores" : []
}
正数将保证数组中的前n个元素会被保留
db.student.update(
{ _id: 1 },
{ $push: { scores: { $each: [ 70, 78, 90], $slice: 2 } } }
)
输出结果:
{
"_id" : 1.0,
"name" : "yoona",
"age" : 24.0,
"college" : "计算机学院",
"birthday" : ISODate("2016-08-30T02:29:24.425Z"),
"scores" : [
70.0,
78.0
]
}
使用负数将保证数组中的最后n个元素会被保留
db.student.update(
{ _id: 1 },
{ $push: { scores: { $each: [ 89, 56 ], $slice: -3 } } }
)
输出结果:
{
"_id" : 1.0,
"name" : "yoona",
"age" : 24.0,
"college" : "计算机学院",
"birthday" : ISODate("2016-08-30T02:29:24.425Z"),
"scores" : [
78.0,
89.0,
56.0
]
}
操作符$each和$slice操作符保证不仅新值会被添加到数组中,还能保证吧数组的大小限制为指定值。
2.3 $sort 排序
如何将代码片段存储在 mongodb 中?