2011-12-14 18 views
3

私は、次のコレクションがあります:私は明確な文書更新したい複数の更新

{ 
"Milestones" : [  
    {  "ActualDate" : null, 
    "Index": 0, 
    "Name" : "milestone1", 
    "TargetDate" : ISODate("2011-12-13T22:00:00Z"),   
    "_id" : ObjectId("4ee89ae7e60fc615c42e28d1")},   
    {  "ActualDate" : null,  
    "Index" : 0,  
    "Name" : "milestone2", 
    "TargetDate" : ISODate("2011-12-13T22:00:00Z"),   
    "_id" : ObjectId("4ee89ae7e60fc615c42e28d2") } ] 
, 
"Name" : "a", "_id" : ObjectId("4ee89ae7e60fc615c42e28ce") 
} 

を:_idが指定されている、Milestones._idとActualDateの一覧はnullです。 私は私のコードは次のようになりDOTNET:

var query = Query.And(new[] { Query.EQ("_id", ObjectId.Parse(projectId)), 
    Query.In("Milestones._id", new BsonArray(values.Select(ObjectId.Parse))), 
Query.EQ("Milestones.ActualDate", BsonNull.Value) });     

var update = Update.Set("Milestones.$.ActualDate", DateTime.Now.Date);  

Coll.Update(query, update, UpdateFlags.Multi, SafeMode.True); 

またはネイティブコードで:

db.Projects.update({ "_id" : ObjectId("4ee89ae7e60fc615c42e28ce"), "Milestones._id" : { "$in" : [ObjectId("4ee89ae7e60fc615c42e28d1"), ObjectId("4ee89ae7e60fc615c42e28d2"), ObjectId("4ee8a648e60fc615c41d481e")] }, "Milestones.ActualDate" : null },{ "$set" : { "Milestones.$.ActualDate" : ISODate("2011-12-13T22:00:00Z") } }, false, true) 

しかし、唯一の最初の項目が更新されています。

答えて

10

これは現時点では不可能です。アップデート中のフラグmultiは、複数のルートドキュメントの更新を意味します。位置演算子は、ネストされた配列項目を1つだけ一致させることができます。 mongodb jiraにはfeatureがあります。あなたは投票して待つことができます。あなたが希望し、各ネストされた配列IDの背面または複数のアトミック更新を保存するよう

現在のソリューションは、負荷ドキュメント、更新することができます。 mongodb.orgのドキュメントから

:アンドリューOrsichで答えたよう

現在$演算子のみ クエリ

+0

Thxを、アンドリュー。私はjiraの問題をupvotedしました。彼らがそれを実装することを願っています。 – 1gn1ter

+2

@ 1gn1ter:この機能は承認されましたが、スケジュールされていませんでした:( –

+2

4年後、それはサポートされていますか? –

1

で最初に一致した項目に適用され、これは瞬間のために可能ではありません、少なくともあなたが望む通りではありません。しかし、ドキュメントを読み込んだり、配列を変更したり、元に戻したりすることは、うまくいくでしょう。他のプロセスがその間に配列を変更する可能性があるため、変更を上書きする危険性があります。これを避けるために、オプティミスティックロックを使用できます。特に、配列が1秒ごとに変更されない場合は、

  1. 負荷新しい属性を含む文書を、:

    milestones_version
  2. を必要に応じてバックのMongoDBに保存し、今milestones_versionにクエリ制約を追加し、それをインクリメント配列を変更

    db.Projects.findAndModify({ 
        query: { 
         _id: your_project_id, 
         milestones_version: expected_milestones_version 
        }, 
        update: { 
         $set: { 
          Milestones: modified_milestones 
         }, 
         $inc: { 
          milestones_version: 1 
         } 
        }, 
        new: 1 
    }) 
    

マイルストーンアレイ(したがって、milestones_version)を別のプロセスで変更した場合は、このコマンドは何もせず、単にnullを返します。ドキュメントをリロードしてもう一度やり直す必要があります。配列が毎秒変更されない場合、これは非常にまれであり、パフォーマンスには影響しません。

この解決策の主な問題は、あなたがすべてのプロジェクト、一つずつ(なしmulti: true)を編集しなければならないということです。あなたはまだjavascript関数を書いて、それをサーバー上で実行させることができます。