- Document 文件插入
教程視頻
1.基本的插入語句結構
- 本文結構:
- 1.基本的插入語句結構
- 2.基本插入+ writeconcern
- 3.批量插入文檔 有可能使用 shell 來完成嗎?
- 4.insert 與 save操作區別
- 5.Document 文件刪除
- 6.使用justOne參數,來刪除一筆資料
1.基本的插入語句結構
db.collection.insert(
<documents>,
{
writeConcern: {
w:"majority",
wtimeout:5000
},
ordered: <boolean>
}
)
參數說明
* <document> 插入的文檔物件* writeConcern:文檔寫入等級設定,預設等級設 w:1
分成5點等級
w:-1 (嚴謹性:非常低);發生資料庫寫入錯誤一慮不回傳
w:0 (嚴謹性:低) ;只可以偵測到網路錯誤
w:1 (嚴謹性:中 預設等級)
w:1,j:1 (嚴謹性:高) ;在寫入日誌後才回傳處理過程。
w:2 (嚴謹性: 高 ) ;這個級別只在replica set的部署模式下生效
備註:w為設定寫入等級 ; j為日誌設定
關於writeConcern的選項大家可以看一下這篇文章寫的很清楚
http://kyfxbl.iteye.com/blog/1952941
基本的插入範例
db.employee.insert({ name:'canred', account:'canred', country:'tw', age:30 })
操作過程1
> use employee
switched to db employee
> db.employee.insert({name:'Canred',account:'Canred',country:'tw',age:30})
WriteResult({ "nInserted" : 1 })
> db.employee.insert({name:'emp1',account:'emp1',country:'us',age:28})
WriteResult({ "nInserted" : 1 })
> db.employee.insert({name:'emp2',account:'emp2',country:'us',age:28})
WriteResult({ "nInserted" : 1 })
> db.employee.insert({name:'emp3',account:'emp3',country:'us',age:28})
WriteResult({ "nInserted" : 1 })
> db.employee.find().pretty()
{
"_id" : ObjectId("54af3572540eca3abfc91415"),
"name" : "Canred",
"account" : "Canred",
"country" : "tw",
"age" : 30
}
{
"_id" : ObjectId("54af358a540eca3abfc91416"),
"name" : "emp1",
"account" : "emp1",
"country" : "us",
"age" : 28
}
{
"_id" : ObjectId("54af3591540eca3abfc91417"),
"name" : "emp2",
"account" : "emp2",
"country" : "us",
"age" : 28
}
{
"_id" : ObjectId("54af3598540eca3abfc91418"),
"name" : "emp3",
"account" : "emp3",
"country" : "us",
"age" : 28
}
>
基本插入+ writeconcern 範例
注意當你使用writeConcern的j:1的時侯,要先確定你用啟動mongod 要有先啟動日誌功能。
ex: mongod --dbpath ../data/mydb --journal
ex: mongod --dbpath ../data/mydb --journal
db.employee.insert({ name:'canred', account:'canred', country:'tw', age:30 },{
writeConcern:{ w:1, j:1
} })
2.批量插入文檔 有可能使用 shell 來完成嗎?
基本上我們想想應該與 插入單個文檔 相同,最多是 來 [ ] 陣列的符號來操作,沒錯就是
這樣,當然也可以使用 for 語句來 批量插入。
這樣,當然也可以使用 for 語句來 批量插入。
db.employee.insert( [ {name:"Data1"}, {name:"Data2"}, {name:"Data3"} ])
然後我們在使用 db.employee.find() 來看一下資料是不是多了3筆。
3.insert 與 save操作區別
若存在主鍵,insert() 不做操作,而save() 則更改原來的內容為新內容
若存在數據有一筆 { _id : 1, " name " : " n1 " }
insert({ _id : 1, " name " : " n2 " }) //會提示錯誤
save({ _id : 1, " name " : " n2 " }) //會把n1 改為n2
save 操作在 _id 找的得的狀況下,會執行更新操作;
若 _id 找不到的時侯會執行插入操作。
操作過程
> db.employee.insert({_id:'A',name:'Hello'})
WriteResult({ "nInserted" : 1 })
> db.employee.insert({_id:'A',name:'Hello'})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicat
e key error index: employee.employee.$_id_ dup key: { : \"A\" }"
}
})
> db.employee.save({_id:'A',name:'Hello 2'})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.employee.find()
{ "_id" : ObjectId("54af3572540eca3abfc91415"), "name" : "Canred", "account" : "
Canred", "country" : "tw", "age" : 30 }
{ "_id" : ObjectId("54af358a540eca3abfc91416"), "name" : "emp1", "account" : "em
p1", "country" : "us", "age" : 28 }
{ "_id" : ObjectId("54af3591540eca3abfc91417"), "name" : "emp2", "account" : "em
p2", "country" : "us", "age" : 28 }
{ "_id" : ObjectId("54af3598540eca3abfc91418"), "name" : "emp3", "account" : "em
p3", "country" : "us", "age" : 28 }
{ "_id" : ObjectId("54af3960540eca3abfc9141f"), "name" : "Data1" }
{ "_id" : ObjectId("54af3960540eca3abfc91420"), "name" : "Data2" }
{ "_id" : ObjectId("54af3960540eca3abfc91421"), "name" : "Data3" }
{ "_id" : "A", "name" : "Hello 2" }
> db.employee.save({_id:'B',name:'Hello 3'})
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "B" })
save({ _id : 1, " name " : " n2 " }) //會把n1 改為n2
save 操作在 _id 找的得的狀況下,會執行更新操作;
若 _id 找不到的時侯會執行插入操作。
操作過程
> db.employee.insert({_id:'A',name:'Hello'})
WriteResult({ "nInserted" : 1 })
> db.employee.insert({_id:'A',name:'Hello'})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicat
e key error index: employee.employee.$_id_ dup key: { : \"A\" }"
}
})
> db.employee.save({_id:'A',name:'Hello 2'})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.employee.find()
{ "_id" : ObjectId("54af3572540eca3abfc91415"), "name" : "Canred", "account" : "
Canred", "country" : "tw", "age" : 30 }
{ "_id" : ObjectId("54af358a540eca3abfc91416"), "name" : "emp1", "account" : "em
p1", "country" : "us", "age" : 28 }
{ "_id" : ObjectId("54af3591540eca3abfc91417"), "name" : "emp2", "account" : "em
p2", "country" : "us", "age" : 28 }
{ "_id" : ObjectId("54af3598540eca3abfc91418"), "name" : "emp3", "account" : "em
p3", "country" : "us", "age" : 28 }
{ "_id" : ObjectId("54af3960540eca3abfc9141f"), "name" : "Data1" }
{ "_id" : ObjectId("54af3960540eca3abfc91420"), "name" : "Data2" }
{ "_id" : ObjectId("54af3960540eca3abfc91421"), "name" : "Data3" }
{ "_id" : "A", "name" : "Hello 2" }
> db.employee.save({_id:'B',name:'Hello 3'})
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "B" })
- Document 文件刪除
1.刪除文檔的語句結構
db.collection.remove( {條件式},justOne )參數說明
* {條件式} :查詢條件
* justOne :true | false ,設定是否只刪除第一筆文檔
刪除所有文檔範例
可以使用 { } 來表示空的條件 ,也就是表示全部
db.employee.remove({})
根據修件刪除文檔
db.employee.remove( {name:'Canred'} )
在文檔中 若 name 為 Canred ,將全部刪除
使用justOne參數,來刪除一筆資料
db.employee.remove( {name:'Canred'} , true )
- 刪除collection
使用drop即可完成
1.刪除collection的語句結構
db.collection.drop()
- 下節教程將介紹 MongoDB的條件操作符
參考資料:來源於 http://kyfxbl.iteye.com/blog/1952941
mongodb有一個write concern的設置,作用是保障write operation的可靠性。一般是在client driver裡設置的,和db.getLastError()方法關係很大
一般來說,所有的mongo driver,在執行一個寫操作(insert、update、delete)之後,都會立刻調用db.getLastError()方法。這樣才有機會知道剛才的寫操作是否成功,如果捕獲到錯誤,就可以進行相應的處理。處理邏輯也是完全由client決定的,比如寫入日誌、拋出錯誤、等待一段時間再次嘗試寫入等。作為mongodb server並不關心,server只負責通知client發生了錯誤
這裡有2點需要注意:
1、db.getLastError()方法是由driver負責調用的,所以業務代碼不需要去顯式調用。這點後面還會專門提到
2、driver一定會調用db.getLastError()函數,但是並不一定能捕獲到錯誤。這主要取決於write concern的設置級別,這也是本文的主題
write concern:0(Unacknowledged)
此級別調用的時序圖如下:
driver調用了getLastError()之後,mongod立刻返回結果,然後才實際進行寫操作。所以getLastError()的返回值一定是null,即使之後的Apply發生了錯誤,driver也不知道。使用這個級別的write concern,driver的寫入調用立刻返回,所以性能是最好的,但是可靠性是最差的,因此並不推薦使用。在各平台最新版本的driver中,也不再以0作為默認級別。其實還有一個w:-1的級別,是error ignored,基本上和w:0差不多。區別在於,w:-1不會捕獲任何錯誤,而w:0可以捕獲network error
write concern:1(acknowledged)
此級別調用的時序圖如下:
和Unacknowledged的區別是,現在mongod只有在Apply(實際寫入操作)完成之後,才會返回getLastError()的響應。所以如果寫入時發生錯誤,driver就能捕獲到,並進行處理。這個級別的write concern具備基本可靠性,也是目前mongodb的默認設置級別
write concern:1 & journal:true(Jounaled)
此級別調用的時序圖如下:
Acknowledged級別的write concern也不是絕對可靠的。因為mongodb的Apply操作,是將數據寫入內存,定期通過fsync寫入硬盤。如果在Apply之後,fsync之前mongod掛了,或者甚至server掛了,那持久化實際上是失敗的。但是在w:1的級別下,driver無法捕獲到這種情況下的error(因為response在apply之後就已經返回到driver)
mongod解決這個問題的辦法是使用Journal機制,寫操作在寫入內存之後,還會寫到journal文件中,這樣如果mongod非正常down掉,重啟以後就可以根據journal文件中的內容,來還原寫操作。在64位的mongod下,journal默認是打開的。但是32位的版本,需要用--journal參數來啟動
在driver層面,則是除了設置w:1之外,再設置journal:true或j:true,來捕獲這個情況下的error
write concern:2(Replica Acknowledged)
這個級別只在replica set的部署模式下生效
這個級別下,只有secondary從primary完成了複製之後,getLastError()的結果才會返回。也可以同時設置journal:true或j:true,則還要等journal寫入也成功後才會返回。但是注意,只要primary的journal寫入就會返回,而不需要等待secondary的journal也寫入。類似的也可以設置w:3,表示至少要有3個節點有數據;或者w:majority,表示>1/2的節點有數據。一般小規模的集群就是3節點部署,所以配置w:2就可以了
建議
設置write concern級別,其實就是在寫操作的性能和可靠性之間做權衡。寫操作的等待時間越長,可靠性就越好。對於非關鍵數據,建議使用默認的w:1就可以了,對於關鍵數據,則使用w:1 & j:true比較好。這裡要注意,journal無論如何都是建議打開的,設置j:true,只是說driver調用getLastError()之後是否要等待journal寫入完成再返回。並不是說不設置j:true就關閉了server端的journal
沒有留言:
張貼留言