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.