Ruby操作MongoDB(進階二)-CRUD操作

    MongDB數據庫的使用離不開CRUD操作。什麼是CRUD,就是創建文檔,讀取文檔信息,更新文檔和刪除文檔。

  1. 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_timeoutMongoDB在十分鐘間隔後自動關閉非活動的遊標,通過這個參數可以在服務器上讓遊標永久存活
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操作。該部分是數據庫的基礎部分。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章