'MongooseError: Query was already executed: in pre hook ['updateOne', 'findOneAndUpdate', 'update', 'updateMany'] using this.set in it
i'm using mongoose on v6.1.5.
i'm trying to create a mongoose hook on update function in order to track element that changed during the update, and make it has a public plugin.
schema.pre(['updateOne', 'findOneAndUpdate', 'update', 'updateMany'], async function () {
const updatedFields = this.getUpdate()
if (isNull(updatedFields)) {
return
}
const trackedFields = reduce(toPairs(updatedFields), (acc, [key, value]: [string, any]): any => {
if (includes(fieldsToTrack, key)) {
return [...acc, {
field: `${key}`,
changedTo: value,
at: Date.now()
}]
}
return acc
}, [])
const docUpdated = await this.model.findOne(this.getQuery())
const oldTrackedFields = docUpdated.get(`${name}`)
this.set({
[name]: [...oldTrackedFields, ...trackedFields]
}).catch((err) => console.log(err))
})
when running the code in my test :, i'm getting a strange error in the console which doesn't block the logic, but throw this:
it.only('should add modified field in __tokens if the field is tracked', async () => {
const schema = new Schema({
name: String,
price: Number,
toto: String
})
schema.plugin(mongooseTracker, {
fieldsToTrack: ['name', 'toto'],
name: '__tokens'
})
const Model = mongoose.model('test7', schema)
await Model.create({ price: 10, name: 'nom', toto: 'c est moi' })
await Model.findOneAndUpdate({ price: 10 }, { name: 'nouveauNom' })
const doc = await Model.findOne({ price: 10 })
expect(doc).toEqual(
expect.objectContaining({
'__tokens': expect.arrayContaining([
expect.objectContaining({
changedTo: 'nouveauNom',
field: 'name'
})
])
})
)
})
console.log
MongooseError: Query was already executed: test7.findOneAndUpdate({ price: 10 }, {
'$set': {
__to...
at model.Query._wrappedThunk [as _findOneAndUpdate] (/home/barder/xxx/mongoose-tracker/node_modules/mongoose/lib/helpers/query/wrapThunk.js:21:19)
at /home/barder/xxx/mongoose-tracker/node_modules/kareem/index.js:281:16
at _next (/home/barder/xxx/mongoose-tracker/node_modules/kareem/index.js:103:16)
at /home/barder/xxx/mongoose-tracker/node_modules/kareem/index.js:513:38
at processTicksAndRejections (node:internal/process/task_queues:78:11) {
originalStack: 'Error: \n' +
' at model.Query._wrappedThunk [as _findOneAndUpdate] (/home/barder/xxxx/mongoose-tracker/node_modules/mongoose/lib/helpers/query/wrapThunk.js:25:28)\n' +
' at /home/barder/xxx/mongoose-tracker/node_modules/kareem/index.js:281:16\n' +
' at _next (/home/barder/xxx/mongoose-tracker/node_modules/kareem/index.js:103:16)\n' +
' at /home/barder/xxx/mongoose-tracker/node_modules/kareem/index.js:513:38\n' +
' at processTicksAndRejections (node:internal/process/task_queues:78:11)'
}
i'm bugging it and found out, it seems that this.set is a duplicate query but i don't understand why ? is this because update function use $set so it make a duplicate call ? And Is using .clone is a good solution ?
Please feel free to give me/us feedback, I/We would greatly appreciate it.
Solution 1:[1]
You cannot run query twice in mangoose, but can clone and run it. Try to change
const doc = await Model.findOne({ price: 10 })
to
const doc = await Model.findOne({ price: 10 }).clone()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
