Wie verwandelt man ein Mungo-Dokument in ein einfaches Objekt?

200

Ich habe ein Dokument von einem Mungo gefunden, das ich vor der JSON-Codierung und dem Versenden als Antwort erweitern möchte. Wenn ich versuche, dem Dokument Eigenschaften hinzuzufügen, wird dies ignoriert. Die Eigenschaften werden nicht angezeigt, wenn Object.getOwnPropertyNames(doc)eine normale Erweiterung nicht möglich ist. Das Seltsame ist, dass es JSON.parse(JSON.encode(doc))funktioniert und ein Objekt mit allen korrekten Eigenschaften zurückgibt. Gibt es einen besseren Weg, dies zu tun?

respektiere den Code
quelle

Antworten:

291

Mungos Modelerben von Documents, die eine toObject()Methode haben. Ich glaube, was Sie suchen, sollte das Ergebnis sein doc.toObject().

http://mongoosejs.com/docs/api.html#document_Document-toObject

jmar777
quelle
1
endlich verstanden. Stellen Sie für diejenigen, die ein undefiniertes Objekt haben müssen, sicher, dass Sie das Dokument anstelle des Modells aufrufen. dh modelName._doc.toObject ()
John
1
Dies ist in Ordnung, aber Lean () wird bevorzugt.
Jason Sebring
Funktioniert dies, wenn Sie ein Array in Model.find({})den Dokumenten zurückgeben? Return ist ein Array. Können Sie docs.toObject?
Jack Blank
5
@jackblank Wenn Sie eine Reihe von Modellen haben, sollten Sie in der Lage sein, über sie zu var docArray = modelArray.map(function(model) { return model.toObject(); });
ordnen
@ jmar777 Ich denke, Ihr Vorschlag gehört als Bearbeitung zu dieser Antwort.
r3wt
199

Eine andere Möglichkeit, dies zu tun, besteht darin, Mongoose mitzuteilen, dass Sie lediglich eine einfache JavaScript-Version des zurückgegebenen Dokuments benötigen, indem Sie es lean()in der Abfragekette verwenden. Auf diese Weise überspringt Mongoose den Schritt des Erstellens der vollständigen Modellinstanz und Sie erhalten direkt eine, die docSie ändern können:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});
JohnnyHK
quelle
16
@Startec Die Verwendung leanist im Allgemeinen leistungsfähiger, da Sie den Aufwand für die erstmalige Erstellung des vollständigen Mongoose-Dokuments überspringen.
JohnnyHK
3
Sie sind ein Champion :) Korrigieren Sie mich, wenn ich falsch liege, aber Sie sollten Ihre find () immer lehnen (), wenn Sie nicht beabsichtigen, das soeben erhaltene Dokument zu ändern und zu speichern (z. B. wenn Sie nur versuchen, auf das zuzugreifen) doc und senden Sie es zurück an Ihren Kunden)
Amarsh
1
@Amarsh Ja, obwohl dies auch voraussetzt, dass Sie keine der im Schema definierten Instanzmethoden oder Virtuals benötigen.
JohnnyHK
1
bizzare obwohl ... dies könnte eine Option mit find () gewesen sein ... es ist oft zu häufig, ein Dokument von einem Mongodb zu lesen und es an einen Webbrowser zurückzusenden. Ich frage mich, ob find (). lean () tatsächlich zuerst find () bedeutet und dann ein lean () jedes Elements im Ergebnis anwendet. In diesem Fall wäre die Kombination find (). lean () tatsächlich langsamer als find () selbst.
Amarsh
4
@Amarsh Nein, durch Verketten lean()der Abfrage wird die Option festgelegt, bevor die Abfrage tatsächlich (von exec) ausgeführt wird, sodass die Ergebnisse direkt in ihrer "schlanken" Form vorliegen. In dieser Frage finden Sie Informationen zu den positiven Auswirkungen des Anrufs auf die Leistung lean.
JohnnyHK
29

Der schnelle Weg, wenn die Eigenschaft nicht im Modell enthalten ist:

document.set( key,value, { strict: false });

alban maillere
quelle
5
ja ... und so überraschend es auch aussehen mag, ich denke immer noch, dass dies nützlich sein könnte. Zum Beispiel behalten Sie alle Grundelemente Ihres Objekts.
Alban Maillere
Vielen Dank für diese Antwort, es war das, wonach ich gesucht habe :)
datUser
6

Eine bessere Möglichkeit, ein solches Problem anzugehen, ist die Verwendung doc.toObject()dieser Methode

doc.toObject({ getters: true })

Weitere Optionen sind:

  • getters: Wenden Sie alle Getter an (Pfad- und virtuelle Getter).
  • virtuals: Anwenden virtueller Getter (kann Getter-Option überschreiben)
  • minimize: leere Objekte entfernen (standardmäßig true)
  • transform: Eine Transformationsfunktion, die vor der Rückgabe auf das resultierende Dokument angewendet wird
  • depopulate: Entvölkern Sie alle aufgefüllten Pfade und ersetzen Sie sie durch ihre ursprünglichen Verweise (standardmäßig false).
  • versionKey: ob der Versionsschlüssel enthalten sein soll (standardmäßig true)

so kann man zum Beispiel sagen

Model.findOne().exec((err, doc) => {
   if (!err) {
      doc.toObject({ getters: true })
      console.log('doc _id:', doc._id)
   }
})

und jetzt wird es funktionieren.

Referenz finden Sie unter: http://mongoosejs.com/docs/api.html#document_Document-toObject

Jalasem
quelle
3

Um ein einfaches Objekt aus dem Mongoose-Dokument zu erhalten, habe ich die _docEigenschaft wie folgt verwendet

mongooseDoc._doc  //returns plain json object

Ich habe es versucht, toObjectaber es gab mir Funktionen, Argumente und alle anderen Dinge, die ich nicht brauche.

dd619
quelle
3
Der Zugriff auf Eigenschaften oder Methoden _am Anfang ist nicht die ideale Lösung. Die Verwendung von Lean könnte Ihren Fall lösen.
Arthur Costa
@ ArthurBrito ja. Es ist keine ideale Lösung, aber es ist immer noch eine LÖSUNG! . Keine Notwendigkeit, die Antwort herunterzustimmen. Ich habe _docEigentum viele Male ohne Probleme benutzt. Mit der leanMethode erhalten Sie ein einfaches Objekt, an dem Sie keine Mungo-Modelloperationen ausführen können.
dd619
Du hast recht. Fügen Sie einfach Ihre Antwort hinzu, die nicht die ideale Lösung ist, dann entferne ich die Abwertung (ich kann sie nur entfernen, wenn Sie sie bearbeitet haben)
Arthur Costa
2

Sie können das Objekt auch stringifizieren und dann erneut analysieren, um das normale Objekt zu erstellen. Zum Beispiel wie: -

const obj = JSON.parse(JSON.stringify(mongoObj))
kaushik_pm
quelle