MongoDB更新文档
更新文档
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:{'book.name': 'it6666.top'}})
更新数组字段
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.it6666.top'}})
删除文档字段中的字段
db.person.update({name:'ww'}, {$unset:{'book.name': ''}})
删除数组字段中的元素,如果删除的是数组字段中的元素, 那么并不会修改数组的长度, 而是用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.name':'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.name':'tags.0.TagName'}})
乾坤大挪移
可以将外层的字段转移到内层的文档中
db.person.update({name:'it6666'}, {$rename:{age:'book.age'}})
db.person.find();
可以将内层文档中的字段, 转移到外层文档中
db.person.update({name:'it6666'}, {$rename:{'book.age':'age'}})
$inc 和 $mul 更新操作符
添加测试数据:
db.person.insert({name: 'BNTang', age: 33});
db.person.find();
- $inc: 更新字段值(增加或者减少字段保存的值)
- 格式:
{$inc:{<field>: <number>}}
db.person.update({name: 'BNTang'}, {$inc: {age: -3}})
db.person.find();
db.person.update({name: 'BNTang'}, {$inc: {age: 5}})
db.person.find();
- $mul: 更新字段值(乘以或者除以字段保存的值)
- 格式:
{$mul:{<field>: <number>}}
db.person.update({name:'BNTang'}, {$mul:{age:2}})
db.person.find();
db.person.update({name:'BNTang'}, {$mul:{age:0.5}})
db.person.find();
注意点:
- 如果操作的字段不存在,那么会自动新增
- 如果是 $inc 那么不仅仅会新增,还会将操作的值赋值给新增的字段
db.person.update({name: 'BNTang'}, {$inc: {score: 66}});
db.person.find();
- 如果是 $mul那么只会新增字段,不会将操作的值赋值给新增的字段,他是用0来填充
db.person.update({name: 'BNTang'}, {$mul: {height: 1.75}});
db.person.find();
- \
mul 只能操作数值类型的字段
db.person.update({name: 'BNTang'}, {$mul: {name: 10}});
$min 和 $max 更新操作符
- 老规矩现在添加一些测试数据, 添加的时候先将之前的 db 删除即可:
db.person.insert({name: 'BNTang', age: 33});
db.person.find();
$min
: 比较保留更小字段值,格式:{$min: {<field>: <value>}}
然后博主就编写了如下这么一条更新指令,然后在执行的时候发现更新 row 为 0,代表啥没有然后数据进行改变:
db.person.update({name: 'BNTang'}, {$min: {age: 34}});
原因就是因为使用了 min ,min 会拿当前修改的值与之前的值进行比较,那个小听谁的,那么这个时候在来一个比之前小的值更新会怎样如下:
db.person.update({name: 'BNTang'}, {$min: {age: 32}});
可以看到更新成功了,那么这个就是 min 的使用,max 就不举例了同理可证,那么剩下的就是几个注意点在说一下就行了。
- 如果操作的字段不存在, 那么会自动增加, 并且会将操作的值赋值给新增的字段
db.person.update({name: 'BNTang'}, {$min: {weight: 120}});
db.person.update({name: 'BNTang'}, {$min: {height: 170}});
- 和
$inc/$mul
不同,$min/$max
不仅仅能操作数值类型的字段, 只要是可以比较的字段都可以操作
db.person.insert({name:'def', age:666})
db.person.update({name:'def'}, {$min:{name:'efg'}})
db.person.update({name:'def'}, {$min:{name:'cde'}})
执行 min 因为 efg
比 def 大,所以没有改变,执行第二个 min 因为 cde 比 def
小,所以就变更为了 cde
。
- 不是相同的数据类型也可以进行比较(这个比较变态)
db.person.update({name:'BNTang'}, {$min:{age:null}});
MongoDB 对 BSON 的数据类型有一个潜在的排序规则(从小到大):
- Null
- Numbers(ints, longs, doubles, decimals)
- Symbol, String
- Object
- Array
- BinData
- ObjectId
- Boolean
- Date
- Timestamp
- Regular Expression
$addToSet 数组更新操作符
$addToSet
: 向数组字段中添加元素, 格式:{$addToSet: {<field>: <values>, ...}}
添加测试数据:
db.person.insert([
{name:'zs', books:[{name:'html', price:66}, {name:'js', price:88}], tags:['html', 'js']},
{name:'ls', books:[{name:'vue', price:99}, {name:'node', price:199}], tags:['vue', 'node']}
])
利用 $addToSet 添加数据:
db.person.update({name:'zs'}, {$addToSet:{tags: 'react'}});
注意点
- 如果操作的元素不存在, 那么会自动新增, 并且将操作的值赋值给新增的数组字段
db.person.update({name:'zs'}, {$addToSet:{other: '123'}});
$addToSet
会自动去重, 如果添加的元素已经存在了, 那么就不会添加了
db.person.update({name:'zs'}, {$addToSet:{other: '123'}});
- 如果往数组字段中添加的是文档类型, 那么必须一模一样才会去重, 也就是属性字段的位置需要保持一致
db.person.update({name:'zs'}, {$addToSet:{books:{name:'html', price:66}}});
db.person.update({name:'zs'}, {$addToSet:{books:{price: 66, name: 'html'}}});
- 如果往数组字段中添加的是数组, 那么也必须一模一样才会去重
db.person.update({name:'ls'}, {$addToSet:{tags:['1', '2']}});
db.person.update({name:'ls'}, {$addToSet:{tags:['1', '2']}});
db.person.update({name:'ls'}, {$addToSet:{tags:['2', '1']}});
- 如果往数组字段中添加的是数组, 那么默认情况下会将整个数组作为一个元素添加进去, 如果不想整体添加进去, 那么必须使用
$each
来添加
db.person.update({name:'ls'}, {$addToSet:{tags:{$each: ['1', '2', '3']}}});
$push 数组更新操作符
$push
: 向数组字段中添加元素(不会自动去重),格式:{$push: {<field>: <value1>, ...}}
db.person.update({name: 'ls'},{$push: {tags: 'vue'}});
测试方式就是执行两次,会发现两次都可以进行添加进去。
$pop 数组更新操作符
$pop
: 从数组字段中删除元素, 格式:{$pop: {<field>: <1|-1>, ...}}
- $pop 有两个取值一个是
1
代表的含义为,删除最后一个也就说从后面开始删,-1
删除第一个从前面开始删
db.person.update({name: 'zs'}, {$pop: {tags: 1}});
db.person.update({name: 'zs'}, {$pop: {tags: -1}});
- 注意点, 数组中的元素都被删除以后, 仍然会保留空的数组
$pull 数组更新操作符
$pull
: 从数组字段中删除特定元素, 格式:{$pull: {<field>: <value|condition>, ...}}
看示例之前首先添加一些测试数据,把之前的 person 先删了,在重新添加:
db.person.insert([
{name:'zs', books:[{name:'html', price:66}, {name:'js', price:88}], tags:['html', 'js', ['1', '2']]},
{name:'ls', books:[{name:'vue', price:99}, {name:'node', price:199}], tags:['a', 'b', 'ab', 'c', 'ac']}
])
- 删除特定元素
db.person.update({name: 'zs'}, {$pull: {tags: 'js'}});
- 根据条件删除元素,可以是正则表达式
db.person.update({name: 'ls'}, {$pull: {tags: /^a/}});
注意点
- 如果要删除的元素是一个数组, 那么必须一模一样才能删除
db.person.update({name:'zs'}, {$pull:{tags:['2', '1']}});
db.person.update({name:'zs'}, {$pull:{tags:['1', '2']}});
- 如果要删除的元素是一个文档, 那么不用一模一样也可以删除
db.person.update({name:'zs'}, {$pull:{books:{price:66, name:'html'}}});
db.person.update({name:'zs'}, {$pull:{books:{name:'js'}}});
$pullAll 数组更新操作符
$pullAll
: 从数组字段中批量删除特定元素, 格式:{$pullAll: {<field>: [<value1>, <value2>, ...], ...}}
看示例之前首先添加一些测试数据,把之前的 person 先删了,在重新添加:
db.person.insert([
{name:'zs', books:[{name:'html', price:66}, {name:'js', price:88}], tags:['html', 'js', ['1', '2']]},
{name:'ls', books:[{name:'vue', price:99}, {name:'node', price:199}], tags:['a', 'b', 'ab', 'c', 'ac']}
])
- 利用 $pullAll 删除特定元素的数据
db.person.update({name:'zs'}, {$pullAll:{tags:['html', 'js']}});
注意点
- 和
$pull
一样, 如果删除的是数组字段中的数组元素, 那么必须一模一样才能删除
db.person.update({name:'zs'}, {$pullAll:{tags:[['2','1']]}});
db.person.update({name:'zs'}, {$pullAll:{tags:[['1','2']]}});
- 和
$pull
不一样, 如果删除的是数组字段中的文档元素, 那么也必须一模一样才能删除
db.person.update({name:'zs'}, {$pullAll:{books:[{price:66,name:'html'}]}});
db.person.update({name:'zs'}, {$pullAll:{books:[{name:'html',price:66}]}});
$ 和 $[] 数组更新操作符
- $: 更新数组中满足条件的特定元素
格式:
db.<collection>.update(
{ <array field>: <query selector> }
{ <update operator>: {'<array field>.$':value}}
)
看示例之前首先添加一些测试数据,把之前的 person 先删了,在重新添加:
db.person.insert([
{name:'zs', books:[{name:'html', price:66}, {name:'js', price:88}], tags:['html', 'js', ['1', '2']]},
{name:'ls', books:[{name:'vue', price:99}, {name:'node', price:199}], tags:['a', 'b', 'ab', 'c', 'ac']}
])
- $ 的意思就是可以把 update 的第一个函数传递的参数作为查询条件,进行作为更改的条件如下假如我需要将 zs 的 js 改为 JavaScript
db.person.update(
{name:'zs', tags:'js'},
{$set:{'tags.$':'JavaScript'}}
);
- $[]: 更新数组中所有元素
格式:
db.<collection>.update(
{ <update operator>: {'<array field>.$[]':value}}
)
$[]
和$
的作用含义差不多就是$[]
是可以批量的更改数组中所有符合条件的元素的数据,利用,我要将 zs 的 tags 当中的所有内容更改为it6666.top
db.person.update(
{name:'zs'},
{$set:{'tags.$[]': 'it6666.top'}}
);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具