2013-12-12 5 views
0

У меня есть эти данные в Монго:обновление MongoDB на JSON массива

{'_id':1, 
      'name':'Root', 
      'taskId':1, 
      'parentId':"", 
      'path':[1], 
      'tasks':[ {"taskId":3,parentId:1,name:'A',type:'task'}, 
         {"taskId":4,parentId:1,name:'D',type:'task'}, 
         {"taskId":5,parentId:4,name:'B',type:'task'}, 
         {'type':'project' , 'proRef':2}, 
         {"taskId":6,parentId:3,name:'E',type:'task'}, 
         {"taskId":7,parentId:6,name:'C',type:'task'}] 

      } 

Теперь я хочу, чтобы обновить TaskId 6 новыми данными JSON.

var jsonData = {"taskId":6,"name":'Sumeet','newField1':'Val1','newField2':'Val2'} 

запрос должен обновить, если поле доступно еще добавить новый ключ к существующему .Output Как

{"taskId":6,parentId:3,name:'Sumeet',type:'task','newField1':'Val1','newField2':'Val2'}] 

Я попытался несколько запросов, но полностью заменить JSON.

db.projectPlan.update({_id:1,'tasks.taskId':6},{$set :{'tasks.$':jsonData }}); 

Заранее благодарим за помощь! Sumeet

+0

Пожалуйста, укажите, если это не представляется возможным также. – Sumeet

+1

Это странно. Согласно [документации] (http://docs.mongodb.org/manual/reference/method/db.collection.update/#update-an-element-if-position-is-unknown), он должен работать. – Philipp

+0

Действительно, этот запрос заменит задачу только taskId 6. Он не объединит существующие данные с новыми данными. Ниже приведено мое решение о том, как можно объединить данные. – user152468

ответ

4

Вам необходимо преобразовать переменную jsonData во что-то, что можно передать для обновления. Вот пример, который делает именно то, что вы хотите с образца документа:

var updateData = {}; 
for (f in jsonData) { 
    if (f != "taskId") updateData["tasks.$."+f]=jsonData[f]; 
}; 
db.projectPlan.update({_id:1, 'tasks.taskId':6}, {$set:updateData}) 

Результат:

{ "_id" : 1, 
    "name" : "Root", 
    "taskId" : 1, 
    "parentId" : "", 
    "path" : [ 1 ], 
    "tasks" : [ 
    { "taskId" : 3, "parentId" : 1,  "name" : "A", "type" : "task" }, 
    { "taskId" : 4, "parentId" : 1,  "name" : "D", "type" : "task" }, 
    { "taskId" : 5, "parentId" : 4,  "name" : "B", "type" : "task" }, 
    { "type" : "project",  "proRef" : 2 }, 
    { "taskId" : 6, "parentId" : 3,  "name" : "Sumeet", "type" : "task", "newField1" : "Val1", "newField2" : "Val2" }, 
    { "taskId" : 7, "parentId" : 6,  "name" : "C", "type" : "task" } 
] } 
1

Вам нужно будет объединить документ вручную:

var jsonData = {"taskId":5,"name":'Sumeet','newField1':'Val1','newField2':'Val2'}; 

db.projectPlan.find({ _id: 1 }).forEach(
    function(entry) { 
    for (var taskKey in entry.tasks) { 
     if (entry.tasks[taskKey].taskId === jsonData.taskId) { 
     printjson(entry.tasks[taskKey]); 
     for (var taskSubKey in jsonData) { 
      entry.tasks[taskKey][taskSubKey] = jsonData[taskSubKey]; 
     } 
     printjson(entry.tasks[taskKey]); 
     } 
    } 
    db.projectPlan.save(entry); 
    } 
); 

Очевидно, что вы можете оставить прочь printjson заявления. Это просто означает, что слияние исходных задач с новыми задачами работает. Обратите внимание, что этот запрос будет обновлять только один документ, если поле _id уникально.

+0

Это совершенно не нужно - зачем вам смотреть на каждый документ? –

+0

Это решение рассматривает документы только с '_id: 1'. Обычно это поле имеет поддержку индекса. Таким образом, этот запрос будет быстрым. – user152468

+0

, то почему у вас есть все javascript для обновления, когда это можно сделать атомарно и поточно-безопасным на сервере? Если ваш код запускается дважды, он может потерять одно из изменений обновления, так как ваш запрос и ваше сохранение не являются атомарными. –

Смежные вопросы