简体   繁体   中英

Mongoose deleteMany subdocuments and related subdocuments

I have a document Project with an array of subdocuments, with a schema Tasks. Tasks has an array of subdocuments with a schema Comments.

const projectSchema = new Schema({
  _id: Schema.Types.ObjectId,
  name: { type: String, required: true, unique: true },
  description: { type: String, default: '' },
  tasks: [{ type: Schema.Types.ObjectId, ref: 'Threads' }]
});
module.exports = mongoose.model('Project', projectSchema);

const tasksSchema = new Schema({
  projectId: { type: Schema.Types.ObjectId },
  _id: Schema.Types.ObjectId,
  title: { type: String, required: true },
  text: { type: String, required: true },
  comments: [{ type: Schema.Types.ObjectId, ref: 'Replies' }]
})
module.exports = mongoose.model('Tasks', tasksSchema);

const commentSchema = new Schema({
  taskId: { type: Schema.Types.ObjectId },
  _id: Schema.Types.ObjectId,
  text: { type: String, required: true }
})
module.exports = mongoose.model('Comment', commentSchema);

When I delete the Project document I want to delete every Task and every Comment relate to that project. To delete the Project I use findOneAndDelete so I set up a post middleware to delete all the Tasks

projectSchema.post('findOneAndDelete', function(doc, next) {
  mongoose.model('Tasks').deleteMany({ projectId: doc._id }).exec(); 
  next();
})

But now I don't know how to delete every comment, because deletemany returns an object with the result of the operation. Should I map the array of Tasks and call findOneAndDelete every time and then delete every single comment? It looks very inefficient for a lot of tasks.

How about embedding comments in post? since its one to many(not huge) relation. So in your code where you delete a project, you first delete all posts, which contain all the comments, only after it succeeds you delete the project. It will also benefit your read performance significantly because you just have to return a single post document instead of multiple(1post + many comment) documents.

Embedding post to project could also be possible, but depending on the size and number of possible posts, its probably better to keep it as a separate document. In this case you need some logic to ensure consistency. Here you could use mongodb's new feature, transaction. But I think for this case a transaction is not necessary.(Also I find it quite unstable for now) You could go with the "eventual consistency" method.

Basically you just delete all the posts related to a project and then delete a project. And then you run batches to check for any inconsistency.(check if there are any posts where its project doesnt exist. If it doestnt then delete the posts)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM