1. 程式人生 > 資料庫 >7.4核心要點:MongoDB更新與刪除

7.4核心要點:MongoDB更新與刪除

7.4.1更新型別與引數選項
多文件更新
預設情況下,只會更新匹配查詢器的第一個文件。要更新所有匹配的文件,就需要顯示指定多文件更新模式。在shell中,使用multi:true來實現。在文件級別更新是原子性的,這意味著一條更新10個文件的語句可能在更新3個文件後由於某種原因失敗。應用程式必須根據自己的策略來處理這些失敗。
upserts
upserts,當文件存在時更新,文件不存在時候插入資料。如果查詢選擇器匹配,更新正常進行。如果沒有匹配的文件,就會插入新的文件。新文件的欄位是查詢選擇器和目標更新文件的邏輯合併。upsert無法與替換更新文件模式一起工作。
7.4.2更新操作符
標準操作符
$inc:可以使用$inc操作符來增加或者減少指定數值(可以是1,-1,2.78)。

$set和$unset:如果要設定某個文件的特定的key值,就可以用$set。如果key鍵已經存在,它的值就會被重寫;否則,建立新的key值。$unset會從文件中刪除提供的key。不過在單個數組元素上使用$unset僅僅會設定元素的值為null而不是刪除元素。要完全刪除陣列元素,可以使用$pull、$pop。

$rename:修改key的名字。可以使用$rename。
$SetOnInsert:在upsert中,$setOnInsert只會在insert的時候起作用,修改的時候不起作用。
陣列更新操作符
$push、$pushAll、$each($each只能和$push、$addToSet一起使用)
$push在陣列後面追加值(可以往陣列中新增任意型別的值)。如果要在一次更新裡新增多個更新,可以組合使用$each和$push。

$slice:允許用來剪短陣列的大小、刪除舊的值。示例:執行後,temps陣列的值在推送資料到陣列後,從開頭刪除值,只留下4個數值。如果傳遞-1給$slice操作符,結果陣列是[96]。如果傳遞0,結果就是[]。如果傳遞正整數,會從陣列尾部開始刪除元素。比如使用了$slice:4,那麼結果是
$sort:排序
$addToSet:往陣列後面新增值。但是它只會新增陣列中不存在的值。($each只能和$push、$addToSet一起使用)
$pop:從陣列中刪除元素。可以傳1刪除最後一直值。可以傳-1刪除第一個值。

$pull和$pullall$pull是$pop的複查形勢。使用$pull,可以通過值精確指定要刪除的元素。$pullall與$pull的工作類似,允許提供要刪除值的列表。而且可以通過傳遞查詢條件來刪除。
定位更新(位置操作符$)
定位操作符允許我們通過原點選擇器來定位要更新的元素。例如:假如我們想設定第二行專案的數值為5,選擇器可以使用sku=10027,但是我們不知道是否存在,或者它在line_items中的下標是多少。我們可以使用位置操作符$來替換下標。
7.4.3findAndMofidy命令
findAndModify(query,update,remove,new,sort,fields,upsert)函式
  • query:查詢選擇器,預設為{}。
  • update:指定更新的文件,預設為{}。
  • remove:布林值,如果為true,則返回刪除的物件。預設為false。
  • new:布林值,如果為true,這返回修改後的文件。預設為false,返回修改前的文件
  • sort:指定排序的方向。使用findAndModify一次就修改一個文件。sort引數可以幫助控制要處理那個文件。
  • fields:返回部分欄位。
  • upsert:布林值,為true時,findAndMofidy作為upsert操作。如果文件不存在,就建立它。

7.4.4刪除
remove(selector)當selector為{}時,刪除整個文件。
7.4.5併發、原子性和隔離(隔離運算子$isolated:隔離其他操作,不允許其他操作交叉更新多個文件)
MongoDB鎖特性1)資料庫在記憶體裡保留文件的內部對映。對於非RAM的讀/寫,資料庫都會屈服於其他操作,直到文件加入記憶體。2)針對寫鎖。如果某個寫操作需要長時間來完成,那麼所有其他的讀和寫操作都會被阻塞。當前的解決方案允許這種長時間執行的操作為其他讀/寫讓路。當一個操作屈服時,它會暫停,並釋放鎖,後面再重新啟動。儘管對於鎖機制進行了優化,但是MongoDB在大量讀/寫的情況下還是會影響效能。一種好而簡單的避免問題的方法就是把高併發的集合儲存到單獨的資料庫裡面。當更新和刪除文件時,這種退讓機制可謂是喜憂參半。假設我們想在其他操作發生前更新或者刪除文件。此時我們可以使用專門的引數$isolated來保持操作獨立。不會讓路。
注意,如果使用$isolated半路失敗了,就不會有顯示的回滾操作。部分文件已經更新而其他部分還是原來的值。因為這些操作失敗在於非原子性。$isolated無法在分片集合中使用。
7.4.6更新效能注意事項
理解MongoDB如果更新磁碟上的文件可以幫助我們優化效能。首先要理解的事情就是更新發生的程度。理想情況下,更新影響磁碟上BSON文件的最小部分,因為這樣是最高效的。
更新磁碟上文件的三種方式
1)第一種更新是最高效的。當只更新文件的單個值並且BSON文件大小不會發送改變時才發生。比如在$inc操作符號中,$inc只增加整數,磁碟上的檔案大小不會改變。如果整數代表int,那麼在磁碟上只佔4個位元組,長整數和double型別會佔用8個位元組。修改這些數值不會改變儲存空間的大小,只需要把文件重新寫入磁碟即可。
2)更新是修改文件的大小和資料結構。BSON文件表示為位元組陣列。前4個位元組表示文件的大小。因此使用$push操作符修改文件,既增加文件的大小又修改結構。這需要在磁碟上重寫整個文件。雖然這樣還不是特別低效率,但是值得我們注意。如果有大型文件(假設4M),我們要在此文件裡新增陣列,那麼在服務端會是很大的工作。
3)更新是重寫一個文件。如果文件擴大,但是不能滿足現在的磁碟空間,則不僅僅需要重寫,還需要移動到新的空間裡。這種移動操作如果程序發生,則會非常昂貴。MongoDB會通過動態調整集合分配預留空間的填充因子(padding factor)來優化問題。這意味著當在一個集合中有許多的需要文件遷移更新時,內部預留空間的填充因子會增加。填充因子會乘以每個插入文件的大小來獲取額外的空間。這也許可以減少未來文件重新遷移的數量。