回答:
MongoDB 2.4以降、アトミックのfindOrCreate
ような操作で一意のインデックス(またはその他の回避策)に依存する必要がなくなりました。
これは、おかげでオペレータドキュメントを挿入するときにのみ起こるはずの更新を指定することができます2.4に新しいです、。$setOnInsert
これをupsert
オプションと組み合わせると、を使用findAndModify
して、アトミックのfindOrCreate
ような操作を実行できます。
db.collection.findAndModify({
query: { _id: "some potentially existing id" },
update: {
$setOnInsert: { foo: "bar" }
},
new: true, // return new doc if one is upserted
upsert: true // insert the document if it does not exist
})
$setOnInsert
のみ挿入された文書に影響し、既存の文書が発見された場合、何も変更は行われません。ドキュメントが存在しない場合は、指定された_idでドキュメントをアップサートし、挿入のみのセットを実行します。どちらの場合も、ドキュメントが返されます。
db.collection.findAndModify({query: {_id: "some potentially existing id"}, update: {$setOnInsert: {foo: "bar"}}, new: true, upsert: true})
)のインサート(アップサート)は編ドキュメントを、あなたが使用することを検討すべきですdb.collection.updateOne({_id: "some potentially existing id"}, {$setOnInsert: {foo: "bar"}}, {upsert: true})
。ドキュメントが既に存在する{"acknowledged": true, "matchedCount": 0, "modifiedCount": 0, "upsertedId": ObjectId("for newly inserted one")}
場合、ドキュメントが挿入されると戻ります{"acknowledged": true, "matchedCount": 1, "modifiedCount": 0}
。
findOneAndUpdate
、findOneAndReplace
またはfindOneAndDelete
最新のドライバー(>バージョン2)を使用して、廃止予定のfindOneAndUpdateを使用しますfindAndModify
。新しい方法は3つの引数を取りfilter
、update
(新しいオブジェクトの挿入すべきデフォルトのプロパティが含まれている、)オブジェクト、そしてoptions
どこにアップサート操作を指定する必要があります。
promise構文を使用すると、次のようになります。
const result = await collection.findOneAndUpdate(
{ _id: new ObjectId(id) },
{
$setOnInsert: { foo: "bar" },
},
{
returnOriginal: false,
upsert: true,
}
);
const newOrUpdatedDocument = result.value;
少し汚れていますが、挿入するだけです。
キーに一意のインデックスが付いていることを確認してください(_idを使用しても問題ありませんが、すでに一意です)。
このようにして、要素がすでに存在する場合は、キャッチできる例外を返します。
存在しない場合は、新しいドキュメントが挿入されます。
更新:MongoDBドキュメントでのこの手法の詳細な説明
collection.findAndModify({_id:'theId'}, <your sort opts>, {$setOnInsert:{foo: 'bar'}}, {new:true, upsert:true}, callback)
ます。ドキュメントを