Мангуст Вставить несколько связанных записей одновременно - PullRequest
0 голосов
/ 18 мая 2018

В настоящее время у меня есть следующая, эффективная вставка по одной лирике на песню за раз:

SongSchema.statics.addLyric = function(songId, title, content) {
  const Lyric = mongoose.model('lyric');

  return this.findById(songId).then(song => {
    const lyric = new Lyric({ title, content, song });
    song.lyrics.push(lyric);
    return Promise.all([lyric.save(), song.save()]).then(([lyric, song]) => song);
  });
};

Однако я хотел бы обновить это до чего-то вроде следующего, где я передаю несколько текстов одновременно вмассив ...

SongSchema.statics.addLyric = function(songId, lyrics) {
  ...
};

Можно ли вставить все тексты сразу и при этом вернуть обновленную песню в graphql

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Честная точка. Вместо выполнения findById() тогда, вероятно, лучше использовать вместо него findByIdAndUpdate(), а также выполнить встроенное создание и вместо этого «связать» Обещание:

SongSchema.statics.addLyrics = function(songId, lyrics) {
  const Lyric = mongoose.model('lyric');

  return Lyric.insertMany(lyrics).then( lyrics =>
    this.findByIdAndUpdate(
      songId,
     { "$push": { "lyrics": { "$each": lyrics } } },
     { "new": true }
  );
};

Использует $each в качестве модификатора для $push, который принимает и массивирует и выполняет «атомарную» операцию для обновления документа. Это намного эффективнее и безопаснее, чем извлекать документ «затем», изменяя его перед обновлением.

Также, конечно, insertMany() делает ваш «массив» из lyrics как одну запись в отличие от «многих».

Альтернативный подход заключается в создании экземпляров на основе Array.map() и save() параллельно.

SongSchema.statics.addLyrics = function(songId, lyrics) {
  const Lyric = mongoose.model('lyric');

  lyrics = lyrics.map(lyric => new Lyric(lyric));

  return Promise.all([
    this.findByIdAndUpdate(
      songId,
      { "$push": { "lyrics": { "$each": lyrics } } },
      { "new": true }
    ),
    ...lyrics.map(lyric => lyric.save())
  ]).then(([song, ...lyrics]) => song);
};

Но первый подход действительно имеет меньше накладных расходов, и Promise.all() не будет отвечать, пока "все" обещания не будут решены в любом случае. Таким образом, вы действительно ничего не получите, не выполняя последовательных операций.


Альтернативный случай, конечно, состоит в том, что вместо сохранения «массива» связанных ObjectId значений в Song вы просто записали бы songId в записи Lyric.

Таким образом, схема стала бы чем-то вроде:

const lyricSchema = new Schema({
  title: String,
  content: String,
  songId: { type: Schema.Types.ObjectId, ref: 'Song' }
})

Тогда вставка просто

lyricSchema.statics.addLyrics = function(songId, lyrics) {
  return this.insertMany(lyrics.map(lyric => ({ ...lyric, songId })))
}

И в схеме Song вместо хранения массива, подобного этому:

songs: [{ type: Schema.Types.ObjectId, ref: 'Lyric' }]

Удалите это и замените на virtual ,

SongSchema.virtual.('songs', {
  ref: 'Lyric',
  localField: '_id',
  foreignField: 'songId'
});

А это значит, что вообще не нужно прикасаться к модели Song, так как вы можете просто вставить соответствующие данные без необходимости обновления массива.

Современные версии MongoDB действительно должны использовать $lookup для «запроса» этой информации в любом случае, и поддержание «массивов» в родительском элементе является чем-то вроде «анти-паттерна», который обычно должен следует избегать.

«Виртуальный», следовательно, «необязательный», и просто способ включить populate() для удобства.

0 голосов
/ 18 мая 2018

Лучший способ, который я знаю, таков:

lyrics = lyrics.map((lyric. i) => {lyric, songId: songI[i]});

SongSchema.collection.insertMany(lyrics, {'ordered': false},
(err, data) => {
    /*Do your stuff*/
});

Упорядоченное значение true выдает ошибку, если есть какие-либо повторяющиеся уникальные значения, и останавливается, если значение false, ошибка все еще выбрасывается, но вставка продолжается для неповторяющихся. Вам не нужно создавать новую схему, но таким образом проверки Momgoose также будут пропущены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...