2015-07-05 7 views
1

Я изо всех сил пытаюсь сохранить массив поддокументов. Просто не сэкономить:Mongoose save subdocument array

Передняя часть отправляет объект «День», который имеет массив заголовков, и каждый заголовок может иметь массив содержимого (который представляет собой схему мангуста).

var DaySchema = mongoose.Schema({ 
date: Date, 
startTime: Date, 
endTime: Date, 
title: String, 
order: Number, 
description: String, 
cohort: { 
    type: objId, 
    ref: 'cohort' 
}, 
instructors: [{ 
    type: objId, 
    ref: 'instructor' 
}], 
headings: [{ 
    title: String, 
    subTitle: String, 
    content: [{ 
     type:objId, 
     ref: 'content' 
    }] 
}] 
}); 


var ContentSchema = mongoose.Schema({ 
title: String, 
description: String, 
contentUrl: String, 
dueDate: Date, 
dateAssigned: Date, 
downloadUrl: String 
}); 

Это код, который я использую для отправки и отправки по дням со связанными объектами контента. Все работает, кроме сохранения содержимого. Когда я смотрю в оболочке mongo, каждое поле содержимого под заголовками выглядит так:

content: [] 

Любые мысли?

exports.putdaycontent = function (req, res) { 

var dayId = req.params.dayId; 
var headings = req.body.headings; 
var day = req.body; 

var updateDay = function() { 
    Day.update({_id: dayId}, day, {new: true, upsert: true}, function (err, day) { 
     if (err) 
      error.databaseError(req, res, err); 

     res.send(day); 
    }); 
}; 

if (headings) { 
    for (var x = 0; x < headings.length; x++) { 
     var h = headings[x]; 

     if (h.content) { 
      for (var y = 0; y < h.content.length; y++) { 
       var c = h.content[y]; 

       //If existing content update it 
       if (c._id && c._id.length > 0) { 
        Content.update({_id: c._id}, c, {new: true,upsert: true}, function (err, content) { 

        }); 
       } else { 
        var content = new Content(c); 
        h.content[y] = content; 
       } 

      } 
     } 
    } 
    day.headings = headings; 
    updateDay(); 

} else { 
    updateDay(); 
} 


}; 

exports.postdaycontent = function (req, res) { 

var headings = req.body.headings; 
var day = req.body; 
var cohortId = day.cohort._id; 

var postDay = function() { 
    var d = new Day(day); 
    console.log("CONTENT DAYS:",d); 
    d.save(function(err, newDay) { 
     if (err) 
      error.databaseError(req, res, err); 

     Cohort.findOneAndUpdate({_id: cohortId}, {$push: {days: newDay}}, {upsert: true}, function(err, newCohort) { 
      res.send({msg:"Successfully saved day to cohort"}); 
     }); 
    }); 
}; 

if (headings) { 
    for (var x = 0; x < headings.length; x++) { 
     var h = headings[x]; 

     if (h.content) { 
      for (var y = 0; y < h.content.length; y++) { 
       var c = h.content[y]; 

       var content = new Content(c); 
       h.content[y] = content; 
       console.log("CONTENT:",content); 

      } 
     } 
    } 
    day.headings = headings; 
} 

postDay(); 
}; 
+0

Асинхронные функции и синхронные петли плохо перемешиваются. Вы никогда не должны использовать '.update()' без '$ set' или подобных операторов. Все массивы ссылаются так, если фактические объекты уже существуют в другой коллекции, которые вы не создаете таким образом. Надеемся, что 'objId' был импортирован из' Schema.Types.ObjectId'. Это всего лишь несколько мыслей, которые приходят на ум с первого взгляда. –

+0

Я не уверен, что вы говорите, я должен * делать. Идея заключается в том, что пользователь создает День с X количеством заголовков и X количеством объектов контента в массиве содержимого. Затем они нажимают кнопку «Сохранить», а «back-end» обновляют объекты, которые необходимо обновить, и если они не существуют, она создает их. Я мог бы сохранить каждый объект контента отдельно, но как бы я мог убедиться, что они добавлены в массив в массиве Content внутри дня? – Spentak

ответ

0

Таким образом, я предположил, что Mongoose сохранит вспомогательные документы, если у них есть поле _id, но, по-видимому, нет. Решение сохранения массивов поддокументу является

  1. Создать новый объект модели для каждого суб-документа в массиве из JSON
  2. вызовов сохранить() на каждый объект
  3. родительский объект Безразлично» t заботиться о том, существует ли _d суб-документа или нет - он может просто сохранить его, прежде чем я даже сохраню сам суб-документ в базе данных.

Опять исправление было просто вызовом .save() в поддоку.

var content = new Content(c); content.save(); h.content[y] = content;

exports.putdaycontent = функция (Req, Рез) {

var dayId = req.params.dayId; 
var headings = req.body.headings; 
var day = req.body; 

var updateDay = function() { 
    Day.update({ 
     _id: dayId 
    }, day, { 
     new: true, 
     upsert: true 
    }, function (err, day) { 
     if (err) 
      error.databaseError(req, res, err); 

     res.send(day); 
    }); 
}; 

if (headings) { 
    for (var x = 0; x < headings.length; x++) { 
     var h = headings[x]; 

     if (h.content) { 
      for (var y = 0; y < h.content.length; y++) { 
       var c = h.content[y]; 

       //If existing content update it 
       if (c._id && c._id.length > 0) { 
        Content.update({ 
         _id: c._id 
        }, c, { 
         new: true, 
         upsert: true 
        }, function (err, content) { 

        }); 
       } else { 
        var content = new Content(c); 
        content.save(); 
        h.content[y] = content; 
       } 

      } 
     } 
    } 
    day.headings = headings; 
    updateDay(); 

} else { 
    updateDay(); 
} 


}; 
2

Это то, что я столкнулся несколько дней назад 22-ого июня 2015. Вот ссылка на вопрос я поднял на github https://github.com/Automattic/mongoose/issues/3093.


Теперь у вас есть два решения вашей проблемы.

  1. use .set() explicitly whenever you're modifying an array index

, например:

doc.someArray.set('3', 'changed'); 
doc.save(); 

здесь массив с именем someArray, изменяется и, таким образом, мы должны изменить его с помощью array.set метода.

Минусом: каждый отдельный Elementy массива должны быть установлены с помощью array.set(), так, например, 5 элементов внутри массива изменений вам нужно будет установить все из них с помощью array.set.


2. Отметьте массив как измененный, а затем сохраните его.

, например:

doc.array[3] = 'changed'; 
doc.markModified('array'); 

Это еще один способ, когда вы не можете явно вызвать метод array.set.например: в моем случае я использовал loadash для слияния документа и сохранил его, я не мог использовать array.set, поэтому я использовал array.markModified.

Benifit: Вам не нужно будет устанавливать каждый из элементов внутри массива, как указано выше, array.set.

Минус:

В случае каждого массива вы будете недом, чтобы пометить его как модифицированный перед сохранением. , например: если у вас есть 10 массивов в документе, вам нужно будет пометить их все как модифицировано перед сохранением: как,

doc.markModified('array1'); 
doc.markModified('array2'); 
doc.markModified('array3'); 


Там до сих пор нет опции в мангусте, чтобы отметить несколько массивов как измененные. Я попросил эту функцию в ссылке, которую я поделил выше.

Так что было бы что-то вроде:

profile.markAllModified(['arrayFirst','arraySecond','arrayThird','arrayFourth']); 

, который был добавлен к вехе 4.0.7 из мангуста, надеюсь, мы видим эту функцию в ближайшее время.

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