[英]How do I find documents in a mongo collection based on a date range in ruby
[英]How do I find out how many Mongo documents were actually inserted?
我有一個看起來像這樣的函數:
def insert_multiple_cakes(cake_list)
ensure_indexes
insert_list = cake_list.map { |cake| mongofy_values(cake.to_hash) }
inserted = db[CAKE_COLLECTION].insert(insert_list, w: 0)
return inserted.length
end
該函數的目標是將cake_list
所有蛋糕插入Mongo數據庫。 數據庫中已經存在的任何蛋糕都應忽略。 該函數應返回插入的蛋糕數,因此,如果cake_list
包含5個蛋糕,並且數據庫中已經存在其中2個蛋糕,則該函數應返回3。
我的問題是經過一個小時的實驗,我得出以下結論:
如果寫問題( :w
選項)為0,則insert調用將靜默忽略所有重復的插入,並且返回值包含所有輸入文檔,即使是未插入的文檔。 設置:continue_on_error
或:collect_on_error
,返回值始終包含所有文檔,並且收集到的錯誤列表始終為空。
如果寫關注為1,則如果輸入文檔之間有任何重復項,則插入調用將失敗,並顯示Mongo::OperationFailure
。 設置:continue_on_error
或:collect_on_error
,當有重復項時插入總是失敗。
因此,在我看來,實現此目標的唯一方法是遍歷輸入列表,搜索每個文檔並過濾掉已經存在的文檔。 我的應用程序一次將要處理(至少)數千個插入,所以我喜歡這個計划,就像我想跨過橋一樣。
我是否誤解了某些東西,還是Ruby客戶端可能被竊聽了?
為了說明這一點,此功能完全可以滿足我的要求並可以正常工作:
def insert_multiple_cakes(cake_list)
ensure_indexes
collection = db[CAKE_COLLECTION]
# Filters away any cakes that already exists in the database.
filtered_list = cake_list.reject { |cake|
collection.count(query: {"name" => cake.name}) == 1
}
insert_list = filtered_list.map { |cake| mongofy_values(cake.to_hash) }
inserted = collection.insert(insert_list)
return inserted.length
end
問題在於它執行的搜索量不勝枚舉,實際上只需要插入一個即可。
您可以執行以下操作( source ):
coll = MongoClient.new().db('test').collection('cakes')
bulk = coll.initialize_unordered_bulk_op
bulk.insert({'_id' => "strawberry"})
bulk.insert({'_id' => "strawberry"}) # duplicate key
bulk.insert({'_id' => "chocolate"})
bulk.insert({'_id' => "chocolate"}) # duplicate key
begin
bulk.execute({:w => 1}) # this is the default but don't change it to 0 or you won't get the errors
rescue => ex
p ex
p ex.result
end
ex.result
包含ninserted
以及每個失敗的原因。
{"ok"=>1,
"n"=>2,
"code"=>65,
"errmsg"=>"batch item errors occurred",
"nInserted"=>2,
"writeErrors"=>
[{"index"=>1,
"code"=>11000,
"errmsg"=>
"insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.cakes.$_id_ dup key: { : \"strawberry\" }"},
{"index"=>3,
"code"=>11000,
"errmsg"=>
"insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.cakes.$_id_ dup key: { : \"chocolate\" }"}]}
批量操作是必經之路。 我接受ranman的回答,但我認為我應該分享自己的最終代碼:
def insert_documents(collection_name, documents)
collection = db[collection_name]
bulk = collection.initialize_unordered_bulk_op
inserts = 0
documents.each { |doc|
bulk.insert doc
inserts += 1
}
begin
bulk.execute
rescue Mongo::BulkWriteError => e
inserts = e.result["nInserted"]
end
return inserts
end
def insert_cakes(cakes)
ensure_cake_indexes
doc_list = cakes.map { |cake|
mongofy_values(cake.to_hash)
}
return insert_documents(CAKE_COLLECTION, doc_list)
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.