Reputation: 321
I'm trying to update an array using presave hooks available in mongoose. Im using this array for Audit Purposes and hence i wanted to enforce correct values using these middle wares
Here is my schema
const taskSchema = new mongoose.Schema({
id: { type: String, required: true },
status: { type: String, required: true },
code: { type: String, required: true }, // ENQUIRY
events:{
type:[{
status: {type: String, required: true},
date:{ type: Date, required: true}
}], required: false
},
assignedTo: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: false },
}, {timestamps:true});
The logic works great in save middleware hook.
taskSchema.pre('save', async function(next) {
try {
let event = {}
let now = Date.now();
event.status = this.status;
event.date = now;
this.events.push(event);
next();
} catch (error) {
console.log(error);
next(error);
}
});
Error when used in findOneAndUpdate hook
taskSchema.pre('findOneAndUpdate', async function(next) {
try {
let event={}
let now = Date.now();
event.status = this._update.status;
event.date = now;
this.events.push(event);
next();
} catch (error) {
console.log(error);
next(error);
}
});
I'm not sure what I'm missing here. Here is the error
TypeError: Cannot read property 'push' of undefined
I see that this.events is undefined.
How do I access that array to have it updated? I also should ignore whatever is sent in request.body.events
Thanks in advance.
Upvotes: 1
Views: 1166
Reputation: 11975
Refer to the Types of Middleware, save
is document middleware and findOneAndUpdate
is query middleware. And in notes, it says that:
Query middleware differs from document middleware in a subtle but important way: in document middleware,
this
refers to the document being updated. In query middleware, mongoose doesn't necessarily have a reference to the document being updated, sothis
refers to the query object rather than the document being updated.
So in your findOneAndUpdate
pre, this.events
is undefined
.
In your case, using below code may solve the problem:
taskSchema.pre('findOneAndUpdate', async function(next) {
try {
let event={}
let now = Date.now();
event.status = this._update.status;
event.date = now;
this._update['$push'] = {events: event};
next();
} catch (error) {
console.log(error);
next(error);
}
});
Upvotes: 3