Jak zmienić dokument Mongoose w zwykły obiekt?

200

Mam dokument z znaleziska mangusty, który chcę rozszerzyć przed kodowaniem JSON i wysłaniem w odpowiedzi. Jeśli spróbuję dodać właściwości do dokumentu, zostanie to zignorowane. Właściwości nie pojawiają się w przypadku Object.getOwnPropertyNames(doc)niemożności normalnego rozszerzenia. Dziwne jest to, że JSON.parse(JSON.encode(doc))działa i zwraca obiekt o wszystkich poprawnych właściwościach. Czy jest na to lepszy sposób?

szacunek Kod
źródło

Odpowiedzi:

292

Mongoose Models dziedziczy po Documents, które mają toObject()metodę. Uważam, że to, czego szukasz, powinno być wynikiem doc.toObject().

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

jmar777
źródło
1
nareszcie to zdobyłem. dla tych, którzy muszą zdefiniować obiekt niezdefiniowany, pamiętaj o wywołaniu dokumentu zamiast modelu. tzn. modelName._doc.toObject ()
John
1
Jest to OK, ale preferowane jest lean ().
Jason Sebring
Czy to działa, jeśli zwrócisz tablicę po Model.find({})powrocie dokumentów to tablica. Czy umiesz docs.toObject?
jack blank
5
@jackblank, jeśli masz szereg modeli, powinieneś być w stanie zmapować je:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777
@ jmar777 Myślę, że twoja sugestia należy do edycji tej odpowiedzi.
r3wt
200

Innym sposobem na to jest poinformowanie Mongoose, że wszystko, czego potrzebujesz, to zwykła wersja JavaScript zwróconego dokumentu za pomocą lean()łańcucha zapytań. W ten sposób Mongoose pomija etap tworzenia pełnej instancji modelu i otrzymujesz bezpośrednio docmodyfikację:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});
JohnnyHK
źródło
16
@Startec Korzystanie leanjest na ogół bardziej wydajne, ponieważ pomijasz narzut związany z pierwszym tworzeniem pełnego dokumentu Mongoose.
JohnnyHK
3
jesteś mistrzem :) popraw mnie, jeśli się mylę, ale zawsze powinieneś pochylić () swoje znaleziska (), jeśli nie zamierzasz modyfikować i zapisywać właśnie otrzymanego dokumentu (powiedz, jeśli próbujesz uzyskać dostęp do dok. i odeślij go do klienta)
Amarsh
1
@Amarsh Tak, choć zakłada to również, że nie potrzebujesz żadnych metod instancji ani wirtualnych zdefiniowanych w schemacie.
JohnnyHK
1
bizzare ... może to być opcja z find () ... często zbyt często czyta dokument z mongodb i odsyła go z powrotem do przeglądarki internetowej. zastanawiam się, czy find (). lean () faktycznie oznacza najpierw find (), a następnie zastosuj lean () każdego elementu w wyniku, w którym to przypadku kombinacja find (). lean () byłaby wolniejsza niż find () samo.
Amarsh
4
@Amarsh Nie, łączenie łańcuchowe lean()w zapytaniu ustawia opcję przed wykonaniem (przez exec) zapytania, dzięki czemu wyniki są bezpośrednio w „ubogiej” formie. Zobacz to pytanie, aby poznać pozytywny wpływ połączeń na wydajność lean.
JohnnyHK,
29

szybki sposób, jeśli właściwość nie znajduje się w modelu:

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

alban maillere
źródło
5
tak ... i choć może to wydawać się zaskakujące, nadal uważam, że to może być przydatne. Na przykład zachowujesz wszystkie prymitywy obiektu.
alban maillere
Dzięki za tę odpowiedź, właśnie tego szukałem :)
datUser
6

Lepszym sposobem rozwiązania takiego problemu jest użycie doc.toObject()tego w ten sposób

doc.toObject({ getters: true })

inne opcje obejmują:

  • getters: zastosuj wszystkie metody pobierające (ścieżkę i metody pobierające wirtualne)
  • virtuals: zastosuj wirtualne operacje pobierania (może zastąpić opcję pobierania)
  • minimize: usuń puste obiekty (domyślnie true)
  • transform: funkcja przekształcania stosowana do dokumentu wynikowego przed zwróceniem
  • depopulate: wyludnij wszystkie zapełnione ścieżki, zastępując je oryginalnymi referencjami (domyślnie false)
  • versionKey: czy dołączyć klucz wersji (domyślnie true)

więc na przykład możesz powiedzieć

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

i teraz będzie działać.

W celach informacyjnych patrz: http://mongoosejs.com/docs/api.html#document_Document-toObject

Jalasem
źródło
3

Aby uzyskać zwykły obiekt z dokumentu Mongoose, użyłem _docwłaściwości w następujący sposób

mongooseDoc._doc  //returns plain json object

Próbowałem, toObjectale dało mi to funkcje, argumenty i wszystkie inne rzeczy, których nie potrzebuję.

dd619
źródło
3
Dostęp do właściwości lub metod _na początku nie jest idealnym rozwiązaniem. Korzystanie z lean może rozwiązać twoją sprawę.
Arthur Costa
@ArthurBrito tak. To nie jest idealne rozwiązanie, ale wciąż ROZWIĄZANIE! . Nie trzeba głosować za odpowiedzią. Korzystałem z _docnieruchomości wiele razy bez żadnych problemów. A użycie leanmetody daje prosty obiekt, na którym nie można wykonywać operacji na modelu mangusty.
dd619,
masz rację. Wystarczy dodać w odpowiedzi, że nie jest to idealne rozwiązanie, a następnie usunę głos negatywny (nie mogę go usunąć, chyba że byłeś edytowany)
Arthur Costa
2

Możesz także skreślić obiekt, a następnie ponownie przeanalizować, aby utworzyć normalny obiekt. Na przykład:

const obj = JSON.parse(JSON.stringify(mongoObj))
kaushik_pm
źródło