一、更新整篇文档
1.1 更新整篇文档
db.<collection>.update( <query>,<update>,<options>)
参数说明:
<query>文档定义了 更新操作 时 筛选文档的条件(对哪些文档进行更新)
<update>提供了更新的内容
<options>声明了一些更新操作的参数
注意:
如果<update>文档不包含任何 更新操作符(具体看1.2),db.collection.update()将会使用<update>文档 直接替换 集合中符合<query>文档筛选条件的文档(看例子1)
文档主键_id是不可以更改的,如果在<update>文档中包含_id字段,则_id值一定要和被更新的文档_id值保持一致(看例子2)
在使用<update>文档替换整篇被更新文档时,只有 第一篇 符合<query>文档筛选条件的文档会被更新,即只能应用在单一文档上(看列子3)
- 例子1: 再来看一看alice的银行账户文档
> db.accounts.find( { name:"alice"})
{ "_id" : "account1", "name" : "alice", "balance" : 100 }
- 例子1:将alice的账户余额改为123
> db.accounts.update( { name:"alice"},{name:"alice",balance:123})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 有多少篇符合查询 # 有多少篇真的被修改了
- 例子1:查看更新之后的银行账户文档
> db.accounts.find( { name:"alice"})
{ "_id" : "account1", "name" : "alice", "balance" : 123 }
- 例子2:主键_id不可以更改,要写也要和被更改的文档_id一致(不推荐加_id)
> db.accounts.update( { name:"alice"},{ _id:"account1",name:"alice",balance:100})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子3:查看账户余额在 20 到 80 之间的账户文档
> db.accounts.find( { balance:{$gt:20,$lt:80}})
{ "_id" : ObjectId("63bd080fef3b5e682a151ff8"), "name" : "bob", "balance" : 50 }
{ "_id" : ObjectId("63c50ac9238aa380d817fa40"), "name" : "bob", "balance" : 50 }
- 例子3:更新账户余额在 20 到 80 之间的账户文档
> db.accounts.update( { balance: { $gt: 20, $lt:80 }}, {name:"bill", balance:50, gender: "M"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子3:再次查看,发现只有第一篇被更改了
> db.accounts.find( { balance:{$gt:20,$lt:80}})
{ "_id" : ObjectId("63bd080fef3b5e682a151ff8"), "name" : "bill", "balance" : 50, "gender" : "M" }
{ "_id" : ObjectId("63c50ac9238aa380d817fa40"), "name" : "bob", "balance" : 50 }
1.2 更新特定字段
db.collection.update()
db.<collection>.upate( <query>,<update>,<options>)
如果<update>文档只包含更新操作符,db.collection.upadte()将会使用<update>文档更新集合中符合<query>文档筛选条件的文档中的特定字段
更新操作符:
$set 更新或新增字段 { $set: { <field1>: <value1>, ...}}
$unset 删除字段 { $unset: { <field1>: "", ... } }
$rename 重命名字段 { $rename: { <field1>:<newName1>, <field2>:<newName2>, ...}}
$inc 加减字段值 { $inc: { <field1>: <amount1>,...}}
$mul 相乘字段值 { $mul: { <field1>: <number1>, ...}}
$min 比较减小字段值 { $min: { <field1>: <value1>,...}}
$max 比较增大字段值 { $max: { <field1>: <value1>,...}}
1.2.1 更新或新增字段--更新操作符
- 例子4:查看jack的银行账户文档
> db.accounts.find( { name:"jack" } ).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"balance" : 2000,
"contact" : [
"11111111",
"Alabama",
"US"
]
}
- 例子4:更新jack的银行账户余额和开户信息
db.accounts.update(
{ name: "jack" },
{ $set:
{
balance:3000,
info: {
dateOpened: new Date("2016-06-18T16:00:00Z"),
branch: "branch1"
}
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子4:再次查看jack账户
> db.accounts.find( { name:"jack" } ).pretty(){
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"balance" : 3000,
"contact" : [
"11111111",
"Alabama",
"US"
],
"info" : {
"dateOpened" : ISODate("2016-06-18T16:00:00Z"),
"branch" : "branch1"
}
}
1.2.2 更新或新增内嵌文档的字段
- 例子5:更新jack的银行账户的开户时间
db.accounts.update(
{ name: "jack"},
{ $set:
{ "info.dateOpened":new Date("2017-01-01T16:00:00Z")}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子5:再次查看jack的银行账户文档
> db.accounts.find( { name:"jack" } ).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"balance" : 3000,
"contact" : [
"11111111",
"Alabama",
"US"
],
"info" : {
"dateOpened" : ISODate("2017-01-01T16:00:00Z"),
"branch" : "branch1"
}
}
1.2.3 更新或新增数组内的字段
- 例子6:更新jack的联系电话
db.accounts.update(
{ name: "jack" },
{ $set:
{
"contact.0": "66666666"
}
}
)
- 例子6: 再次查看jack的银行账户文档
> db.accounts.find( { name:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"balance" : 3000,
"contact" : [
"66666666",
"Alabama",
"US"
],
"info" : {
"dateOpened" : ISODate("2017-01-01T16:00:00Z"),
"branch" : "branch1"
}
}
-例子6:添加jack新的联系方式(在第四个元素位置)
db.accounts.update(
{ name: "jack"},
{ $set:
{
"contact.3":"new contact"
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子6: 再次查看jack的账户
> db.accounts.find( { name:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"balance" : 3000,
"contact" : [
"66666666",
"Alabama",
"US",
"new contact"
],
"info" : {
"dateOpened" : ISODate("2017-01-01T16:00:00Z"),
"branch" : "branch1"
}
}
- 例子6:再次给jack添加联系方式(在第7个元素位置)
db.accounts.update(
{ name: "jack"},
{ $set:
{
"contact.6":"another new contact"
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子6: 再次查看jack账户信息
> db.accounts.find( { name:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"balance" : 3000,
"contact" : [
"66666666",
"Alabama",
"US",
"new contact",
null,
null,
"another new contact"
],
"info" : {
"dateOpened" : ISODate("2017-01-01T16:00:00Z"),
"branch" : "branch1"
}
}
# 如果向现有数组字段范围以外的位置添加新值,数组字段的长度会扩大,未被赋值的数组成员将被设置为 null
1.2.4 删除字段
- 例子7: 删除jack的银行账户 余额 和 开户地点(内嵌文档)
db.accounts.update(
{ name: "jack" },
{ $unset:
{
balance:"",
"info.branch": "",
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子7:再次查看jack账户信息
> db.accounts.find( { name:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"contact" : [
"66666666",
"Alabama",
"US",
"new contact",
null,
null,
"another new contact"
],
"info" : {
"dateOpened" : ISODate("2017-01-01T16:00:00Z")
}
}
$unset命令中的赋值操作对结果没有任何影响,所以一般直接用空值"",看下面测试
- 例子7: 删除jack的银行开户时间
db.accounts.update(
{ name: "jack" },
{ $unset:
{
"info.dateOpened": "this can be any value"
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子7:再次查看jack的账户信息
> db.accounts.find( { name:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"contact" : [
"66666666",
"Alabama",
"US",
"new contact",
null,
null,
"another new contact"
],
"info" : {
}
}
如果 $unset命令中的字段根本不存在,那么文档内容将保持不变(看下面例子)
- 例子8:删除不存在的字段
db.accounts.update(
{ name: "jack"},
{ $unset:
{
notExistField:""
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
1.2.5 删除数组内的字段
- 例子9:删除jack的联系电话
db.accounts.update(
{ name: "jack"},
{
$unset: {
"contact.0": ""
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
- 例子9:再次查看jackde账户信息
> db.accounts.find( { name:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"name" : "jack",
"contact" : [
null,
"Alabama",
"US",
"new contact",
null,
null,
"another new contact"
],
"info" : {
}
}
# 删除后数组长度没变化,元素值被设为null
1.2.6 重命名字段
- 例子10: 如果$rename命令要重命名的字段并不存在,那么文档内容不会被改变
db.accounts.update(
{ name: "jack" },
{ $rename:
{
"notExistField":"name"
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
- 例子11:如果新的字段名已经存在,那么原有的这个字段会被覆盖
db.accounts.update(
{ name: "jack"},
{ $rename:
{
"name":"contact"
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 再次查看
> db.accounts.find( { contact:"jack"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152001"),
"contact" : "jack",
"info" : {
}
}
当 rename命令会先set新字段
1.2.7 重命名内嵌文档的字段
- 例子12:更新karen的银行账户的开户时间和联系方式
# 1.先查看karen账户内容
> db.accounts.find( { name:"karen"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152002"),
"name" : "karen",
"balance" : 2500,
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China"
]
}
# 2. 再更新
db.accounts.update(
{ name: "karen" },
{ $set:
{
info: {
dateOpene: new Date("2017-01-01T16:00:00Z"),
branch: "branch1"
},
"contact.3": {
primaryEmail: "xxx@gmail.com",
secondaryEmail: "yyy@gmail.com"
}
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 3. 再次查看账户内容
> db.accounts.find( { name:"karen"}).pretty(){
"_id" : ObjectId("63be7ea6ef3b5e682a152002"),
"name" : "karen",
"balance" : 2500,
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
}
],
"info" : {
"dateOpene" : ISODate("2017-01-01T16:00:00Z"),
"branch" : "branch1"
}
}
- 例子13:更新账户余额和开户地点字段在文档中的位置(两个交换位置)
db.accounts.update(
{ name: "karen"},
{ $rename:
{
"info.branch": "branch",
"balance": "info.balance"
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 再次查看
> db.accounts.find( { name:"karen"}).pretty()
{
"_id" : ObjectId("63be7ea6ef3b5e682a152002"),
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
}
],
"info" : {
"dateOpene" : ISODate("2017-01-01T16:00:00Z"),
"balance" : 2500
},
"branch" : "branch1"
}
1.2.8 重命名数组中内嵌文档的字段
- 例子14:更新Karen的联系方式
# 错误1
db.accounts.update(
{ name: "karen" },
{
$rename:
{
"contact.3.primaryEmail": "primaryEamil"
}
}
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 2,
"errmsg" : "The source field cannot be an array element, 'contact.3.primaryEmail' in doc with _id: ObjectId('63be7ea6ef3b5e682a152002') has an array field called 'contact'"
}
})
# 错误2:
db.accounts.update(
{ name: "karen" },
{
$rename:
{
"branch": "contact.3.branch"
}
}
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 2,
"errmsg" : "The destination field cannot be an array element, 'contact.3.branch' in doc with _id: ObjectId('63be7ea6ef3b5e682a152002') has an array field called 'contact'"
}
})
$rename命令中的旧字段和新字段都不可以指向数组元素
1.2.9更新字段数值(加减)
- 例子15:更新david的账户余额
# 1. 余额减去0.5
db.accounts.update(
{ name: "david"},
{ $inc:
{
balance:-0.5
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
`
# 2. 查看账户信息
> db.accounts.find( { name:"david"}).pretty()
{
"_id" : ObjectId("63bd1a23ef3b5e682a151ffa"),
"name" : "david",
"balance" : 199.5
}
{
"_id" : ObjectId("63bd1c91ef3b5e682a151ffc"),
"name" : "david",
"balance" : 20
}
1.2.10 更新字段数值(相乘)
- 例子16: 更新账户余额
# 1. 余额乘以0.5
db.accounts.update(
{ name: "david"},
{ $mul:
{
balance: 0.5
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 2. 查看账户信息
> db.accounts.find( { name:"david"}).pretty()
{
"_id" : ObjectId("63bd1a23ef3b5e682a151ffa"),
"name" : "david",
"balance" : 99.75
}
{
"_id" : ObjectId("63bd1c91ef3b5e682a151ffc"),
"name" : "david",
"balance" : 20
}
mul命令只能应用在数字字段上
1.2.11 比较之后更新字段值(min、max)
- 例子17: 更新账户余额
# 1. 查看karen的银行账户文档
db.accounts.find(
{ name: "karen" },
{ name:1,info:1,_id:0}
)
{ "name" : "karen", "info" : { "dateOpene" : ISODate("2017-01-01T16:00:00Z"), "balance" : 2500 } }
# 2. min保留比较小的字段值
db.accounts.update(
{ name:"karen"},
{ $min:
{
"info.balance":5000
}
}
)
# 所以没有任何文档更新
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
# 3.max保留比较大的值
db.accounts.update(
{ name:"karen"},
{ $max:
{
"info.balance":5000
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 4. 查看更新结果
db.accounts.find(
{ name: "karen" },
{ name:1,info:1,_id:0}
)
{ "name" : "karen", "info" : { "dateOpene" : ISODate("2017-01-01T16:00:00Z"), "balance" : 5000 } }
- 例子18: 如果被更新的字段不存在
# 1. 更新一个不存在的字段
db.accounts.update(
{ name: "karen"},
{ $min:
{
notYetExist:10
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 2. 查看karen的账户
db.accounts.find(
{ name: "karen" },
{ name:1,notYetExist:1,info:1,_id:0}
)
所以不存在的字段会添加到文档中,值就位上面设置的值
{ "name" : "karen", "info" : { "dateOpene" : ISODate("2017-01-01T16:00:00Z"), "balance" : 5000 }, "notYetExist" : 10 }
- 例子19:如果被更新的字段类型和更新值类型不一致
# 1. 将数值与Null比
db.accounts.update(
{ name: "karen"},
{
$min:
{
"info.balance":null
}
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 查看Karen账户文档
db.accounts.find(
{ name: "karen" },
{ name:1 , info: 1 , _id:0 }
)
用null替换掉之前的值
{ "name" : "karen", "info" : { "dateOpene" : ISODate("2017-01-01T16:00:00Z"), "balance" : null } }
如果被更新的字段类型和更新值类型不一致,max命令会按照
BSON数据类型排序规则进行比较
最小:
NUll
Numbers(ints,longs,doubles,decimals)
Symbol, String
Object
Array
BinData
ObjectId
Boolean
Date
Timestamp
最大
Regular Expression
1.3 更新数组
数组更新操作符:
$addToSet 向数组中增添元素(可搭配$each) { $addToSet: { <field1>: <value1>,...}}
$pop 从数组中移除元素(默认末尾) { $pop: { <field>: <-1 | 1>,... }}
$pull 从数组中有选择性的移除元素 { $pull: { <filed1>: <value|condition>, ...}}
$pullAll 从数组中有选择性的移除元素 { #pullAll: { <field1>: [ <value1>,<value2> ...], ...}}
$push 向数组字段中添加元素 { $push: { <field1>:<value1>, .... } }
1.3.1 向数组字段中添加元素(push)
$addToSet
- 例子20:查看Karen的银行账户文档
db.accounts.find(
{ name: "karen"},
{ name: 1, contact: 1, _id: 0}
).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
}
]
}
- 例子20: 向karen的账户(contact)添加联系方式
# 添加一个重复的值
db.accounts.update(
{ name: "karen"},
{ $addToSet: { contact: "China" }}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
如果要插入的值已经存在数组字段中,则$addToSet不会再添加重复值
注意一下:使用$addToSet插入数组和文档时,插入值中的字段顺序也和已有值重复的时候,才被算作重复值被忽略
- 例子21:向Karen的账户文档中添加新的联系方式
添加 数组 重复值(但是顺序不一样)
db.accounts.update(
{ name: "karen" },
{ $addToSet: {
contact: {
"secondaryEmail": "yyy@gmail.com",
"primaryEmail":"xxx@gmail.com"
}
}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
查看Karen的账户
db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
}
]
}
- 例子22: 向Karen的账户文档中添加多个联系方式(一个数组成为内嵌数组)
插入一个数组数据
db.accounts.update(
{ name: "karen"},
{ $addToSet: { contact: [ "contact1","contact2"]}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
# 再次查看
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[
"contact1",
"contact2"
]
]
}
$addToSet会将数组插入被更新的数组字段中,成为内嵌数组
如果想要将多个元素直接添加到数组字段中,则需要使用$each操作符
- 例子23:向Karen的账户文档添加多个联系方式(一个数组直接插入元素)
db.accounts.update(
{ name: "karen"},
{ $addToSet: { contact: { $each: [ "contact1","contact2" ] } } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
再次查看
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[
"contact1",
"contact2"
],
"contact1", # 发现元素单独插入,而不是直接插入一个数组
"contact2"
]
}
$push
addToSet命令相似,但是addToSet命令一样,如果$push命令指定的数组字段不存在,这个字段会被添加到原文档中
db.accounts.update(
{ name: "lawrence"},
{ $push: {newArray: "new element" } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.accounts.find( { name: "lawrence"}, { name:1, newArray:1, _id:0 } ).pretty()
{ "name" : "lawrence", "newArray" : [ "new element" ] }
1.3.2 从数组字段中删除元素($pop)
- 例子24:从Karen的账户文档中删除最后一个联系方式
1代表删除最后一个元素
db.accounts.update(
{ name: "karen"},
{ $pop: { contact:1 } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[
"contact1",
"contact2"
],
"contact1" # 之前的contact2删掉了
]
}
-1代表删除第一个元素
db.accounts.update(
{ name: "karen" },
{ $pop: { "contact.5": -1}} # 删除下标5(第6个)元素的第一个元素
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[
"contact2" # 删除了这个内嵌数组的第一个元素
],
"contact1"
]
}
再次删除,会保留空的数组
> db.accounts.update( { name: "karen" }, { $pop: { "contact.5": -1}} )
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[ ], # 删掉最后一个元素,会留下空数组
"contact1"
]
}
删除掉数组中最后一个元素,会留下空数组
注意一点,$pop操作符只能应用在数组字段上,看下面例子
尝试应用在数组字段上的字符串
db.accounts.update(
{ name: "karen" },
{ $pop: { "contact.1": -1 } }
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 14,
"errmsg" : "Path 'contact.1' contains an element of non-array type 'string'"
}
})
1.3.3 从数组字段中删除特定元素
使用$pull
先将Karen的账户文档复制一份,并将新文档的用户姓名设置为lawrence
db.accounts.find(
{name: "karen"},
{ _id: 0 }
).forEach( function(doc){
var newDoc = doc;
newDoc.name= "lawrence";
db.accounts.insert(newDoc)
})
查看larence的银行账户文档
> db.accounts.find( { name: "lawrence"} ).pretty()
{
"_id" : ObjectId("63d630f61ce94226b81725a2"),
"name" : "lawrence",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[ ],
"contact1"
],
"info" : {
"dateOpene" : ISODate("2017-01-01T16:00:00Z"),
"balance" : null
},
"branch" : "branch1",
"notYetExist" : 10
}
- 例子25:从Karen的联系方式中删去包含'hi'字母的元素
db.accounts.update(
{ name: "karen"},
{ $pull: { contact: { $elemMatch: { $regex: /hi/}}}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
事实上,既然$pull操作符本身是只能作用在数组元素上的,我们便不需要再额外使用$elemMatch操作符了
可以将$pull操作符处理的数组元素当作普通的顶层字段来应用筛选条件
db.accounts.update(
{ name: "karen"},
{ $pull: { contact: {$regex: /hi/}}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
再次查看
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing", # 删掉了原本的china
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[ ],
"contact1"
]
}
当然,如果有数组元素本身就是一个
内嵌数组,也可以使用$elemMatch来对这些内嵌数组进行筛选
- 例子26:从Karen的联系方式中删去电话号码22222222
db.accounts.update(
{ name: "karen"},
{ $pull: { contact: { $elemMatch: {$eq: "22222222"}}}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.accounts.find( { name: "karen"}, { name: 1, contact: 1, _id: 0} ).pretty()
{
"name" : "karen",
"contact" : [
"Beijing",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[ ],
"contact1"
]
}
使用$pullAll
{ $pullAll: { <field1>: [ <value1>,<value2> ] } }
相当于
{ $pull: { <field>: { $in:[ <value1>,<value2> ] } } }
如果要删去的元素是一个数组,数组元素的值和排列顺序都必须和被删除的数组完全一样
- 例子27:查看lawrence的银行账户文档
db.accounts.find(
{ name: "lawrence"},
{ name:1, contact:1, _id:0 }
).pretty()
{
"name" : "lawrence",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
{
"secondaryEmail" : "yyy@gmail.com",
"primaryEmail" : "xxx@gmail.com"
},
[ ],
"contact1"
]
}
- 例子28:删除联系电话(一个内嵌数组)
当元素的排列顺序不一样时,无法删除
db.accounts.update(
{name: "lawrence"},
{ $pullAll: { contact: [ [ "33333333", "22222222"]]}}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
当值和排列顺序完全一样时才可以删除
如果要删去的元素是一个
文档,$pullAll命令只会删去字段和字段排列顺序都完全匹配的文档元素
- 例子29:
情况一:当要删去的文档只包含原文档的一部分时,删除失败
db.accounts.update(
{ name: "lawrence"},
{ $pullAll: {contact: [ { "primaryEmail": "xxx@gmail.com" } ] } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
情况二:当包含全部字段时,就要看字段的顺序是否一致
db.accounts.update(
{ name: "lawrence"},
{ $pullAll: {contact: [ { "secondaryEmail": "yyy@gmail.com","primaryEmail": "xxx@gmail.com" } ] } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
查看删除后的文档,发现删除了符合顺序的那个文档
> db.accounts.find( { name: "lawrence"}, { name:1, contact:1, _id:0 } ).pretty()
{
"name" : "lawrence",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
{
"primaryEmail" : "xxx@gmail.com",
"secondaryEmail" : "yyy@gmail.com"
},
[ ],
"contact1"
]
}
$pull命令会删去包含指定的文档字段和字段值的文档元素,字段排列顺序
不需要完全匹配
- 例子30:
情况一:当提供给pull命令的参数文档只和原文档部分符合时,会删除
db.accounts.update(
{ name: "lawrence" },
{ $pull: { contact: { "primaryEmail": "xxx@gmail.com"} } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.accounts.find( { name: "lawrence"}, { name:1, contact:1, _id:0 } ).pretty()
{
"name" : "lawrence",
"contact" : [
[
"22222222",
"33333333"
],
"Beijing",
"China",
[ ],
"contact1"
]
}
情况二:当提供给pull命令的参数文档和原文档的字段相同,顺序不同时,会删除
db.accounts.update(
{ name: "lawrence" },
{ $pull: { contact: { "secondaryEmail": "yyy@gmail.com","primaryEmail": "xxx@gmail.com"} } }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })