Reputation: 4942
I have a case where I'm using mongoose .pre('save')
hooks to denormalize some data to other documents. I'm struggling with a good solution to update data and keep denormalization consistent across the database. If I want to update a document, I consider three alternatives:
The reason why I prefer not to do this is that it doesn't trigger my mongoose middleware that I need to denormalize my data.
.post('update')
hooksThe problem with this method is for one that I can't tell in the hook which fields have been updated, right? So I should then assume all fields have been updated and denormalize data across the entire database? Seems very intense.
It seems convenient, but poses a risk to overwriting data, i.e. if the document was to be updated from elsewhere in the 'between'-moment.
in models/car.model.js:
const { mongoose } = require('mongoose');
const Schema = mongoose.Schema;
const Manufacturer = require('./manufacturer.model.js');
const CarSchema = new Schema({
name: String,
manufacturer: {
type: {
_id: Schema.Types.ObjectId,
name: String,
},
},
});
CarSchema.pre('save', async function(next) {
/*
if (this.isModified('name')) {
await Manufacturer.findByIdAndUpdate(this.manufacturer, {
$set: {
car-name: this.name,
},
});
}
*/
if (this.isModified('manufacturer') {
const manufacturer = await Manufacturer.findOne({
_id: this.manufacturer._id,
}, {
name: 1,
});
this.manufacturer.name = manufacturer.name;
}
});
in controllers/car.controller.js:
app.patch('/:id', async function (req, res, next) {
const car = await Car.findById(req.params.id);
// Bad solution, helps please
for (var key in req.body) {
car[key] = req.body[key];
}
await car.save();
res.sendStatus(200);
});
Any solution that could bring the best of both worlds?
Upvotes: 0
Views: 2487
Reputation: 3872
Number 2 is a viable option, you can just do this.getUpdate()
using context: 'query'
in your post('update')
hook. Also, what's wrong with performing an atomic update, like updateOne()
?
Also, glad to see you're using async middleware, but just FYI you don't need next()
if you have an async hook function.
Upvotes: 2