《MongoDB》Mongo Shell中的基本操作-更新操作一覽前端博主,熱衷各種前端向的騷操作,經(jīng)常想到哪就寫到哪,如果有感興趣的技術(shù)和前端效果可以留言~博主看到后會去代替大家踩坑的~
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名注冊、雅安服務(wù)器托管、營銷軟件、網(wǎng)站建設(shè)、寧江網(wǎng)站維護(hù)、網(wǎng)站推廣。
主頁: oliver尹的主頁
格言: 跌倒了爬起來就好~
來個關(guān)注吧,點(diǎn)個贊吧,謝謝
本篇記錄備份的是Mongo DB的一些基礎(chǔ)知識,包括文檔長什么樣子,Mongo Shell中的CRUD這四種基本操作,什么是CRUD?C(Creadt、創(chuàng)建)R(Read、讀?。︰(Update、更新)D(Delete、刪除),人話就是增、刪、改、查等等;
注意,本文中的示例命令都是基于Mongo Shell的,并不是直接運(yùn)行在類似于node代碼中的~
本文主要記錄分享了MongoDB中的更新操作以及更新操作時的操作符
當(dāng)通過insert()方法將文檔在MongoDB中創(chuàng)建之后,肯定是需要對文檔進(jìn)行更新的,比如用戶點(diǎn)擊了修改密碼,這些操作不是新增,是對現(xiàn)有數(shù)據(jù)進(jìn)行修改;
3.1 db.collection.update()更新文檔,具體模版如下:
db.update(,,
在不使用 更新操作符 的情況下,使用db.collection.update()將會 直接替換集合中的文檔;更新操作符等會再看;
以上方的這個模版為例,且不使用更新操作符看一個具體的示例:
db.test.update({name:"oliver"},{name:"oliver",age:20})
簡單說明:在test這個集合中找到了name值是oliver的數(shù)據(jù),并且將這條數(shù)據(jù) 替換 成了{(lán)name:“oliver”,age:20},假如這條數(shù)據(jù) 本來還有其他的字段,這些字段都將會消失,因?yàn)槭翘鎿Q操作
注意點(diǎn)在更新操作中有一個需要注意的問題
db.test.update({name:"oliver"},{_id:"demotest",name:"oliver",age:20})
那么 _id這個值必須和原來的這個文檔的_id值保持一致,如果不一致,那么就會報錯,更新失??;
db.test.update({balance:{$gt:20,$lt:80}},{name:"bill",balance:50,gender:"M"})
在test集合中查詢所有balance大于20,小于80的文檔,將其更新成name等于bill,balance等于50,gender等于M
從結(jié)果看,只有第一篇被更新了,第二篇并沒有被更新,因此說明update的整篇文檔更新只能作用在單一文檔上,這是一個局限~
使用$set更新某個字段或者在某個文檔中創(chuàng)建字段,基本模版如下:
db..update({ $set : {:,...,:} })
具體示例如下
db.test.update(
{name: "jack"},
$set:{
balance: 3000,
info: {
dateOpened: new Date("2016-05-18T16:00:00z")
branch:"branch1"
}
})
首先在update的第一個參數(shù)name:jack,意思是找到name等于jack的數(shù)據(jù),之后對這條數(shù)據(jù)進(jìn)行更新,更新的字段是balance和info,將balance的值更新為3000,將info的值更新成一個對象,這個對象里有一個branch,且其值是branch1,如果jack這條數(shù)據(jù)不存在balance或者info,那么將為這條數(shù)據(jù)添加這兩個字段并且加上對應(yīng)的值;
如果更新的字段是 文檔中的內(nèi)嵌字段,比如上例中info里面的dateOpened,info本身就是一個對象,那么更新方式應(yīng)該如下:
db.test.update(
{name: "jack"},
$set:{
"info.dateOpened": new Date("2022-09-18T17:00:00z"),
})
如果更新的字段是 數(shù)組內(nèi)的字段,那么更新方式應(yīng)該如下:
db.test.update(
{name: "jack"},
$set:{
"contact.0": 752746873,
})
contact是一個數(shù)組,.0代表的就是數(shù)組內(nèi)的下標(biāo),意思就是將contact下的第0位更新成752746873,在數(shù)組內(nèi)新增也是同樣的,為某個新位置添加對應(yīng)的值即可,值得注意的是,如果下標(biāo)的位置超出了原本的長度,比如contact的長度是3,但現(xiàn)在我們在第5位添加了數(shù)據(jù),那么第4位就會自動補(bǔ)全為null;
使用$unset刪除文檔中的某個字段,基本模版如下:
db..update({ $unset : {:"",...,:""} })
具體示例如下
db.test.update(
{name: "jack"},
$unset:{
balance: "",
"info.branch": ""
})
在test集合中找到name等于jack的文檔,刪掉balance這個字段,同時也刪掉info這個對象下的branch這個字段;
如果,刪除的字段在文檔中本身就不存在,那么文檔本身將不會收到任何影響~
如果要 刪除數(shù)組內(nèi)的某個字段,那么命令應(yīng)該這么寫:
db.test.update(
{name: "jack"},
$unset:{"contact.0": ""})
值得注意的是,刪除內(nèi)容并不會改變數(shù)組的長度,只是會將對應(yīng)位置的值變成null;
使用$rename重命名文檔中的某個字段,基本模版如下:
db..update({ $rename : {:,...,:} })
首先要注意的是,如果重命名的字段在文檔中并不存在,那么文檔將不會有任何改變;如果重命名的字段在文檔中已經(jīng)存在了,那么原來存在的字段會被抹去,這個要非常注意;舉個例子吧
db.test.update(
{name: "jack"},
$rename:{
name: "contact"
})
contact這個字段在文檔中本身就已經(jīng)存在了,我們知道這個字段原來是一個數(shù)組,那么如果我們通過rename將name改成contact,那么contact這個字段原來值會被抹去
所以使用時得非常注意與小心,實(shí)際上,如果我們使用rename已經(jīng)存在的字段,它在內(nèi)部會先做一個unset刪除,在做一個set新增;
如果重命名的字段是 內(nèi)嵌文檔中的字段,那么我們改已以下方式重命名:
db.test.update(
{name: "karen"},
$rename:{
"info.branch": "branch",
"balance":"info.balance"
})
什么意思呢?簡單的說就是將info.branch路徑的字段重命名成branch,將balance重命名到info下的balance,實(shí)際造成的結(jié)果就有點(diǎn)類似于將字段移動,
那么 數(shù)組中的字段重命名 呢?
db.test.update(
{name: "karen"},
$rename:{
"contact.3.primaryEmail": "primaryEmail"
})
答案是 不行,MongoDB會報錯,它會不允許,同理,反向放入數(shù)組也不行,也會報錯
使用$inc可以更新的某個 數(shù)字類型的字段值,簡單的說就是用來進(jìn)行數(shù)字運(yùn)算,基本模版如下:
db..update({ $inc : {:,...,:} })
看個例子
db.test.update(
{name: "karen"},
$inc:{
"balance": 0.5
})
得到的結(jié)果就是給name等于karen的文檔下的balance值 加上0.5,同理,如果給的是一個負(fù)數(shù),如下例
db.test.update(
{name: "karen"},
$inc:{
"balance": -0.5
})
得到的結(jié)果就是給name等于karen的文檔下的balance值 減去0.5;
注意的是,如果操作的字段并 不存在于文檔上,那么字段與字段值會被作為初始數(shù)據(jù)添加到文檔上,比如"balance"這個字段不存在文檔上,那么該文檔會被添加一個"balance": -0.5的字段;
使用$mul可以更新的某個 數(shù)字類型的字段值,簡單的說就是用來進(jìn)行數(shù)字運(yùn)算,基本模版如下:
db..update({ $mul : {:,...,:} })
看個例子
db.test.update(
{name: "karen"},
$mul:{
"balance": 2
})
得到的結(jié)果就是給name等于karen的文檔下的balance值 乘以2,同理,如果給的是一個負(fù)數(shù),如下例
db.test.update(
{name: "karen"},
$mul:{
"balance": 0.5
})
得到的結(jié)果就是給name等于karen的文檔下的balance值 乘以0.5;
注意的是,如果操作的字段并 不存在于文檔上,那么字段與字段值會被作為初始數(shù)據(jù)添加到文檔上且值和$inc不同,它的值是0,比如"balance"這個字段不存在文檔上,那么該文檔會被添加一個"balance": 0的字段;
使用$min可以更新的某個字段值,簡單的說就是用來進(jìn)行字段比較,小的那一個會被最終留下,基本模版如下:
db..update({ $min : {:,...,:} })
看個例子
db.test.update(
{name: "karen"},
$min:{
"info.balance": 5000
})
意思是,先找到name值等于karen的文檔,然后對info.balance的值進(jìn)行比較,如果原文檔中的Info.balance值比較小,那么會保留原來的值,如果5000比較小,那么會將info.balance的值更新成5000;
除了數(shù)字類型外,min操作符還可以用在其他類型上,比如時間,可以比較時間哪個小,小的那個會被留下, 另外,如果更新的字段不存在,那么$min操作符會將值初始化進(jìn)文檔;
如果,兩者的類型不一樣,比如 info.balance的值是一個數(shù)字,我們將其更新成Null,
db.test.update(
{name: "karen"},
$min:{
"info.balance": null
})
最終,文檔的info.balance真的會被更新成null,因?yàn)樵趍ongodb中它其實(shí)是有一個內(nèi)部的大小排序的,排序如下
Null< Number< Symbol, String< Object< Array< BinData< ObjectId< Boolean< Date< Timestamp< Regular Expression
由于null比Number要小,因此上面例子中的更新會將null替換掉數(shù)字;
使用$max可以更新的某個字段值,簡單的說就是用來進(jìn)行字段比較,大的那一個會被最終留下,基本模版如下:
db..update({ $max : {:,...,:} })
看個例子
db.test.update(
{name: "karen"},
$max:{
"info.balance": 5000
})
意思是,先找到name值等于karen的文檔,然后對info.balance的值進(jìn)行比較,如果原文檔中的Info.balance值比較小,那么會保留5000,如果5000比較小,那么會將info.balance的值將不會變動,還是保留原來的值;
除了數(shù)字類型外,min操作符還可以用在其他類型上,比如時間,可以比較時間哪個大,大的那個會被留下,另外,如果更新的字段不存在,那么$max操作符會將值初始化進(jìn)文檔;
如果,兩者的類型不一樣,比如 info.balance的值是一個數(shù)字,我們將其更新成Null,
db.test.update(
{name: "karen"},
$min:{
"info.balance": null
})
最終,文檔的info.balance會按規(guī)則進(jìn)行排序,大的那個將會被留下,排序如下
Null< Number< Symbol, String< Object< Array< BinData< ObjectId< Boolean< Date< Timestamp< Regular Expression
由于null比Number要小,因此上面例子中的更新將不會被執(zhí)行,Number依然會被保留下來;
基本使用方式如下
db..update({ $addToset : {:} })
具體示例如下:
db.test.update(
{name: "jack"},
{$addToset:{contact: "chind"}})
如果添加的值在待添加的數(shù)組中已存在,則會添加失敗不會被添加進(jìn)去,但注意的是,如果添加的值是復(fù)雜類型,那么判斷會比較復(fù)雜,需要值完全相同且順序也完全相同才會被判定是否已存在數(shù)組中;
$pop 移除元素$pop用來刪除數(shù)組中的元素,但值得注意的是,只能刪除第一個元素或者最后一個元素,基本使用方式如下
db..update({ $pop : {:<1|-1>} })
具體示例如下:
db.test.update(
{name: "jack"},
{$pop:{contact: 1}})
代表刪除contact這個數(shù)組中最后一個元素,1代表最后一個,-1代表第一個;
$pull 選擇性刪除基本使用方式如下
db..update({ $pull : {:} })
具體示例如下:
db.test.update(
{name: "jack"},
{$pull:{contact: {$regex:/hi/}}}
)
找到所有name值是jack的文檔,刪除contact中所有包含hi的字段,這里的包含是通過正則進(jìn)行匹配的,另外pull也可以刪除特定的元素,示例如下:
db.test.update(
{name: "jack"},
{$pull:{contact: "222222"}}
)
另外,通過pull去刪除一個復(fù)雜類型的數(shù)據(jù)時,比如刪除的不再是一個字符串,而是一個對象,通過pull刪除時只需要提供對象中的一個鍵值對接口刪除整個數(shù)據(jù),或者提供全量的值但順序可以不一樣,這個和pullAll不一樣,pullAll需要 全部提供且順序也一樣;
$pullAll 選擇性刪除基本使用方式如下
db..update({ $pullAll : {:[,]} })
具體示例如下:
db.test.update(
{name: "jack"},
{$pullAll:{contact: ['222222','333333']}}
)
找到所有name值是jack的文檔,刪除contact中所有值是222222或者333333的值;
另外,通過pullAll去刪除一個復(fù)雜類型的數(shù)據(jù)時,比如刪除的不再是一個字符串,而是一個對象,那么參數(shù)必須是順序也是一摸一樣的才會被刪掉;
基本使用方式如下
db..update({ $push : {:...} })
具體示例如下:
db..update({ $push : {newArray:[1,2,3]} })
這樣[1,2,3]這個數(shù)組將會被添加進(jìn)newArray里,如果說想要將1,2,3分別添加進(jìn)行newArray而不是作為一個整體添加進(jìn)去則需要通過$each操作符
db..update({ $push : {newArray:{$each:[1,2,3]}} })
另外push比addtoset更加強(qiáng)大的地方在于存儲位置的調(diào)整,比如
db..update({ $push : {newArray:{$each:[1,2,3],$position:0}} })
這個的意思就是說,1,2,3會被存儲到下標(biāo)為第0位的這個位置;
還可以進(jìn)行排序,通過 sort 這個操作符進(jìn)行操作,值得注意的是$sort這個操作符不可以單獨(dú)使用,必須和 each 操作符一起使用
db..update({ $push : {newArray:{$each:[1,2,3],$sort:1}} })
從小到大進(jìn)行排序,同理,-1則代表從大到小排序;
$slice 操作符代表截取
db..update({ $push : {newArray:{$each:[1,2,3],$slice:-8}} })
代表截取到這數(shù)的8位進(jìn)行保存,對于剩下的就不再進(jìn)行保存了,直接丟棄,同理,如果值是正數(shù),那么就代表正著數(shù)的8位進(jìn)行保存
如果position,sort,slice被一起使用時,那么順序永遠(yuǎn)是,先通過$position向指定位置進(jìn)行保存,在進(jìn)行排序,最后進(jìn)行截??;
在上面我們知道,update有三個參數(shù)
db.update(,,
第三個參數(shù)中,有幾個比較重要的配置項,首先是multi,是否允許更新多篇文檔
multi 多篇更新{multi:}
具體示例
db.test.update({name:"oliver"},{name:"oliver",age:20},{multi:true})
那么所有的數(shù)據(jù)都將會被改寫,但值得注意的是,更新多個文檔的操作雖然在單一線程中執(zhí)行,但是線程在執(zhí)行的過程中可能被掛起,以便其他線程也有機(jī)會對數(shù)據(jù)進(jìn)行操作;因此,多個文檔被操作因此不能保證原子性,也就代表結(jié)果不一定是對的,比如掛起階段,某個文檔被其他線程給刪了,那等到掛起的線程繼續(xù)操作時,文檔已經(jīng)改變了,或者干脆已經(jīng)沒有了;
upsert 更新或創(chuàng)建update在沒有匹配到文檔時是否進(jìn)行創(chuàng)建,默認(rèn)時不會進(jìn)行創(chuàng)建的;
{upsert:}
具體示例
db.test.update({name:"oliver"},{name:"oliver",age:20},{upsert:true})
簡單的說,假如在test中沒有匹配到name為oliver的文檔,此時會在test中創(chuàng)建一篇{name:“oliver”,age:20}的文檔
四、小結(jié)本文主要記錄了在常規(guī)數(shù)據(jù)庫操作中文檔更新的一些用法~更新的命令非常簡單,都是db.collection.update(),但查詢時候的操作符非常復(fù)雜,需要經(jīng)常使用與回顧~
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧