私は最近この問題を抱えていました。#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 コレクションで呼び出された外部キー フィールドがあると仮定すると、一括更新ではないためです。次のことができる場合があります。
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フィールドunique
がある場合、フラグはエラーを発生させます。オプションはしませんuser_id
。sparse
nil 値があると思われる場合は、それを使用してください。
ターミナルからmongo 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/
ドキュメントは、最初の引数としてafilter
ではなく aが必要であることを示していますが、それらは同じようです..query
Address.collection.update_one( { user_id: user_id },
'$set' => { "address": 'the_address', upsert: true} )
PS: asなど{ "address": 'the_address' }
を含めずに update 句としてのみ記述すると、フィールドだけを更新するのではなく、ドキュメント全体が上書きされます。update operator
$set
address
編集#2
unique
orで索引付けする理由についてsparse
upsert
以下のリンクのセクションを見ると、次のことがわかります。
複数のアップサートを回避するには、フィルター フィールドが一意にインデックス化されていることを確認してください。
https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/