更新文档
MongoDB中有三个常用的更新方法 save()
/ update()
/ findAndmodify()
save 方法
save用于往集合里添加一个新文档或者覆盖一个文档,当没有指定文档 _id
的时候就是新增,当指定了集合中已经存在的 _id
的时候就是覆盖原有文档,添加测试数据。
db.person.insert([
{name:'zs', age:18},
{name:'ls', age:19},
{name:'ww', age:20},
{name:'zs', age:21},
])
首先来看看没有指定 _id
的情况运行如下指令即可。
db.person.save({name: 'BNTang', age: 23})
指定 _id
db.person.save({_id: '5fa5fd3b00833f20162063b7', name: 'BNTang', age: 6666})
update 方法
语法如下所示:
db.collection.update(<filter>, <update>, <options>)
- <filter>:筛选条件
- <update>:新的内容
- <options>:额外配置
通过 update
方法覆盖满足条件的数据,默认情况下如果 <update>
没有使用更新操作符, 那么就会使用指定的内容覆盖符合条件的内容。
删除之前的测试数据重新插入
db.person.drop();
db.person.insert([
{name:'zs', age:18},
{name:'ls', age:19},
{name:'ww', age:20},
{name:'zs', age:21},
])
db.person.update({name:'BNTang'}, {name:'zs'})
注意点:
update方法默认情况下就是覆盖,如果不想覆盖, 而是想单纯的更新, 那么就必须在第二个参数中使用 更新操作符
。
db.person.update({name:'ww'},{score: 99.9},{})
update方法默认只会更新满足条件的第一个文档,如果想更新所有满足条件的文档, 那么就必须指定第三个参数。
db.person.update({name:'zs'}, {name:'zs', age:66}, {})
如果在使用update方法的时候, 在第二个参数中指定了_id
, 那么就必须保证指定的_id
和被更新的文档的_id
的取值一致, 否则就无法更新, 否则就会报错
开发技巧: 在企业开发中如果需要使用update方法, 那么就不要指定_id
db.person.update({name:'zs'}, {_id:1, name:'zs', age:55}, {})
db.person.update({name:'zs'}, {_id:ObjectId("5fa60bb100833f20162063b8"), name:'zs', age:88}, {})
如果想更新所有满足条件的文档, 我们可以指定第三个参数的取值为 multi:true
,如果指定了 multi:true, 那么就必须在第二个参数中使用更新操作符
db.person.update({name:'zs'}, {name:'zs', age:55}, {multi:true})
更新操作符
默认情况下update会使用新文档覆盖旧文档,如果不想覆盖而是仅仅想更新其中的某些字段,那么我们就需要使用update的更新操作符。
$set 更新操作符
$set: 更新或者新增字段, 字段存在就是更新, 字段不存在就是新增,格式如下:
{$set:<value1>, ...}
db.person.update({name:'zs'}, {$set:{name:'it6666'}})
db.person.update({name:'it6666'}, {$set:{age:'888'}})
更新内嵌文档和数组
删除之前测试的数据重新进行插入新的数据
db.person.drop();
db.person.insert([
{name:'zs', age:18},
{name:'ls', age:19},
{name:'ww', age:20},
{name:'zs', age:21},
])
db.person.update({name:'ww'}, {age:55})
更新普通字段
db.person.update({name:'ls'}, {$set:{age:55}})
db.person.update({name:'zs'},{$set: {age:666}},{multi: true})
db.person.insert(
{
name: 'ww',
age: 18,
book:{name: '跟着BNTang学编程', price: 2888},
tags:['html', 'JavaScript']}
)
更新文档字段
db.person.update({name:'ww'}, {$set:{'': ''}})
更新数组字段
db.person.update({name:'ww'}, {$set: {'tags.0': 'vue'}})
注意点,如果操作的字段存在, 那么就是更新, 如果操作的字段不存在, 那么就是新增
db.person.update({name:'ls'}, {$set:{score: 59.5}})
如果操作的是数组字段, 如果操作的索引不存在, 那么也会自动新增,如果被操作的索引前面没有数据, 那么会自动用null来填充
db.person.update({name:'ww'}, {$set: {'tags.2': 'react'}})
db.person.update({name:'ww'}, {$set: {'tags.5': 'node'}})
$unset 更新操作符
- $unset: 删除字段,语法格式如下:
{$unset:{<field>:'', ...}}
删除普通字段
db.person.update({name:'ls'}, {$unset:{score:''}})
如果使用 $unset
删除某一个字段, 那么后面赋值为任何的内容都不重要
db.person.update({name:'ls'}, {$unset:{age:'www.'}})
删除文档字段中的字段
db.person.update({name:'ww'}, {$unset:{'': ''}})
删除数组字段中的元素,如果删除的是数组字段中的元素, 那么并不会修改数组的长度, 而是用null来填充删除的内容
db.person.update({name:'ww'}, {$unset:{'tags.1': ''}})
注意点,删除数组元素并不会影响数组的长度, 而是设置为Null,如果删除的字段不存在, 不会做任何操作
$rename 更新操作符
- $rename: 重命名字段,语法格式如下:
{$rename:{<field>:<newName>, ...}}
db.person.update({name:'zs'}, {$rename:{name:'MyName'}})
如果修改的是文档字段中的字段, 那么取值必须写上层级关系
db.person.update({name:'ww'}, {$rename:{'':'book.BookName'}})
如果要操作的字段不存在, 那么不会做任何的操作
db.person.update({name:'ls'}, {$rename:{age:'MyAge'}})
如果重命名之后的名称已经存在了, 那么已经存在的字段就会被删除,底层的本质: 先调用了 $unset
删除了原有的book字段, 然后再调用$set修改字段的名称。
db.person.update({name:'ww'}, {$rename:{name:'book'}})
不能通过 $rename
更新操作符来操作数组。
db.person.insert(
{
name:'it6666',
age:666,
book:{name:'BNTang', price:999},
tags:[{name:'html', price:'123'}, {name:'js', price:456}]
}
)
db.person.update({name:'it6666'}, {$rename:{'':'tags.0.TagName'}})
乾坤大挪移
可以将外层的字段转移到内层的文档中
db.person.update({name:'it6666'}, {$rename:{age:'book.age'}})
db.person.find();
可以将内层文档中的字段, 转移到外层文档中
db.person.update({name:'it6666'}, {$rename:{'book.age':'age'}})