Mongoose: Haken entfernen beim Entfernen von Dokumenten nicht ausgelöst

Erstellt am 7. Dez. 2012  ·  24Kommentare  ·  Quelle: Automattic/mongoose

Die Pre/Post-Hooks für remove werden nur ausgelöst, wenn die Methode remove() der Dokumentinstanz verwendet wird, nicht wenn die Methoden des Modells verwendet werden:

var mongoose = require("mongoose");
var db = mongoose.createConnection('mongodb://localhost/experiment');
db.once('open', function(){

  testSchema = new mongoose.Schema({ title: String });
  testSchema.post('remove', function(removed){
    console.log('removed', removed.title);
  });
  var Test = db.model('Test', testSchema);

  // > "removed A"
  new Test({ title: 'A' }).save(function(err, created){
    created.remove();
  });

  // Nothing :(
  Test({ title: 'B' }).save(function(err, created){
    Test.remove({ title: 'B' }).exec();
  });

  // Nothing :(
  Test({ title: 'C' }).save(function(err, created){
    Test.find({ title: 'C' }).remove();
  });

});
docs

Hilfreichster Kommentar

So habe ich das Problem umgangen:

Post.findOneAndRemove({'id': data.post, 'user.uid': socket.handshake.user.id}, function(err, post) {
    post.remove();
});

models.js

postSchema.post('remove', function(doc) {
    console.log('removed');
});

// prints 'removed' once

Der Remove-Hook wird bei findOneAndRemove nicht ausgelöst, funktioniert jedoch, wenn ich remove im Callback aufrufe

Alle 24 Kommentare

das funktioniert wie erwartet. das gleiche gilt für Model.update . keine Middleware heißt b/c Middleware wird nur auf Mungos-Dokumenten ausgeführt, die nicht beteiligt sind, wenn ein remove Befehl über Model.remove() direkt an MongoDB gesendet wird.

Ich lasse dies vorerst offen, bis ich die Model.remove Dokumente so korrigiert habe, dass sie mit Model.update inline sind. Danke für die Warnung.

Ich verstehe. Gibt es eine Möglichkeit, sich in _all_ remove-Operationen einzuklinken?

derzeit nicht.

Okay. Dankeschön!

Nun, Sie könnten es tun, wenn Sie Model.remove geflickt haben, aber das liegt an Ihnen :)

Funktioniert nicht mit findOneAndRemove

Scheint auch nicht zu funktionieren, wenn Sie Model.remove(_id).exec() aufrufen;

So habe ich das Problem umgangen:

Post.findOneAndRemove({'id': data.post, 'user.uid': socket.handshake.user.id}, function(err, post) {
    post.remove();
});

models.js

postSchema.post('remove', function(doc) {
    console.log('removed');
});

// prints 'removed' once

Der Remove-Hook wird bei findOneAndRemove nicht ausgelöst, funktioniert jedoch, wenn ich remove im Callback aufrufe

OK, aber warum ? Es tut mir leid, dass ich nicht verstanden habe, warum der Hook auf Model.remove() und nicht auf Query.remove() ausgeführt wird. Warum sollte ich jetzt die Hooks verwenden, wenn sie nicht jedes Mal aufgerufen werden?
Was ist der Nutzen ?

Ich meine: Soll ich die Hooks verwenden und Query.remove vermeiden oder die Hooks nicht verwenden und immer manuell entfernen?

@Darksheep42 Wenn Sie Hooks verwenden möchten, verwenden Sie doc.remove() . Der Grund, warum Dinge wie MyModel.remove(); Hooks nicht unterstützen, ist, dass das entfernte Dokument möglicherweise nicht im Speicher vorhanden ist .

Wäre es möglich, jetzt mit der Abfrage-Middleware in 4.0 Unterstützung für Query.remove() Hooks hinzuzufügen?

Im Moment nicht - das ist sehr knifflig, denn es gibt bereits Middleware für Model.remove()

Gibt es ein anderes Problem als den Namenskonflikt? Könnten Sie den Hook nicht einfach 'remove-query' oder so nennen, statt 'remove'?

Oder wie wäre es mit dem, was Sie mit update zu tun scheinen - rufen Sie den Abfrage-Hook auf, auch wenn die doc-Version der Funktion verwendet wird. Natürlich würde dies die Abwärtskompatibilität brechen, aber es ist eine Idee.

Scheint eine vernünftige Idee zu sein, aber ich zögere, die API zu brechen, es sei denn, es gibt einen wirklich guten Grund dafür. Im Moment arbeitet der Remove-Hook für ein Dokument, daher ist der Kontext in der Middleware das Dokument. Bei allgemeinen Query.remove() befindet sich das Dokument möglicherweise nicht einmal im Speicher. Ich nehme an, wir könnten es anders nennen wie "remove-query , but that's nasty. What do you think about adding an extra options arg to pre() and post()", etwa:

schema.pre('remove', { query: true }, function() {
  // This is only attached as query middleware
});

schema.pre('remove', { doc: true }, function() {
  // This will not run on Query.remove(), only doc.remove()
});

Ich vermute, das könnte funktionieren. Es ist wahrscheinlich besser als nur einen anderen Namen zu verwenden und die API wird nicht beschädigt. Also denke ich, wenn es jemand getan hat

schema.pre('remove', { query: true, doc: true }, function() {

});

Der Hook würde sowohl bei Abfrage- als auch bei Dokumentanforderungen aufgerufen werden. Ich denke, ein Benutzer könnte dies tun, wenn er sich nicht für den Kontext interessiert. Wenn Sie dies tun, möchten Sie wahrscheinlich auch den Hook update ändern, damit er diesem neuen Stil entspricht, und dies könnte möglicherweise den Code der Leute beschädigen.

Ja, das Knifflige in diesem Zusammenhang ist "Was ist die Standardeinstellung?" Um die API beizubehalten, müssten wir es so einrichten, dass update standardmäßig eine Abfrage-Middleware ist, aber remove standardmäßig eine Dokument-Middleware ist. Das wird sehr seltsam. Ich denke, wir sollten einfach eine separate Ausgabe für 5.0 eröffnen und uns später darum kümmern :)

Wie wäre es, nur für die nächste Version oder eine Version in naher Zukunft können wir den Hook einfach 'remove-query' nennen oder so? Es unterbricht die API nicht und AFAIK sollte ziemlich einfach zu implementieren sein. Wir könnten diese Funktion wirklich nutzen, da Sie derzeit nicht 100 % der Entfernungsanfragen über Middleware erfassen können und wir dies viel lieber tun, als bestimmte Techniken in unserer Codebasis durchzusetzen. In 5.0 können wir es "richtig" machen, aber ich würde diese schnelle Ergänzung gerne vor v5 sehen.

Alternativer Ansatz: Wie wäre es, wenn wir einfach eine preQuery() und eine postQuery() Funktion erstellen?

Also anstatt zu schreiben

schema.pre('remove', function() {
    // What is this? A doc hook? A query hook? Idk man
});

du würdest schreiben

schema.preQuery('remove', function() {
    // This is definitely a query hook
});
schema.pre('remove', function() {
    // This must be a doc hook
});

Würden also pre für Dokumente reserviert sein? Ich denke auch, dass Sie dies in eine 4.x-Version einfügen könnten, ohne die API zu beschädigen, aber wir möchten wahrscheinlich den alten pre Stil für Abfrage-Middleware in 5.0 entfernen.

Ja, preQuery() wäre eine gute Möglichkeit, die API zu erhalten, bis wir eine sauberere API finden können. Ich könnte mir jedoch vorstellen, dass preQuery() sofort veraltet sein könnte, da ich von der Syntax nicht ganz begeistert bin.

Dieses Problem ist noch offen, ist es behoben?
Was ist mit preQuery?

Das Problem Pre-Remove für Dokumente vs. Abfragen wird in #3054 verfolgt, noch nicht implementiert, PRs willkommen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen