2

Mongo でサブドキュメントの配列内の要素を更新しようとすると、問題が発生します。コレクション「リソース」で次のドキュメントを検討すると

{
    "_id": 1,
    "resources": [
        {
            "resource_id": 1,
            "resource_list": ["item1","item2"]
        },
        {
            "resource_id": 2,
            "resource_list": ["item4","item3"]
        }
    ]
}

for"item4"のような他の値で更新したい"item5""resource_id" = 2

次のステートメントでエラーが発生しました:配列を含む対応するクエリ フィールドがないと、位置演算子を適用できません

db.resource.update({"resources.resource_id": 2, "resources.resource_list": "item4"}, {$set: {"resources.$.resource_list.$": "item5"}})

これに関するヘルプは大歓迎です。

4

2 に答える 2

1

位置演算子は、クエリで 1 回だけ使用できます。これは制限です。改善のためのオープン チケットがあります: https://jira.mongodb.org/browse/SERVER-831

この問題を解決する別の方法は、"item5" を配列にプッシュし、"item4" をプルすることです。このようなもの:

db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $pull: { "resources.$.resource_list": "item4" }, $push: { "resources.$.resource_list": "item5" } })

ただし、これも不可能で$pullあり$push、同じフィールドの同じクエリで使用することはできません。関連チケット: https://jira.mongodb.org/browse/SERVER-1050

私は2つの解決策を見ています。1 つは、2 つのクエリを実行することです。最初のクエリで「item5」をプッシュし、2 番目のクエリで「item4」をプルします。

db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $push: { "resources.$.resource_list": "item5" } });
db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $pull: { "resources.$.resource_list": "item4" } });

1 つのクエリで実行する場合は、mongo シェルを使用できます。このようなもの:

db.resource.find({ 'resources.resource_id': 2, 'resources.resource_list': 'item4' }).forEach( function(document) {
  for (var i in document.resources) {
    if (document.resources[i].resource_id == 2) {
      var index = document.resources[i].resource_list.indexOf('item4');
      document.resources[i].resource_list[index] = 'item5';
      db.resource.save(document);
    }
  }
})
于 2014-03-30T22:59:44.307 に答える
0

シンボル$は、検索の最後の配列の最後の位置のみを変更し、$addToSetまたはを使用$pushしてアイテムを追加できます...

 > db.resource.find()
    { "_id" : 1, 
      "resources" : [
                     { "resource_id" : 1,   
                       "resource_list" : [ "item1","item2" ] },     
                     { "resource_id" : 2, 
                       "resource_list" : [ "item4", "item3" ] } ] }

    > db.resource.update({"resources.resource_id": 2, 
                          "resources.resource_list": "item4"},
                         {$addToSet:{"resources.$.resource_list": "item5"}})

    > db.resource.find()
    { "_id" : 1, "resources" : [
                             { "resource_id" : 1, 
                               "resource_list" : [ "item1", "item2" ] },
                             { "resource_id" : 2, 
                               "resource_list" : [ "item4", "item3", "item5" ] } ] }

    > db.resource.update({"resources.resource_id": 2, 
                          "resources.resource_list": "item4"},
                         {$pull: {"resources.$.resource_list": "item4"}})

    > db.resource.find()
    { "_id" : 1, "resources" : [ 
                               { "resource_id" : 1,
                                 "resource_list" : [ "item1", "item2" ] },
                               { "resource_id" : 2,
                                 "resource_list" : [ "item3","item5" ] } ] }

しかし、同時に 2 つのクエリを実行したほうがよいでしょうか?

> db.algo.update({"resources.resource_id": 2,
                  "resources.resource_list": "item4"}, 
                 {$addToSet:{"resources.$.resource_list": "item5"},
                   $pull: {"resources.$.resource_list": "item4"}})

修飾子によるフィールド名の重複は許可されていません

于 2014-04-02T19:16:42.393 に答える