Обработка удаления документов с реляционными полями

#mongodb #mongoose

#mongodb #мангуст

Вопрос:

У меня есть 3 коллекции, пользователи, сообщения и комментарии.

Схема пользователя

 {
  posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }],
  likes: {
    comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
    posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }],
  }
}
  

Схема публикации

 {
  author: { type: Schema.Types.ObjectId, ref: 'User' },
  likes: [{ type: Schema.Types.ObjectId, ref: 'User' }],
  comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
}
  

Схема комментариев

 {
  author: { type: Schema.Types.ObjectId, ref: 'User' },
  post: { type: Schema.Types.ObjectId, ref: 'Post', },
}
  

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

Это функция, которую я использую, и она работает, и все отлично, но мне интересно, есть ли лучший способ решения этой проблемы?

 PostSchema.statics.deletePost = async function (postId) {
  const post = await this.findById(postId);
  const commentIds = post.comments;

  await Promise.all([
    User.findByIdAndUpdate(
      post.author,
      { $pull: { posts: postId } },
    ),
    User.updateMany(
      { _id: { $in: post.likes } },
      { $pull: { 'likes.posts': postId } },
    ),
    commentIds.map(async (commentId) => {
      const comment = await Comment.findById(commentId);

      User.findByIdAndUpdate(
        comment.author._id,
        { $pull: { comments: commentId } },
      );

      User.updateMany(
        { _id: { $in: comment.likes } },
        { $pull: { 'likes.comments': commentId } },
      );
    }),
    this.findByIdAndDelete(postId),
  ]);

  return post._id;
};
  

Комментарии:

1. Для чистого кода вы должны использовать await каждое отдельное обещание. И с массивом обещаний, которые вы должны использовать Promise.all . В противном случае ваш код в порядке.

Ответ №1:

Ваш код может создать несоответствие в базе данных.

при работе с несколькими документами используйте новую функцию ТРАНЗАКЦИЙ С НЕСКОЛЬКИМИ ДОКУМЕНТАМИ в MongoDB 4. Это означает, что либо все документы / коллекция будут обновлены, либо нет, если что-то пошло не так. Транзакция в целом будет атомарной.

или

Эффективно разрабатывайте схему, которая включает в себя все ваши 3 разные схемы. Потому что операция над одним документом является атомарной. читайте здесь https://docs.mongodb.com/manual/core/transactions /