Come si trasforma un documento Mongoose in un semplice oggetto?


200

Ho un documento di una mangusta che desidero estendere prima della codifica JSON e dell'invio come risposta. Se provo ad aggiungere proprietà al documento, questo viene ignorato. Le proprietà non appaiono nel Object.getOwnPropertyNames(doc)rendere impossibile una normale estensione. La cosa strana è che JSON.parse(JSON.encode(doc))funziona e restituisce un oggetto con tutte le proprietà corrette. C'è un modo migliore per farlo?

Risposte:


292

Mongoose Models eredita da Documents, che hanno un toObject()metodo. Credo che ciò che stai cercando dovrebbe essere il risultato doc.toObject().

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


1
finalmente capito. per quelli che hanno l'opposizione non definita, assicurarsi di chiamare il documento anziché il modello. cioè modelName._doc.toObject ()
John,

1
Questo è OK ma si preferisce lean ().
Jason Sebring,

Funziona se si restituisce un array sul Model.find({})ritorno di documenti è un array. Puoi docs.toObject?
Jack

5
@jackblank se hai una serie di modelli, allora dovresti essere in grado di var docArray = modelArray.map(function(model) { return model.toObject(); });
mapparli

@ jmar777 Penso che il tuo suggerimento appartenga a una modifica di questa risposta.
rw

201

Un altro modo per farlo è dire a Mongoose che tutto ciò che serve è una semplice versione JavaScript del documento restituito usando lean() nella catena di query. In questo modo Mongoose salta il passaggio della creazione dell'istanza del modello completo e si ottiene direttamente un che docè possibile modificare:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});

17
L'utilizzo di @Startec leanè generalmente più efficace perché si salta l'overhead della prima creazione dell'intero documento Mongoose.
JohnnyHK,

3
sei un campione :) correggimi se sbaglio, ma dovresti sempre appoggiarti () ai tuoi find () se non hai intenzione di modificare e salvare il documento che hai appena ricevuto (diciamo, se stai solo cercando di accedere al doc e
rispediscilo

1
@Amarsh Sì, anche se questo presuppone anche che non sia necessario alcuno dei metodi di istanza o virtuali definiti nello schema.
JohnnyHK,

1
bizzare però ... questa potrebbe essere stata un'opzione con find () ... è spesso troppo comune leggere un documento da un mongodb e rispedirlo a un browser web. mi chiedo se find (). lean () in realtà significhi prima find () e poi applichi un lean () di ogni elemento nel risultato, nel qual caso, find (). lean () combinazione sarebbe effettivamente più lenta di find () si.
Amarsh,

4
@Amarsh No, il concatenamento lean()sulla query imposta l'opzione prima che la query venga effettivamente eseguita (da exec) in modo che i risultati siano direttamente nella loro forma "snella". Vedi questa domanda per il lato positivo delle prestazioni della chiamata lean.
JohnnyHK,

29

il modo rapido se la proprietà non è nel modello:

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


5
sì ... e per quanto sorprendente possa sembrare, penso ancora che ciò possa essere utile. Ad esempio, mantieni tutte le primitive del tuo oggetto.
alban maillere,

Grazie per questa risposta, era quello che stavo cercando :)
datUser

6

Un modo migliore per affrontare un problema come questo è usare in doc.toObject()questo modo

doc.toObject({ getters: true })

altre opzioni includono:

  • getters: applica tutti i getter (percorso e getter virtuali)
  • virtuals: applica getter virtuali (può ignorare l'opzione getter)
  • minimize: rimuove oggetti vuoti (il valore predefinito è true)
  • transform: una funzione di trasformazione da applicare al documento risultante prima della restituzione
  • depopulate: spopolare eventuali percorsi popolati, sostituendoli con i loro riferimenti originali (il valore predefinito è falso)
  • versionKey: se includere la chiave di versione (il valore predefinito è true)

quindi per esempio puoi dire

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

e ora funzionerà.

Per riferimento, consultare: http://mongoosejs.com/docs/api.html#document_Document-toObject


3

Per ottenere un oggetto semplice dal documento Mongoose, ho usato la _docproprietà come segue

mongooseDoc._doc  //returns plain json object

Ci ho provato toObjectma mi ha dato funzioni, argomenti e tutte le altre cose di cui non ho bisogno.


3
Accedere a proprietà o metodi con _all'inizio non è la soluzione ideale. L'uso di lean potrebbe risolvere il tuo caso.
Arthur Costa,

@ArthurBrito sì. Non è una soluzione ideale ma è comunque una SOLUZIONE! . Non è necessario effettuare il downgrade della risposta. Ho usato la _docproprietà molte volte senza affrontare alcun problema. L'uso del leanmetodo fornisce un oggetto semplice su cui non è possibile eseguire operazioni sul modello di mangusta.
dd619,

hai ragione. Basta aggiungere la tua risposta che non è la soluzione ideale, quindi rimuoverò il downvote (non posso rimuoverlo se non lo hai modificato)
Arthur Costa

2

È inoltre possibile stringere l'oggetto e quindi analizzarlo nuovamente per creare l'oggetto normale. Ad esempio come: -

const obj = JSON.parse(JSON.stringify(mongoObj))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.