恐れ入りますが、単一のアトミック更新では不可能です。両方の条件を満たすいくつかの更新操作を実行する必要があります。
更新ロジックを2つの異なる更新操作に分割します。最初の操作では、位置$
オペレーター
history
内の要素を識別するため 必要なアレイと$set
>
ここで、 findAndModify()
更新されたドキュメントを返すことができるため、この操作のメソッド。デフォルトでは、返されるドキュメントには、更新時に行われた変更は含まれていません。
したがって、この武器を装備して、次の操作で2番目のロジックをプローブできます。つまり、「history.name」と「history.organisation」の組み合わせがアレイに存在しない場合は更新します 。この2回目の更新操作では、 $push
要素を追加する演算子。
次の例は、上記の概念を示しています。最初は、クエリ部分とドキュメントが別々のオブジェクトとして更新されることを前提としています。
たとえば、既存の履歴配列と一致するドキュメントがある場合、1回の更新操作が実行されますが、ドキュメントが一致しない場合は、 findAndModify()
メソッドはnullを返します。2番目の更新操作でこのロジックを使用して、ドキュメントを配列にプッシュします。
var doc = {
"name": "Test123",
"organisation": "Rat"
}, // document to update. Note: the doc here matches the existing array
query = { "email": "[email protected]" }; // query document
query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
"query": query,
"update": {
"$set": {
"history.$.name": doc.name,
"history.$.organisation": doc.organisation
}
}
}); // return the document modified, if there's no matched document update = null
if (!update) {
db.users.update(
{ "email": query.email },
{ "$push": { "history": doc } }
);
}
一致するドキュメントに対してこの操作を行った後、コレクションをクエリすると同じ
が生成されます。db.users.find({ "email": "[email protected]" });
出力:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
}
]
}
次に、一致しないドキュメントについて考えます。
var doc = {
"name": "foo",
"organisation": "bar"
}, // document to update. Note: the doc here does not matches the current array
query = { "email": "[email protected]" }; // query document
query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
"query": query,
"update": {
"$set": {
"history.$.name": doc.name,
"history.$.organisation": doc.organisation
}
}
}); // return the document modified, if there's no matched document update = null
if (!update) {
db.users.update(
{ "email": query.email },
{ "$push": { "history": doc } }
);
}
このドキュメントのこのコレクションのクエリ
db.users.find({ "email": "[email protected]" });
降伏する
出力:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
},
{
"name" : "foo",
"organisation" : "bar"
}
]
}