《MongoDB》MongoShell中的基本操作-更新操作一览-创新互联

前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~
主页: oliver尹的主页
格言: 跌倒了爬起来就好~
来个关注吧,点个赞吧,谢谢

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册雅安服务器托管、营销软件、网站建设、宁江网站维护、网站推广。

《MongoDB》Mongo Shell中的基本操作-更新操作一览
  • 一、简介
  • 二、内容概述
  • 三、更新文档
    • 3.1 db.collection.update()
      • 注意点
    • 3.2 更新操作符
      • $set 更新或新增字段
      • $unset 删除字段
      • $rename 重命名字段
      • $inc 加减字段值
      • $mul 相乘字段值
      • $min 比较较小字段值
      • $max 比较较大字段值
    • 3.3 数组更新操作符
      • $addToset 添加元素
      • $pop 移除元素
      • $pull 选择性删除
      • $pullAll 选择性删除
      • $push 添加元素
    • 3.4 配置参数
      • multi 多篇更新
      • upsert 更新或创建
  • 四、小结

一、简介

本篇记录备份的是Mongo DB的一些基础知识,包括文档长什么样子,Mongo Shell中的CRUD这四种基本操作,什么是CRUD?C(Creadt、创建)R(Read、读取)U(Update、更新)D(Delete、删除),人话就是增、删、改、查等等;
注意,本文中的示例命令都是基于Mongo Shell的,并不是直接运行在类似于node代码中的~

二、内容概述

本文主要记录分享了MongoDB中的更新操作以及更新操作时的操作符
在这里插入图片描述

三、更新文档

当通过insert()方法将文档在MongoDB中创建之后,肯定是需要对文档进行更新的,比如用户点击了修改密码,这些操作不是新增,是对现有数据进行修改;

3.1 db.collection.update()

更新文档,具体模版如下:

db.update(,,
  • query: 代表更新文档时筛选文档的条件,简单的说就是要更新某个文档的前提是你得找到这个文档;
  • update: 代表更新文档时需要更新的内容;
  • option: 代表声明了一些更新操作的参数;

在不使用 更新操作符 的情况下,使用db.collection.update()将会 直接替换集合中的文档;更新操作符等会再看;
以上方的这个模版为例,且不使用更新操作符看一个具体的示例:

db.test.update({name:"oliver"},{name:"oliver",age:20})

简单说明:在test这个集合中找到了name值是oliver的数据,并且将这条数据 替换 成了{name:“oliver”,age:20},假如这条数据 本来还有其他的字段,这些字段都将会消失,因为是替换操作

注意点

在更新操作中有一个需要注意的问题

  • 文档主键也就是_id是不可以更改的,在上例中其实也已经看到了,在update中并没有包含_id字段,如果一定要写_id,比如
db.test.update({name:"oliver"},{_id:"demotest",name:"oliver",age:20})

那么 _id这个值必须和原来的这个文档的_id值保持一致,如果不一致,那么就会报错,更新失败;

  • 当update中查询到多篇文档时,只有 第一篇 符合查询条件的文档会被更新,比如
db.test.update({balance:{$gt:20,$lt:80}},{name:"bill",balance:50,gender:"M"})

在test集合中查询所有balance大于20,小于80的文档,将其更新成name等于bill,balance等于50,gender等于M
在这里插入图片描述
从结果看,只有第一篇被更新了,第二篇并没有被更新,因此说明update的整篇文档更新只能作用在单一文档上,这是一个局限~

3.2 更新操作符 $set 更新或新增字段

使用$set更新某个字段或者在某个文档中创建字段,基本模版如下:

db..update({ $set : {:,...,:} })

具体示例如下

db.test.update(
{name: "jack"},
$set:{
	balance: 3000,
	info: {
  	dateOpened: new Date("2016-05-18T16:00:00z")
  	branch:"branch1"
  }
})

首先在update的第一个参数name:jack,意思是找到name等于jack的数据,之后对这条数据进行更新,更新的字段是balance和info,将balance的值更新为3000,将info的值更新成一个对象,这个对象里有一个branch,且其值是branch1,如果jack这条数据不存在balance或者info,那么将为这条数据添加这两个字段并且加上对应的值;
在这里插入图片描述
如果更新的字段是 文档中的内嵌字段,比如上例中info里面的dateOpened,info本身就是一个对象,那么更新方式应该如下:

db.test.update(
{name: "jack"},
$set:{
	"info.dateOpened": new Date("2022-09-18T17:00:00z"),
})

如果更新的字段是 数组内的字段,那么更新方式应该如下:

db.test.update(
{name: "jack"},
$set:{
	"contact.0": 752746873,
})

contact是一个数组,.0代表的就是数组内的下标,意思就是将contact下的第0位更新成752746873,在数组内新增也是同样的,为某个新位置添加对应的值即可,值得注意的是,如果下标的位置超出了原本的长度,比如contact的长度是3,但现在我们在第5位添加了数据,那么第4位就会自动补全为null;
在这里插入图片描述

$unset 删除字段

使用$unset删除文档中的某个字段,基本模版如下:

db..update({ $unset : {:"",...,:""} })

具体示例如下

db.test.update(
	{name: "jack"},
	$unset:{
		balance: "",
		"info.branch": ""
})

在test集合中找到name等于jack的文档,删掉balance这个字段,同时也删掉info这个对象下的branch这个字段;
在这里插入图片描述

如果,删除的字段在文档中本身就不存在,那么文档本身将不会收到任何影响~
如果要 删除数组内的某个字段,那么命令应该这么写:

db.test.update(
	{name: "jack"},
	$unset:{"contact.0": ""})

值得注意的是,删除内容并不会改变数组的长度,只是会将对应位置的值变成null;
在这里插入图片描述

$rename 重命名字段

使用$rename重命名文档中的某个字段,基本模版如下:

db..update({ $rename : {:,...,:} })

首先要注意的是,如果重命名的字段在文档中并不存在,那么文档将不会有任何改变;如果重命名的字段在文档中已经存在了,那么原来存在的字段会被抹去,这个要非常注意;举个例子吧

db.test.update(
	{name: "jack"},
	$rename:{
		name: "contact"
})

contact这个字段在文档中本身就已经存在了,我们知道这个字段原来是一个数组,那么如果我们通过rename将name改成contact,那么contact这个字段原来值会被抹去
在这里插入图片描述
所以使用时得非常注意与小心,实际上,如果我们使用rename已经存在的字段,它在内部会先做一个unset删除,在做一个set新增;
如果重命名的字段是 内嵌文档中的字段,那么我们改已以下方式重命名:

db.test.update(
	{name: "karen"},
	$rename:{
		"info.branch": "branch",
  	"balance":"info.balance"
})

什么意思呢?简单的说就是将info.branch路径的字段重命名成branch,将balance重命名到info下的balance,实际造成的结果就有点类似于将字段移动,
在这里插入图片描述
那么 数组中的字段重命名 呢?

db.test.update(
	{name: "karen"},
	$rename:{
		"contact.3.primaryEmail": "primaryEmail"
})

答案是 不行,MongoDB会报错,它会不允许,同理,反向放入数组也不行,也会报错
在这里插入图片描述

$inc 加减字段值

使用$inc可以更新的某个 数字类型的字段值,简单的说就是用来进行数字运算,基本模版如下:

db..update({ $inc : {:,...,:} })

看个例子

db.test.update(
	{name: "karen"},
	$inc:{
		"balance": 0.5
})

得到的结果就是给name等于karen的文档下的balance值 加上0.5,同理,如果给的是一个负数,如下例

db.test.update(
	{name: "karen"},
	$inc:{
		"balance": -0.5
})

得到的结果就是给name等于karen的文档下的balance值 减去0.5;
注意的是,如果操作的字段并 不存在于文档上,那么字段与字段值会被作为初始数据添加到文档上,比如"balance"这个字段不存在文档上,那么该文档会被添加一个"balance": -0.5的字段;

$mul 相乘字段值

使用$mul可以更新的某个 数字类型的字段值,简单的说就是用来进行数字运算,基本模版如下:

db..update({ $mul : {:,...,:} })

看个例子

db.test.update(
	{name: "karen"},
	$mul:{
		"balance": 2
})

得到的结果就是给name等于karen的文档下的balance值 乘以2,同理,如果给的是一个负数,如下例

db.test.update(
	{name: "karen"},
	$mul:{
		"balance": 0.5
})

得到的结果就是给name等于karen的文档下的balance值 乘以0.5;
注意的是,如果操作的字段并 不存在于文档上,那么字段与字段值会被作为初始数据添加到文档上且值和$inc不同,它的值是0,比如"balance"这个字段不存在文档上,那么该文档会被添加一个"balance": 0的字段;

$min 比较较小字段值

使用$min可以更新的某个字段值,简单的说就是用来进行字段比较,小的那一个会被最终留下,基本模版如下:

db..update({ $min : {:,...,:} })

看个例子

db.test.update(
	{name: "karen"},
	$min:{
		"info.balance": 5000
})

意思是,先找到name值等于karen的文档,然后对info.balance的值进行比较,如果原文档中的Info.balance值比较小,那么会保留原来的值,如果5000比较小,那么会将info.balance的值更新成5000;
除了数字类型外,min操作符还可以用在其他类型上,比如时间,可以比较时间哪个小,小的那个会被留下, 另外,如果更新的字段不存在,那么$min操作符会将值初始化进文档;
如果,两者的类型不一样,比如 info.balance的值是一个数字,我们将其更新成Null,

db.test.update(
	{name: "karen"},
	$min:{
		"info.balance": null
})

最终,文档的info.balance真的会被更新成null,因为在mongodb中它其实是有一个内部的大小排序的,排序如下
Null< Number< Symbol, String< Object< Array< BinData< ObjectId< Boolean< Date< Timestamp< Regular Expression
由于null比Number要小,因此上面例子中的更新会将null替换掉数字;

$max 比较较大字段值

使用$max可以更新的某个字段值,简单的说就是用来进行字段比较,大的那一个会被最终留下,基本模版如下:

db..update({ $max : {:,...,:} })

看个例子

db.test.update(
	{name: "karen"},
	$max:{
		"info.balance": 5000
})

意思是,先找到name值等于karen的文档,然后对info.balance的值进行比较,如果原文档中的Info.balance值比较小,那么会保留5000,如果5000比较小,那么会将info.balance的值将不会变动,还是保留原来的值;
除了数字类型外,min操作符还可以用在其他类型上,比如时间,可以比较时间哪个大,大的那个会被留下,另外,如果更新的字段不存在,那么$max操作符会将值初始化进文档;
如果,两者的类型不一样,比如 info.balance的值是一个数字,我们将其更新成Null,

db.test.update(
	{name: "karen"},
	$min:{
		"info.balance": null
})

最终,文档的info.balance会按规则进行排序,大的那个将会被留下,排序如下
Null< Number< Symbol, String< Object< Array< BinData< ObjectId< Boolean< Date< Timestamp< Regular Expression
由于null比Number要小,因此上面例子中的更新将不会被执行,Number依然会被保留下来;

3.3 数组更新操作符 $addToset 添加元素

基本使用方式如下

db..update({ $addToset : {:} })

具体示例如下:

db.test.update(
{name: "jack"},
{$addToset:{contact: "chind"}})

如果添加的值在待添加的数组中已存在,则会添加失败不会被添加进去,但注意的是,如果添加的值是复杂类型,那么判断会比较复杂,需要值完全相同且顺序也完全相同才会被判定是否已存在数组中;

$pop 移除元素

$pop用来删除数组中的元素,但值得注意的是,只能删除第一个元素或者最后一个元素,基本使用方式如下

db..update({ $pop : {:<1|-1>} })

具体示例如下:

db.test.update(
{name: "jack"},
{$pop:{contact: 1}})

代表删除contact这个数组中最后一个元素,1代表最后一个,-1代表第一个;

$pull 选择性删除

基本使用方式如下

db..update({ $pull : {:} })

具体示例如下:

db.test.update(
	{name: "jack"},
	{$pull:{contact: {$regex:/hi/}}}
)

找到所有name值是jack的文档,删除contact中所有包含hi的字段,这里的包含是通过正则进行匹配的,另外pull也可以删除特定的元素,示例如下:

db.test.update(
	{name: "jack"},
	{$pull:{contact: "222222"}}
)

另外,通过pull去删除一个复杂类型的数据时,比如删除的不再是一个字符串,而是一个对象,通过pull删除时只需要提供对象中的一个键值对接口删除整个数据,或者提供全量的值但顺序可以不一样,这个和pullAll不一样,pullAll需要 全部提供且顺序也一样;

$pullAll 选择性删除

基本使用方式如下

db..update({ $pullAll : {:[,]} })

具体示例如下:

db.test.update(
	{name: "jack"},
	{$pullAll:{contact: ['222222','333333']}}
)

找到所有name值是jack的文档,删除contact中所有值是222222或者333333的值;
另外,通过pullAll去删除一个复杂类型的数据时,比如删除的不再是一个字符串,而是一个对象,那么参数必须是顺序也是一摸一样的才会被删掉;

$push 添加元素

基本使用方式如下

db..update({ $push : {:...} })

具体示例如下:

db..update({ $push : {newArray:[1,2,3]} })

这样[1,2,3]这个数组将会被添加进newArray里,如果说想要将1,2,3分别添加进行newArray而不是作为一个整体添加进去则需要通过$each操作符

db..update({ $push : {newArray:{$each:[1,2,3]}} })

另外push比addtoset更加强大的地方在于存储位置的调整,比如

db..update({ $push : {newArray:{$each:[1,2,3],$position:0}} })

这个的意思就是说,1,2,3会被存储到下标为第0位的这个位置;
还可以进行排序,通过 sort 这个操作符进行操作,值得注意的是$sort这个操作符不可以单独使用,必须和 each 操作符一起使用

db..update({ $push : {newArray:{$each:[1,2,3],$sort:1}} })

从小到大进行排序,同理,-1则代表从大到小排序;
$slice 操作符代表截取

db..update({ $push : {newArray:{$each:[1,2,3],$slice:-8}} })

代表截取到这数的8位进行保存,对于剩下的就不再进行保存了,直接丢弃,同理,如果值是正数,那么就代表正着数的8位进行保存
如果position,sort,slice被一起使用时,那么顺序永远是,先通过$position向指定位置进行保存,在进行排序,最后进行截取;

3.4 配置参数

在上面我们知道,update有三个参数

db.update(,,

第三个参数中,有几个比较重要的配置项,首先是multi,是否允许更新多篇文档

multi 多篇更新
{multi:}

具体示例

db.test.update({name:"oliver"},{name:"oliver",age:20},{multi:true})

那么所有的数据都将会被改写,但值得注意的是,更新多个文档的操作虽然在单一线程中执行,但是线程在执行的过程中可能被挂起,以便其他线程也有机会对数据进行操作;因此,多个文档被操作因此不能保证原子性,也就代表结果不一定是对的,比如挂起阶段,某个文档被其他线程给删了,那等到挂起的线程继续操作时,文档已经改变了,或者干脆已经没有了;

upsert 更新或创建

update在没有匹配到文档时是否进行创建,默认时不会进行创建的;

{upsert:}

具体示例

db.test.update({name:"oliver"},{name:"oliver",age:20},{upsert:true})

简单的说,假如在test中没有匹配到name为oliver的文档,此时会在test中创建一篇{name:“oliver”,age:20}的文档

四、小结

本文主要记录了在常规数据库操作中文档更新的一些用法~更新的命令非常简单,都是db.collection.update(),但查询时候的操作符非常复杂,需要经常使用与回顾~

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文名称:《MongoDB》MongoShell中的基本操作-更新操作一览-创新互联
分享地址:http://ybzwz.com/article/ddijjo.html