2
votes

Utilisation du hook Mongoose `pre` pour obtenir le document avant findOneAndUpdate ()

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?


0 commentaires

4 Réponses :


9
votes

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.


5 commentaires

Haris a raison, les documents répertorient findOneAndUpdate 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.



2
votes

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.


0 commentaires

2
votes

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
});


0 commentaires

0
votes

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


0 commentaires