Ruby操作MongoDB(進階)-CRUD操作
MongDB數據庫的使用離不開CRUD操作。什麽是CRUD,就是創建文檔,讀取文檔信息,更新文檔和刪除文檔。
key-value鍵值對標記
在MongoDB的Ruby驅動中,Key_value鍵值多次出現。而且有時會出現語法上的巧合,這取決於在使用的Ruby版本中如何申明。
在文檔創建步驟中,1.9及之後版本支持以下語法:
document={name:"Tom",age:20}。
但是如果你使用的是2.2或者更高的版本,你可以用雙引號將你的key包起來。如:
document={"name":"Tom","age":36}
如果你需要使用以"$"開始的MongoDB操作符,例如$set,$gte或者$near,你就必須使用雙引號將其閉合包裹。如果你使用2.2或者更好的Ruby版本,可使用如下寫法:
collection.update_one({name:"Tom"},{"$set":{age:42}})
如果你使用了更早的版本,使用HashRocket符號寫法
collection.update_one({name:"Tom"},{"$set"=>{age:42}})
使用strings和hashrockets來描述鍵值對在任意版本都適用
collection.update_one({"name"=>"Tom"},{"$set"=>{"age":42}})
2. 文檔創建-類比關系型數據庫的表格創建
這邊首先講述下,MongoDB中的文檔創建與關系型數據庫中表格創建的區別。在MongoDB中插入數據到集合的時候會自動創建文檔,而關系型數據庫表格的使用必須基於預先定義好表結構。MongoDB這種機制的好處在於可以不用預先知道文檔的結構。具有更好的兼容性。
在MongoDB中,在指定了具體的集合名字後,我們使用insert_one()和insert_many()兩個方法來向集合中插入文檔信息。插入操作返回一個包含了插入信息的Mongo::Operation::Result對象。在2.6及之後的MongoDB版本中,由於使用了寫命令,如果插入失敗,會拋出異常。2.4版本的MongoDB中,只有在插入黑白且寫的結果大於等於1時才會拋出異常。
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=>‘film‘)
result=client[:actors].insert_one({:name=>"TK"})
result.n #返回成功插入的文檔數
result=client[:actors].insert_many([
{:name=>"April"},{:name=>‘Tom‘}
])
result.insert_count #此處返回2,插入兩個文檔
3. Decimal128類型數字
在3.4版本中,Decimal128是一個BSON數據類型,它是基於decimal類型使用128比特的浮點數值,可以模擬精確的小數舍入,主要用於處理貨幣型數據,諸如金融和稅收的計算。
下面的例子在inventory集合中插入了一個包含Decimal128類型price域的文檔。
client=Mongo::Client.new([‘127.0.0.1:27017‘],:databse=>‘test‘)
price=BSON::Decimal128.new("428.59")
client[:inventory].insert_one({ "_id"=>1,
"item"=>"26 inch moitor"
"price"=>price
)
成功執行上述語句後,會生成下述文檔
{"_id":1,"item":"26 inch monitor","price":NumberDecimal("428.59")}
你也可以通過Ruby的BigDecimal對象創建一個Decimal128的對象,或者通過Decimal128.from_string().
big_decimal=BigDecimal.new(428.79,5)
price=BSON::Decimal128.new(big_decimal)
或者
price=BSON::Decimal128.from_string("428.79")
4. 文檔讀取 - 類比數據庫查詢數據
Ruby驅動類型通過find方法為集合的查詢提供了一個流暢的接口。find方法也有多個可用參數。查詢方法對於服務器來說是一個懶執行的方式。也就是說只有在叠代到對應結果時,在這時查詢才會被分配,並得到一個Mongo::Curor的返回。要想找出滿足查詢規則的所有文檔集合,通過find方法加上對應的過濾條件。
client = Mongo::Client.new([‘127.0.0.1:27017‘],:database="film")
client[:actors].find(:name=>"Tom").each do |document|
end
查詢參數,為了增加查詢時的參數,將一系列合適的方法串在find方法之後。Mongo::Collection::View是一個每次方法調用後會新生成的而且不可變的對象。
下表是當使用查詢方法時,可以使用的參數列表信息,還有相應方法的例子
參數 | 描述 |
allow_patrial_results | 共享集群模式下使用。如果集群中一個碎片宕機了,查詢出的結果就是從當前存活的碎片中獲取到的,這樣就可能只獲取到了結果的一部分。 |
batch_size(Integer) | 設置了每執行一次GETMORE操作,遊標返回的每批次的文檔個數 |
commont(String) | 查詢的註釋 |
hint(Hash) | 運行查詢時使用index hint優化查詢速度 |
limit(Integer) | 將返回的文檔的數量限制為所提供的值 |
max_scan(Integer) | 如果要進行全集掃描,設定文檔掃描的最大數值 |
no_cursor_timeout | MongoDB在十分鐘間隔後自動關閉非活動的遊標,通過這個參數可以在服務器上讓遊標永久存活 |
projection(Hash) | 設定結果中需要包含哪些信息,剔除哪些信息。例如client[:actors].find.projection(:name=>1) |
read(Hash) | 僅僅為當前查詢設定讀取首選項 client[:actors].find.read(:mode=>:secondary_preferred) |
show_disk_loc(Boolean) | 讓結果信息包含文檔的位置信息 |
skip(Integer) | 在查詢結果中跳過指定數目的文檔 |
snapshot | 使用快照模式進行查詢 |
sort(Hash) | 確定結果的排序規則 client[:actors].find.sort(:name=>-1) |
附件的查詢參數
4.1 count
獲取文檔操作返回的文檔總數目
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=‘film‘)
client[:actors].find(:name=>"Tom").count
4.2 distinct
去除結果中的重復值。可以類比SQL中的distinct操作
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=‘film‘)
client[:actors].find.distinct(:name)
4.3 tailable cursor
對於獲取到的結果集合,你可能需要在當前遊標已遍歷完所有結果後保持tailable cursor的打開狀態。下面的例子展示的是tailable cursor的使用方法。
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=>‘film‘)
client[:actors].drop
client[:actors,capped:true,size:512].create
result=client[:actors].insert_many([{:name=>"Tom"},{:name=>"Alex"}])
enum=client[:actors].find({},:cursor_type=>:tailable_wait).to_enum
while true
doc=enum.text
end
4.4 讀取首選項read preference
該參數設定了在副本集結構中,查詢或相應的命令操作應該發送給哪個候選成員。它由一個標識特定符號的節點,名為tag_sets的hashes數組,兩個時間選項(local_threshold,server_selection_timeout)組成。
local_threshold:最近的服務器和可以發送指令操作的可用服務器之間的時間延遲窗口的上限值(單位為秒)。默認值為0.015s或15ms。
server_selection_timeout:服務器選擇時,拋出異常前的阻塞時間。默認是30s,也就是30000ms。
更對關於服務器選擇算法,請參考後續博文。
讀取首選項參數可以作為客戶端連接的一個參數,也可以作為運行在數據庫之上的命令的參數
#客戶端連接時設定read preference參數,應用於所有的操作上
client = Mongo::Client.new([‘127.0.0.1:27017‘],read:{:mode=>:secondary,:tag_sets=>[{‘dc‘=>‘nyc‘}]})
#對於給定的命令設定讀取首選項參數
client.database.command({:collstats=>‘test‘},:read=>{:mode=>:secondary,:tag_sets=>[{‘dc‘=>‘nyc‘}]})
4.4.1 mode參數
模式參數的取值包含五種,也就是:primary,:secondary,:primary_prefered,:secondary_prefered,:nearest。具體的模式含義,請參考後續博文。
4.4.2 tag_sets參數
tag_sets參數是一串排序的標簽集合,用於控制服務器選舉時限制服務器的選舉資格。讀取首選項的標簽集(T)需要匹配服務器的標簽集(S);如果T是S的子集,也可是相應的服務器標簽集(S)匹配讀取首選項的標簽集(T).
例如,讀取首選項標簽集{dc:‘ny‘,rack:2}匹配了擁有標簽集{dc:‘ny‘,rack:2,size:‘large‘}的備選服務器。空的文檔標簽集可以匹配任何服務器,這是由於空的標簽集是任意標簽集的子集。這也意味著標簽集參數是[{}]時匹配所有的服務器。
5.文檔更新-類似於關系型數據庫的update操作
文檔更新可以選擇單個更新或多個一起更新方式,也可以選擇使用findAndModify()命令
5.1 update_one
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=>‘film‘)
actors=client[:actors]
#find後再modify
result=actors.find(:name=>‘Alex‘).update_one("$inc"=>{:plays=>1})
result.n
#直接update_one
reslut=actors.update_one({:name=>"Alex"},{"$inc"=>{:palys=>1}})
result.n
5.2 update_many
#find後再modify
result =actors.find([:label=>‘Hospital‘]).update_many("$inc"=>{:plays=>1})
result.modified_count
#直接update_many
reslut=actors.update_many({:label=>‘Hospital‘},{"$inc"=>{:plays=>1}})
result.modified_count
5.3 replace_one
#find後再replace
result =actors.find(:name=>‘Aphex Twin‘).replace_one(:name=>‘Richard‘)
result.modified_count
#直接replace_one
result=actors.replace_one({:name=>‘Aphex Twin‘},{:name=>‘Richard‘})
result.modified_count
通過$findAndModify方法來進行文檔更新和返回,可以使用find_one_and_delete,find_one_and_replace,find_one_and_update三個方法中的任意一個。你可以在更新操作發生前後均能等到對應的文檔信息。
5.4 find_one_and_delete
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=>‘film‘)
actors=client[:actors]
actors.find(:name=>‘Jose James‘).find_one_and_delete
5.5 find_one_and_replace
doc=actors.find(:name=>Jose James‘).find_one_and_replace(:name=>‘Jose‘)
doc
doc=actors.find_one_and_replace({:name=>‘Jose James‘},{:name=>‘Jose‘})
doc
doc=actors.find(:name=>‘Jose James‘).find_one_and_replace({:name=>‘Jose‘},:return_document=>:after)
doc
5.6 find_one_and_update
doc=actors.find(:name=‘Jose James‘).find_one_and_update(‘$set‘=>{:name=>‘Jose‘})
doc
doc=actors.find_one_and_update({:name=>‘Jose James‘},{‘$set‘=>{:name=>‘Jose‘}})
doc
5.7 find_one_and_replace
doc=actors.find(:name=>‘Jose James‘).find_one_and_replace({‘$set‘=>{:name=>‘Jose‘}},:return_document=>:after)
doc
doc=actors.find_one_and_replace({:name=>‘Jose James‘},{‘$set‘=>{:name=>‘Jose‘}},return_document=>:after)
doc
6 文檔刪除操作Deleting
6.1 delete_one 單個刪除
client=Mongo::Client.new([‘127.0.0.1:27017‘],:database=>‘film‘)
actors=client[:actors]
#find後再刪除
result=actors.find(:name=>‘Bob‘).delete_one
result.deleted_count
#直接delete
result=actors.delete_one({:name=>‘Bob‘})
result.deleted_count
6.2 delete_many 多個刪除
result=actors.find(:label=>‘Mute‘).delete_many
result.deleted_count
result=actors.delete_many({:label=>‘Mute‘})
result.deleted_count
至此,Ruby操作MongoDB的CRUD操作。該部分是數據庫的基礎部分。
本文出自 “techFuture” 博客,謝絕轉載!
Ruby操作MongoDB(進階)-CRUD操作