Node.js Mongoose一次插入多个相关记录

Node.js Mongoose一次插入多个相关记录,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,目前,我有以下方法,每次有效地插入一首歌词: 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.

目前,我有以下方法,每次有效地插入一首歌词:

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

我所知道的最佳方式如下:

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

SongSchema.collection.insertMany(lyrics, {'ordered': false},
(err, data) => {
    /*Do your stuff*/
});
songs: [{ type: Schema.Types.ObjectId, ref: 'Lyric' }]
如果存在任何重复的唯一值,Ordered true将抛出错误,如果Ordered true为stop,则仍将抛出错误,但对于非重复的值,将继续插入。
您不需要创建新的架构,但这样也将跳过Momgoose验证。

Fair point。与其这样做,不如改为使用,还可以内联创建并“链接”承诺:

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 }
  );
};
它用作接受和数组的修饰符,并执行“原子”操作来更新文档。它比获取文档“然后”在更新之前对其进行修改更高效、更安全

当然,你的
歌词的“数组”也不是“很多”,而是作为一个单曲

另一种方法是基于
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
值的“数组”,而只需在
歌词
条目中记录
songId

因此,模式将变成如下所示:

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
模式中,不保留这样的数组:

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

SongSchema.collection.insertMany(lyrics, {'ordered': false},
(err, data) => {
    /*Do your stuff*/
});
songs: [{ type: Schema.Types.ObjectId, ref: 'Lyric' }]
将其拆下并更换为

这意味着根本不需要触摸
Song
模型,因为您可以简单地插入相关数据,而无需更新数组

不管怎样,现代MongoDB版本确实应该用来“查询”这些信息,并且在父级中维护“数组”有点“反模式”,这通常应该避免


因此,“虚拟”是“可选的”,只是为了方便起见启用
populate()

提供的答案中是否有您认为无法解决问题的内容?如果是,请对答案进行评论,以澄清哪些问题需要解决,哪些问题尚未解决。如果它确实回答了您提出的问题,那么请注意您提出的问题