最近我有這個問題。有一個內置的方式,但它不同於活動記錄'#find_or_initialize_by
或#find_or_create_by
方法。
就我而言,我需要批量插入記錄並更新或創建如果沒有找到,但我相信同樣的技術即使你不是批量插入使用。
# returns an array of query hashes:
def update_command(users)
updates = []
users.each do |user|
updates << { 'q' => {'user_id' => user._id},
'u' => {'address' => 'address'},
'multi' => false,
'upsert' => true }
end
{ update: Address.collection_name.to_s, updates: updates, ordered: false }
end
def bulk_update(users)
client = Mongoid.default_client
command = bulk_command(users)
client.command command
client.close
end
,因爲你沒有批量更新,假設你有你的地址集合稱爲user_id
一個外鍵字段。你也許能夠:
Address.collection.update({ 'q' => {'user_id' => user._id},
'u' => {'address' => 'address'},
'multi' => false,
'upsert' => true }
將匹配對user_id
,更新給定的領域時發現(address
在這種情況下),或創建一個新的未發現的時候。
對於這項工作,有1個雖然最後關鍵的一步。 您必須使用特殊標誌將索引添加到您的Address集合。
要查詢上的字段(user_id
在這種情況下) 必須任{ unique: true }
或{ sparse: true }
標誌索引。如果您有2個或更多無nil user_id
字段,則unique
標誌將產生錯誤 。 sparse
選項不會。 如果您認爲您可能沒有任何值,請使用該值。通過終端
訪問您的蒙戈DB
show dbs
use your_db_name
檢查,如果該地址收集已經有您正在尋找
db.addresses.getIndexes()
如果已經對user_ID的索引的索引,您可能想要刪除它 db.addresses.dropIndex({ user_id: 1})
並使用以下標誌再次創建它:
db.addresses.createIndex({ user_id: 1}, { sparse: true })
https://docs.mongodb.com/manual/reference/method/db.collection.update/
編輯#1
似乎有Mongoid 5的變化..而不是User.collection.update
可以使用User.collection.update_one
https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/
該文檔顯示你作爲fi需要一個filter
而不是一個query
第一個參數,但他們似乎是相同..
Address.collection.update_one({ user_id: user_id },
'$set' => { "address": 'the_address', upsert: true})
PS: 如果你只寫{ "address": 'the_address' }
爲您的UPDATE子句,而不包括update operator
如$set
,整個文件將被覆蓋,而不是更新只是address
領域。
編輯#2
關於爲什麼您可能希望索引與unique
或sparse
如果你看一下在鏈接波紋管的upsert
部分中,您將看到:
爲了避免多個upserts,確保過濾器字段是唯一的索引 。
https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/
爲什麼你需要一個獨特的或稀疏索引? –
因爲你將匹配那個關鍵字來'更新'如果找到或'插入'如果沒有找到。如果你沒有一個唯一的或稀疏索引,你仍可以更新的第一個匹配的文件或用'更新所有匹配的文檔{多:真}'標誌。 請參閱編輯#2。 – Shiyason
我不需要索引來確保唯一值。 –