2016-12-08 16 views
2

はのは、私はこのような文書があるとしましょう戻る:配列内のサブ文書の中のMongoDBアップサートおよび更新サブドキュメント

{ 
    "_id" : ObjectId(1234), 
    "name": "foo", 
    "bars": [ 
     { "name": "n1", "myBool": true }, 
     { "name": "n2", "myBool": false }, 
     { "name": "n3", "myBool": false } 
    ] 
} 

私はname(または全体サブドキュメントを見つけたいと思い、それは本当に問題ではありません)そして、barsの最初のサブ文書のmyBooltrueは、アトミック操作で与えられた_idの場合は現在falseです。たとえば、上記のデータを使用して、n2を返信し、_idObjectId(1234)に等しい文書のmyBooltruen2に設定したいとします。

どうすればこの問題を解決できますか?

答えて

2

findAndModifyコマンドをパラメータnewをtrueに設定して実行すると、元のデータではなく変更されたドキュメントが返されます。

アップデートでは、配列内の要素の位置を明示的に指定せずに更新する配列内の要素を識別する$ positional operatorを使用する必要があります。これを機能させるには、配列フィールドをクエリドキュメントの一部として表示する必要があります。

var result = db.runCommand({ 
    "findAndModify": "collection", 
    "query": { 
     "_id" : 1234, 
     "bars.myBool": false 
    }, 
    "update": { "$set": { "bars.$.myBool": true } }, 
    "new": true 
}); 
printjson(result.value); 

サンプル出力は

{ 
    "_id" : 1234, 
    "name" : "foo", 
    "bars" : [ 
     { 
      "name" : "n1", 
      "myBool" : true 
     }, 
     { 
      "name" : "n2", 
      "myBool" : true 
     }, 
     { 
      "name" : "n3", 
      "myBool" : false 
     } 
    ] 
} 
+0

サブドキュメントの代わりに、文書全体を返すだけに微調整することができますか?私。どのサブ文書(名前)が変更されたのか知りたい。 – Johan

+1

残念ながら、アトミックアップデートではできません。配列を手動でフィルタリングする必要があります。つまり、2つの別々のクエリを実行する必要があります。1. "_id"の文書を見つけるには:1234、 "bars.myBool":false } 'そして、 。 2つの文書を取得すると、 'bars'配列のサブ文書の違いを見つけることができます。 – chridam

+0

残念ながら、2つ以上のスレッドがこれを同時に実行できるため、これは非常に並行した環境では機能しません。私。別のスレッドが "myBool"も更新していて、変更されたスレッドがどれかわからないので、結果を最初に読み込んで比較することはできません。 – Johan

0

更新: はこの作品の周りに、しかし果たすかもしれませ

出力文書には、コマンドの返されたドキュメントが含まれているvalueフィールドを持っていますあなたの要件は、次のクエリを使用します。

db.test.findAndModify({ 
    query: { "_id": 123456, "bars.myBool": false}, 
    update: {$set: {"bars.$.myBool": true}}, 
     fields: { 
      "bars": {$elemMatch: {"myBool" : false }} 
     } 
}) 

改ざんは、変更される元の文書を返します。

それはあなたが

を更新されている文書を取得することができます

{ 
    "_id" : 123456, 
    "bars" : [ 
     { 
      "name" : "n2", 
      "myBool" : false 
     } 
    ] 
} 

を返すのでresultは、あなたが名前を得ることができ、それを通して単一のサブ文書、との配列が含まれています。

続きを読む程度findAndModify

+0

ありがとう、しかし私の問題は私が名前を知らないということです。私はアトミック操作で名前(およびmyBoolを更新する)を取得したいと思います。 – Johan

+0

申し訳ありませんが、OPを理解していないため、一度更新された答えを確認してください。 –

関連する問題