2013-03-05 2 views
2

Я, похоже, столкнулся с блокпостом при использовании MongoDB и хотел бы знать, есть ли вокруг него все это без необходимости изменять мою структуру базы данных. Сейчас моя структура базы данных выглядит следующим образом:Mongo update of subdocs

Company= 
{ 
    _id:1, 
    properties:[ 
     { 
      property_id: 1 
      tags : [ 
      { 
       tag_id: 1 
       tag_value: 1000 
       channels: [ 
         { 
          channel_id:1 
          channel_name:"test1" 
         }, 
         { 
          channel_id:2 
          channel_name:"test2" 
         }] 
      }, 
      { 
       tag_id:2 
       tag_value: 2500 
       channels: [ 
         { 
          channel_id:2 
          channel_name:"test2" 
         }, 
         { 
          channel_id:3 
          channel_name:"test3" 
         }] 

      }] 
     }, 
     { 
      property_id: 2 
      tags : [ 
      { 
       tag_id: 3 
       tag_value: 500 
       channels: [ 
         { 
          channel_id:1 
          channel_name:"test1" 
         }, 
         { 
          channel_id:3 
          channel_name:"test3" 
         }] 
      }, 
      { 
       tag_id: 4 
       tag_value: 5000 
       channels: [ 
         { 
          channel_id:1 
          channel_name:"test1" 
         }]      
      }] 
     }]  
} 

Я бегу в проблему, где я не могу понять способ обновления конкретных tag_ids в собственности. Например, я хочу изменить значение tag_id 4 в свойстве 2 на 100. Или я хочу добавить канал в массив каналов в tag_id 3.

То, что я хотел бы сделать, было бы чем-то похожее на это:

db.company.update({_id:1, "properties.property_id":2, "tags.tag_id":4}, {"properties.$.tags.$.tag_value":100}); 

Однако я знаю, что это не поддерживается в текущей версии MongoDB, и она уже находится в JIRA. Поэтому мой вопрос заключается в том, что в любом случае необходимо обновить значение документа, где вам нужно указать два разных условия для доступа к нему. Я знаю, что могу делать properties.1.tags.0, однако я не буду знать порядок своих массивов, и мои запросы будут выполняться программно.

Любая помощь будет отличной, даже конформацией, которую я должен перестроить мой стол.

Спасибо

+2

Обновление массивы вложен в массиве имеет плохую поддержку в MongoDB; Я не знаю, как это сделать, не указывая числовые индексы, как вы упомянули. Ваш лучший вариант может состоять в том, чтобы переделать/сгладить схему, чтобы предотвратить это. – JohnnyHK

+0

Это то, что я думал, надеюсь, MongoDB скоро будет поддерживать поддержку вложенных документов. – Eumcoz

ответ

1

Свести массив может привести к довольно большим документам, потому что для каждого внутреннего элемента массива всех данных своего внешнего элемента должны быть повторены (и это для всех уровней).

Таким образом, если Свести это не вариант, здесь обходной путь, ожидая расширения функциональных возможностей в упомянутом Jira (SERVER-831):

  • прочитать документ в переменную
  • манипулировать массив
  • обновить документ, переписав весь массив

Учитывая ваши примеры, это будет выглядеть так:

doc = db.xx.findOne({_id:1}); 
doc.properties.forEach(function(p) { 
    if (p.property_id == 2) { 
     p.tags.forEach(function(t) { 
      if (t.tag_id == 3) { 
       t.tag_value = 100; 
      } 
      else if (t.tag_id == 4) { 
       newChannel = {}; 
       newChannel.channel_id = 5; 
       newChannel.channel_name = "test5"; 
       t.channels.push(newChannel); 
      } 
     }) 
    } 
}); 
db.xx.update({_id:1},{$set:{properties:doc.properties}}); 

В результате:

doc = db.xx.findOne({_id:1}) 
{ 
    "_id" : 1, 
    "properties" : [ 
     { 
      "property_id" : 1, 
      "tags" : [ 
       { 
        "tag_id" : 1, 
        "tag_value" : 1000, 
        "channels" : [ 
         { 
          "channel_id" : 1, 
          "channel_name" : "test1" 
         }, 
         { 
          "channel_id" : 2, 
          "channel_name" : "test2" 
         } 
        ] 
       }, 
       { 
        "tag_id" : 2, 
        "tag_value" : 2500, 
        "channels" : [ 
         { 
          "channel_id" : 2, 
          "channel_name" : "test2" 
         }, 
         { 
          "channel_id" : 3, 
          "channel_name" : "test3" 
         } 
        ] 
       } 
      ] 
     }, 
     { 
      "property_id" : 2, 
      "tags" : [ 
       { 
        "tag_id" : 3, 
        "tag_value" : 100, 
        "channels" : [ 
         { 
          "channel_id" : 1, 
          "channel_name" : "test1" 
         }, 
         { 
          "channel_id" : 3, 
          "channel_name" : "test3" 
         } 
        ] 
       }, 
       { 
        "tag_id" : 4, 
        "tag_value" : 5000, 
        "channels" : [ 
         { 
          "channel_id" : 1, 
          "channel_name" : "test1" 
         }, 
         { 
          "channel_id" : 5, 
          "channel_name" : "test5" 
         } 
        ] 
       } 
      ] 
     } 
    ] 
} 
+0

Я смог временно реструктурировать свою БД и превратил ее в более реляционную модель (которую мне не нравится делать в манго, но должен был заставить ее работать). Я надеюсь, что к моменту, когда я буду использовать вышеприведенную структуру, билет JIRA будет разрешен, последнее обновление говорит, что они надеются, что это произойдет в версии 2.6. Если нет, ваше решение кажется жизнеспособным решением, и я могу изучить его. Я отмечу это как принятое, так как это, вероятно, лучший вариант в настоящее время. – Eumcoz