Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.92k stars 3.84k forks source link

[Help] post 'save' hook not fired when calling .save() on document #10479

Closed DaliborTrampota closed 3 years ago

DaliborTrampota commented 3 years ago

Do you want to request a feature or report a bug? probably not a bug but I dont know how to get my post 'save' hook called on document save()

What is the current behavior? post hook 'save' doesnt trigger

If the current behavior is a bug, please provide the steps to reproduce.

tagSchema.post('save', (error, doc, next) => {
    console.log('postSave', error, doc, next)

    next()
})

//elsewhere
const allTags = await this.db.tag.find();
let tag = allTags[0] //just for example I have some other code in between
tag.save()//this doesnt trigger the post 'save' hook

What is the expected behavior? console log saying: 'postSave', error if any, the doc and [Function (anonymous)]

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version. node v14.15.4 mongoose 5.13.2 mongo I again dont know I'm running mongo atlas

Also is there discord support server so I dont have to spam the issues here?

edit:

const { Schema, model } = require('mongoose');

const tagSchema = new Schema({
    _id: String,
    name: String,//Tag trigger
    createdAt: Number,
    ownerID: String,
    guildID: String,
    uses: Number,
    data: String
});

tagSchema.post('save', (error, doc, next) => {
    console.log('postSave', error, doc, next)

    next()
})

tagSchema.post('updateOne', (error, doc, next) => {
    console.log('postUpdate', error, doc, next)
    next()
})

module.exports = model('Tag', tagSchema);

//when creating new tag post save hook is triggered just fine
module.exports.new = (name, data, message) => {
    return new Promise((resolve, reject) => {
        let newTag = new module.exports({ name, data, guildID: message.guild.id, ownerID: message.userID, createdAt: Date.now(), uses: 0 })
        newTag.save().then(resolve).catch(reject);
    })
}
DaliborTrampota commented 3 years ago

And is there a hook that gets triggered on every action? I just want to handle errors in one place preferably or separately for each model. But now I have to handle it everywhere I use save, findOneAndUpdate, updateMany and many more

DaliborTrampota commented 3 years ago

Actually I found what the issue was. Its because I have the error there. I thought it would trigger with or without the error depending on the situation but it triggers only on error. So is there a way to make just one save hook for both success and error?

Kamikadze4GAME commented 3 years ago

Hello @DaliborTrampota

There is mongoosejs slack.

Post hook (middleware) with 3 arguments is Error handling middleware. It will be called only if any error was occurred during query execution. To handle successful execution just remove first argument from your callback function:

tagSchema.post('save', (doc, next) => {...})

So is there a way to make just one save hook for both success and error?

No, there is no way to make one post save hook for both success and error.

DaliborTrampota commented 3 years ago

Hello @Kamikadze4GAME and thank you for the info.

I have one more question I couldn't find answer to. The error handling middleware has very short stack trace. So when I log the error there is not the line of the .save() call where the error initiated. There is only stack trace of stuff that is going inside mongoose src code. Is there a way to get where the error initiated?

Thanks.

Kamikadze4GAME commented 3 years ago

Look at "Better stack trace" section

DaliborTrampota commented 3 years ago

Look at "Better stack trace" section

I did and tested it out. It works fine but only without the post hooks

This is error from error handling middleware

MongooseError: document must have an _id before saving
    at E:\GitHub\KokNut\KokNut Official\node_modules\mongoose\lib\model.js:290:18
    at processTicksAndRejections (internal/process/task_queues.js:75:11)

this is from .catch() on the same method

MongooseError: document must have an _id before saving
    at E:\GitHub\KokNut\KokNut Official\node_modules\mongoose\lib\model.js:290:18
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
From previous event:
    at promiseOrCallback (E:\GitHub\KokNut\KokNut Official\node_modules\mongoose\lib\helpers\promiseOrCallback.js:31:10)
    at Mongoose._promiseOrCallback (E:\GitHub\KokNut\KokNut Official\node_modules\mongoose\lib\index.js:1149:10)
    at model.Model.save (E:\GitHub\KokNut\KokNut Official\node_modules\mongoose\lib\model.js:502:35)
    at E:\GitHub\KokNut\KokNut Official\src\Schema\Tag.js:31:16
From previous event:
    at Function.module.exports.new (E:\GitHub\KokNut\KokNut Official\src\Schema\Tag.js:29:12)
    at Tags.run (E:\GitHub\KokNut\KokNut Official\src\Commands\Fun\Tag.js:36:20)
    at async module.exports (E:\GitHub\KokNut\KokNut Official\src\CustomEvents\command.js:27:5)

both of those errors were logged from the exact same part of the code at the same time

as you can see the error handling middleware error doesnt provide the from previous event part of the stack trace. Is there a way to get it?

DaliborTrampota commented 3 years ago

:( is there a discord support server? official or unofficial. doesn't matter really :)

Kamikadze4GAME commented 3 years ago

Hello @DaliborTrampota

I sent you link to official mongoosejs slack few days ago: mongoosejsteam.slack.com

IslandRhythms commented 3 years ago

@DaliborTrampota there is a support server for discord.js

DaliborTrampota commented 3 years ago

@DaliborTrampota there is a support server for discord.js

I'm master of discord.js I live from making discord bots on fiverr. I need support for the advanced stuff of mongoose because the documentation is confusing most of the time. But thanks anyways. I still haven't figured out how to get longer stack trace for the error handling middleware but I can live with that just it would be cool ti get the exact place where the error originated. I could just parse the error stack then and filter the important bits

vkarpov15 commented 3 years ago

The "From previous event" line makes it seem like you're using bluebird in debug mode - can you confirm that?

DaliborTrampota commented 3 years ago

The "From previous event" line makes it seem like you're using bluebird in debug mode - can you confirm that? @vkarpov15

Yes, I'm using bluebird but I'm not sure if in debug mode.


    global.Promise = require('bluebird');
    Promise.config({ longStackTraces: true });

this is all I have related to bluebird in my project

vkarpov15 commented 3 years ago

Try also doing mongoose.Promise = require('bluebird'), that may help with your stack traces