J'essaie d'utiliser les hooks Mongoose pre
et post
dans mon backend MongoDB afin de comparer le document dans ses états pré et post-enregistré, afin de déclencher certains autres événements en fonction de ce qui a changé. Jusqu'à présent, cependant, j'ai du mal à obtenir le document via le hook Mongoose pre
.
D'après la documentation, "les pré-hooks fonctionnent à la fois pour doc.save () et doc.update (). Dans les deux cas, cela fait référence au document lui-même ...". Alors, voici ce que j'ai essayé. D'abord dans mon modèle / schéma j'ai le code suivant:
exports.preSave = function(next) { console.log("this: ", this); } };
... Et puis dans mon fichier de déclencheurs j'ai le code suivant:
let Schema = mongoose .Schema(CustomerSchema, { timestamps: true }) .pre("findOneAndUpdate", function(next) { trigger.preSave(next); }) // other hooks }
Mais c'est ce qui se connecte à la console:
ceci: {preSave: [Function], postSave: [AsyncFunction]}
Donc, clairement, cela n'a pas fonctionné. Cela n'a pas déconnecté le document comme je l'espérais. Pourquoi ce
n'est-il pas le document lui-même ici, comme les documents eux-mêmes semblent l'indiquer? Et puis-je accéder au document avec un crochet pre
? Sinon, y a-t-il une autre approche que les gens ont utilisée pour y parvenir?
4 Réponses :
Vous ne pouvez pas récupérer le document dans le hook pre
.
Selon la documentation pre
est un middleware de requête et this
fait référence à la requête et non au document en cours de mise à jour.
Haris a raison, les documents répertorient findOneAndUpdate code > comme middleware de requête (
update
également, d'ailleurs). Le fait est que ces méthodes n'ont tout simplement pas accès au document en cours de mise à jour.
Merci, JohnnyHK et @Haris pour la clarification. Ces documents sont difficiles à faire face ou à face.
Vous pouvez récupérer le document dans / some / pre
hooks. Cela dépend du type de middleware, pas du pré / post. findOneAndUpdate
est un middleware de type requête - mais ce n'est pas spécifiquement le pre
.
@scipilot qu'en est-il des intergiciels spécifiques aux documents tels que remove (). Je n'obtiens pas non plus le contexte de cela. Veuillez voir mon implémentation ci-dessous: Le contrôleur supprime un objet: wait entity.remove (); Pré hook: entitySchema.pre ('remove', async (next) => {console.log ("remove", this); // ****** Sortie - suppression {} attendre deleteAllUsersInEntity (this); attendre deleteAllThreadsInEntity (ceci);})
@HeetShah, il est préférable d'ouvrir une nouvelle question avec plus de contexte pour que les gens vous y aident. Mais cela devrait fonctionner: cela devrait être le document. Votre document est-il simplement vide? {}
est un objet vide, pas rien du tout.
La confusion est due à la différence de contexte this
dans chacun des types de fonctions middleware. Pendant le middleware document pre
ou post
, vous pouvez utiliser this
pour accéder au modèle de document, mais pas dans l'autre crochets.
Il existe trois types de fonctions middleware, qui ont toutes des étapes pré et post.
Dans les fonctions middleware de document, ceci
fait référence au document (modèle).
initier, valider, enregistrer, supprimer
Dans les fonctions middleware de requête, ceci
fait référence à la requête .
count,find,findOne,findOneAndRemove,findOneAndUpdate,update
Dans le middleware agrégé, ceci
fait référence à l'objet agrégation .
aggregate
C'est expliqué ici https://mongoosejs.com/docs/middleware. html # types-of-middleware
Par conséquent, vous pouvez simplement accéder au document pendant pre ("init"), pre ("init"), pre ("validate"), post ("validate"), pre ("save"), post ("save"), pre ("remove"), post ("remove")
, mais pas dans aucun des autres.
J'ai vu des exemples de personnes effectuant plus de requêtes dans les autres hooks middleware, pour retrouver le modèle, mais cela me semble assez dangereux.
La réponse courte semble être, vous devez changer la requête d'origine pour qu'elle soit orientée document, pas de style de requête ou d'agrégation. Cela semble être une limitation étrange.
Selon la documentation, vous ne pouvez pas obtenir le document en fonction, mais il peut obtenir la requête comme suit
schema.pre('findOneAndUpdate', async function() { const docToUpdate = await this.model.findOne(this.getQuery()); console.log(docToUpdate); // The document that findOneAndUpdate() will modify });
Si vous voulez vraiment accéder au document (ou à l'ID) dans les fonctions du middleware de requête
UserSchema.pre<User>(/^(updateOne|save|findOneAndUpdate)/, async function (next) { const user: any = this if (user.password) { if (user.isModified('password')) { user.password = await getHashedPassword(user.password) } return next() } const { password } = user.getUpdate() if (password) { user._update.password = await getHashedPassword(password) } next() })
Si quelqu'un a besoin de la fonction pour hacher mot de passe lorsque le mot de passe de l'utilisateur change
UserSchema.pre<User>(/^(updateOne|save|findOneAndUpdate)/, async function (next) { const user: any = this if (!user.password) { const userID = user._conditions?._id const foundUser = await user.model.findById(userID) ... }
user.password existe lorsque "save" est le déclencheur
user.getUpdate () retournera les accessoires qui changent dans " mettre à jour "les déclencheurs