MongoDB權威指南學習筆記03
章節:第三章 建立、更新及刪除文件
時間:2013-07-22
內容:
-
插入並儲存文件
-
使用insert方法:如
1db.foo.insert({
"bar"
:
"baz"
})
-
批量插入
-
批量插入能傳遞一個由文件構成的陣列給資料庫,且一次批量插入只是單個的TCP請求,無需處理大量的訊息頭,避免了許多零碎的請求所帶來的開銷
-
只有插入多個文件到一個集合時,才能提高效率,而不能用批量插入一次對多個集合執行操作
-
要是隻匯入原始資料,可以使用命令列工具,如mongoimport,而不是批量插入
-
-
插入:原理和作用
-
當執行插入時,使用的驅動程式會將資料轉換成BSON形式,然後將其送入資料庫
-
資料庫解析BSON,檢驗是否包含“_id”鍵並且文件不超過4MB
-
MongoDB在插入時不做別的資料校驗,也不執行程式碼,所以也就沒有注入式攻擊的可能,但副作用是允許插入無效的資料
-
-
-
刪除文件
-
刪除特定文件,如
1db.mailing.
list
.remove({
"opt-out"
: true})
-
刪除集合中的所有文件,如db.users.remove(),但不會刪除集合本身,原有的索引也會保留
-
刪除速度:通常刪除文件會很快,但若要清楚整個集合的文件,則直接刪除集合(然後重建索引)會更快,如db.drop_collection(“bar”)即是刪除集合bar
-
-
更新文件
-
更新文件的方法update有2個引數,一個是查詢文件,用來找出要更新的文件,另一個是修改器文件,描述對找到的文件做哪些更改
-
更新操作是原子的,若是兩個更新同時發生,先到達伺服器的先執行,接著執行另外一個
-
文件替換:
-
更新最簡單地情形就是完全用一個新文件替代匹配的文件,這適用於模式結構發生了較大變化時,如
1db.users.update({
"name"
:
"joe"
} , joe)
-
常見錯誤就是查詢條件匹配了多個文件,然後更新的時候由於第二次引數的存在就產生重複的“_id”值,資料庫會報錯,不做任何修改
-
-
使用修改器
-
通常文件只會有一部分要更新,利用原子的更新修改器,可以使得這種部分更新極為高效
-
更新修改器是種特殊的鍵,用來指定複雜的更新操作,比如調整、增加或者刪除鍵,還可以運算元組或者內嵌文件
-
使用修改器時,”_id”的值不能改變(而整個文件替換時是可以改變的);其他鍵值,包括其他唯一索引的鍵,都是可以更改的
-
“$set”修改器:“$set”用來指定一個鍵的值,若鍵不存在,則建立它,如
1db.users.update({
"name"
:
"joe"
},...{
"$set"
:{
"favorite book"
:
"green eggs and ham"
}})
也可以用“$unset”將鍵完全刪除,如
1db.users.update({
"name"
:
"joe"
},{
"$unset"
:{
"favorite book"
:
1
}})
-
“$inc”修改器:“$inc”修改器用來增加已有鍵的值,或者在鍵不存在時建立一個鍵,如
1db.games.update({
"game"
:
"pinball"
,
"user"
:
"joe"
},...{
"$inc"
:{
"score"
:
50
}})
“$inc”只能用於整數、長整數或雙精度浮點數,用在其它型別的資料上會導致操作失敗;另外“$inc”鍵的值必須為數字,不能使用字串、陣列或其他非數字的值
-
陣列修改器:用在值為陣列的鍵上,如果指定的鍵已存在,”$push”會向已有的陣列末尾加入一個元素,要是沒有就會建立一個新的陣列,如
1db.blog.posts.update({
"title"
:
"A blog post"
},{$push:{
"comments"
:...{
"name"
:
"joe"
,
"email"
:
"joe@example.com"
,
"content"
:
"nice post."
}}})
如果一個值不在陣列中再將其加進去,可以用“$ne”或“$addToSet”實現,如
123db.papers.update({
"authors cited"
:{
"$ne"
:
"Richie"
}},...{
"$push"
:{
"authors cited"
:
"Richie"
}})
或
db.users.update({
"_id"
:ObjectId(
"4b2d75476cc6113d5ee930164"
)},...{
"$addToSet"
:{
"emails"
:
"joe@gmail.com"
}})
將“$addToSet”和“$each”組合起來,可以新增多個不同的值,而用“$ne”和“$push”組合就不能實現,如
1db.users.update({
"_id"
:ObjectId(
"4b2d75476cc6113d5ee930164"
},{
"$addToSet"
:...{
"emails"
:{
"$each"
:[
"joe@php.net"
,
"joe@example.com"
,
"joe@python.org"
]}}})
若是把陣列看成佇列或棧,可以用“$pop”,此修改器可以從陣列的任何一端刪除元素,{$pop:{key:1}}從陣列末尾刪除一個元素,{$pop:{key:-1}}則從頭部刪除
有時需要基於特定條件來刪除元素,而不僅僅是依據位置,“$pull”可以做到,“$pull”會將所有匹配到的部分刪除,如
1db.lists.update({},{
"$pull"
:{
"todo"
:
"laundry"
}})
-
陣列的定位修改器:若是陣列有多個值,而我們只想對其中的一部分進行操作,有2種方法可以實現:通過位置或者定位操作符(“$”),如
12345#下標為0表示陣列的第一個元素
db.blog.update({
"post"
:post_id},...{
"$inc"
:{
"comments.0.votes"
:
1
}})
#在大多數情況下,不預先查詢文件就不能知道要修改陣列的下標,故MongoDB提供了定位操作符“$”,用來定位查詢文件已經匹配的元素,並進行更新
db.blog.update({
"comments.author"
:
"John"
},...{
"$set"
:{
"comments.$.author"
:
"Jim"
}})
#定位符只更新第一個匹配到的元素
-
修改器速度:$inc能就地修改,且不需要改變文件的大小,故執行非常快,而資料修改器可能更改了文件的大小,就會慢一些;MongoDB預留了些補白給文件,來適應大小變化,但若超出了原來的空間,則會分配新的空間,就會減慢速度,同時隨著陣列變長,MongoDB需要更長的時間來遍歷整個陣列,對每個陣列的修改也會慢下來。
-
-
upsert:是一種特殊的更新,若是沒有文件符合更新條件,就會以這個條件和更新文件為基礎建立一個新的文件,若匹配到了文件,則正常更新;update操作的第3個參數列示是否開啟upsert,如
1db.analytics.update({
"url"
:
"/blog"
},{
"$inc"
:{
"count"
:
3
}},true)
save Shell幫助程式:save是一個shell函式,可以在文件不存在時插入,存在時更新,只有一個引數:文件;若這個文件含有“_id”鍵,save會呼叫upsert,否則呼叫插入,如
123var x
=
db.foo.findOne()
x.num
=
42
db.foo.save(x)
-
更新多個文件:預設情況下,更新只能對符合匹配條件的第一個文件執行操作,若使所有匹配到的文件都得到更新,可以設定update的第4個引數為true,如
1db.users.update({birthday:
"10/13/1978"
},...{$
set
:{gift:
"Happy Birthday!"
}},false,true)
要知道多少文件被更新了,可以執行getLastError命令,鍵“n”的值就是要的數字,如
12db.count.update({x:
1
},{$inc:{x:
1
}},false,true)
db.runCommand({getLastError:
1
})
-
返回已更新的文件:用getLastError僅能獲得有限的資訊,並不能返回已更新的文件,可通過findAndModify命令實現,其呼叫方式和普通的更新略有不同,有點慢,因為它要等待資料庫的響應,如
1234567891011121314151617ps
=
db.runCommand({
"findAndModify"
:processes,
...
"query"
:{
"status"
:
"READY"
},
...
"sort"
:{
"priority"
:
-
1
},
...
"update"
:{
"$set"
:{
"status"
:
"RUNNING"
}}}).value
do_something(ps)
db.process.update({
"_id"
:ps._id},{
"$set"
:{
"status"
:
"DONE"
}})
#findAndModify命令中每個鍵的對應值:
findAndModify:字串,集合名
query:查詢文件,用來檢索文件的條件
sort:排序結果的條件
update:修改器文件,對所找到的文件執行的更新
remove:布林型別,表示是否刪除文件
new:布林型別,表示返回的是更新前的文件還是更新後的文件,預設是更新前的文件
#findAndModify命令的限制:
#"update"和"remove"必須有一個,也只能有一個;
#若匹配不到文件,則返回錯誤
#一次只能處理一個文件,也不能執行upsert操作,只能更新已有文件
-
瞬間完成:本章討論的3個操作(插入、刪除、更新)都是瞬間完成的,因為它們都不需要等待資料庫響應,只會受客戶端傳送的速度和網路速度的制約;這對於某些應用(如日誌記錄,分析資料等)是可以接受的,但對於某些應用(如付費系統)就不適用了
-
安全操作
-
若要完成電子商務系統,則需要一個“安全”版本,保證執行時檢查到了錯誤還可以重來;
-
安全的版本在執行完了操作後立即執行getLastError命令,來檢查是否執行成功,驅動程式會等待資料庫響應,然後適當地處理錯誤,一般會丟擲一個可被捕獲的異常
-
“安全”的代價就是效能,即便忽略客戶端處理異常的開銷,等待資料庫響應本身的時間比只傳送訊息的時間多一個數量級,所以,應用程式需要權衡資料的重要性(以及丟失後的後果)及速度需求
-
-
捕獲“常規”錯誤
-
安全操作也是一種除錯資料庫“奇怪”行為的好方法,這樣可以避免很多常見的資料庫使用錯誤
-
最常見的就是鍵重複的錯誤,即插入一個“_id”值已被佔用的文件
-
請求和連線
-
資料庫會為每一個MongoDB資料庫連線建立一個佇列,存放這個連線的請求
-
當客戶端傳送一個請求,會被放到佇列的末尾,只有佇列中的請求都執行完畢,後續的請求才會執行
-
所以從單個連線就可以瞭解整個資料庫,並且它總是能讀到自己寫的東西
-
每個連線都有獨立的佇列,要是開啟2個shell,就有2個資料庫連線,在一個shell中執行插入,之後在另一個shell中執行查詢不一定能得到插入的文件
-
使用Ruby、Python和Java驅動程式時要特別注意這種行為,因為這幾種語言的驅動程式都使用了連線池
相關文章
- HTTP 1.x 學習筆記 —— Web 效能權威指南HTTP筆記Web
- 《HTTPS權威指南》-公鑰基礎設施(PKI)學習筆記HTTP筆記
- 《IDA pro權威指南》閱讀筆記筆記
- MongoDB 學習筆記MongoDB筆記
- MongoDB學習筆記MongoDB筆記
- jQuery學習筆記03jQuery筆記
- 【MongoDB學習筆記】MongoDB 快速入門MongoDB筆記
- 讀書筆記【JS 權威指南】14.1 計時器筆記JS
- 《JAVA學習指南》學習筆記Java筆記
- CUDA C 程式設計權威指南 學習筆記:第二章 CUDA程式設計模型程式設計筆記模型
- 【MongoDB學習筆記】MongoDB索引那點事MongoDB筆記索引
- 提權學習筆記筆記
- Node學習筆記 Mongodb 和 Mongoose筆記MongoDB
- 《MongoDB權威指南》迷你書連載一-入門篇MongoDB
- HTML5與CSS3權威指南筆記案例1HTMLCSSS3筆記
- OpenResty學習筆記03:再探WAFREST筆記
- FPGA學習筆記03——UART串列埠FPGA筆記串列埠
- 《L03 Laravel 教程》 學習筆記Laravel筆記
- 基於docker 初學 MongoDb 學習筆記DockerMongoDB筆記
- 【MongoDB學習筆記】-使用 MongoDB 進行 CRUD 操作(下)MongoDB筆記
- 【MongoDB學習筆記】-使用 MongoDB 進行 CRUD 操作(上)MongoDB筆記
- MongoDB 學習筆記之常用 shell 命令MongoDB筆記
- 2020-11-14springboot學習筆記03Spring Boot筆記
- 【MongoDB學習筆記】手把手教你配置Python操作MongoDBMongoDB筆記Python
- React入門指南(學習筆記)React筆記
- Go 入門指南學習筆記Go筆記
- 留學指南權威乾貨與攻略!
- HTTP權威指南學習-第12章 基本認證機制HTTP
- 讀書筆記【JS 權威指南】14.2 瀏覽器定位和導航筆記JS瀏覽器
- JavaScript 日期權威指南JavaScript
- dotnet學習筆記-專題03-RabbitMQ-01筆記MQ
- Libev 官方文件學習筆記 – 03:常用 watcher 介面筆記
- JavaWeb學習筆記_Day03_JavaScript詳解Web筆記JavaScript
- Golang學習筆記-IDE安裝指南Golang筆記IDE
- 【區塊鏈學習】《區塊鏈學習指南》學習筆記區塊鏈筆記
- 《802.11無線網路權威指南-網路概論》-- 讀書筆記2筆記
- Java 13權威指南 - CodeFXJava
- JavaScript權威指南(6)——物件JavaScript物件
- [譯] JAVASCRIPT 日期權威指南JavaScript