261 votes

Comment transformer un document Mongoose en un objet simple ?

J'ai un document provenant d'une recherche de mangouste que je veux étendre avant de l'encoder en JSON et de l'envoyer comme réponse. Si j'essaie d'ajouter des propriétés au document, elles sont ignorées. Les propriétés n'apparaissent pas dans Object.getOwnPropertyNames(doc) rendant impossible une extension normale. Ce qui est étrange, c'est que JSON.parse(JSON.encode(doc)) fonctionne et renvoie un objet avec toutes les propriétés correctes. Existe-t-il une meilleure façon de procéder ?

378voto

jmar777 Points 11681

Mangouste Model héritent de Document qui ont un toObject() méthode. Je pense que ce que vous recherchez devrait être le résultat de doc.toObject() .

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

5 votes

Je l'ai finalement obtenu. Pour ceux qui ont toObject non défini, assurez-vous d'appeler sur le document au lieu du modèle, c'est-à-dire modelName._doc.toObject().

6 votes

C'est acceptable, mais lean() est préférable.

3 votes

Cela fonctionne-t-il si vous retournez un tableau sur Model.find({}) le retour de docs est un tableau. Pouvez-vous docs.toObject ?

255voto

JohnnyHK Points 61191

Une autre façon de procéder est d'indiquer à Mongoose que tout ce dont vous avez besoin est une version JavaScript simple de la doc retournée en utilisant la commande lean() dans la chaîne d'interrogation. De cette manière, Mongoose saute l'étape de la création de l'instance complète du modèle et vous obtenez directement un fichier doc que vous pouvez modifier :

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

0 votes

Node dit que le doc n'a pas de méthode toObject() mais .lean() fonctionne comme par magie !

0 votes

Cela semble être la meilleure façon de procéder. Y a-t-il une méthode généralement préférée ou plus performante ?

25 votes

@Startec utilise lean est généralement plus performant car il ne nécessite pas la création préalable du document Mongoose complet.

30voto

alban maillere Points 74

La manière rapide si la propriété n'est pas dans le modèle :

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

7 votes

Oui... et aussi surprenant que cela puisse paraître, je pense toujours que cela pourrait être utile. Par exemple, vous gardez toutes les primitives de votre objet.

0 votes

Merci pour cette réponse, c'est ce que je cherchais :)

27voto

Suggestion de JohnnyHK :

Dans certains cas, comme l'a suggéré @JohnnyHK, vous voudrez obtenir l'objet en tant que Plain Javascript. comme décrit dans ce Documentation sur Mongoose il existe une autre alternative pour interroger les données directement en tant qu'objet :

const docs = await Model.find().lean();

Renvoi conditionnel de Plain Object :

De plus, si quelqu'un veut se tourner de manière conditionnelle vers un objet, il est également possible de le faire en tant que option argument, voir docs find() au troisième paramètre :

const toObject = true;
const docs = await Model.find({},null,{lean:toObject});

Elle est disponible sur les fonctions : find() , findOne() , findById() , findOneAndUpdate() y findByIdAndUpdate() .

NOTE :

il convient également de mentionner que le _id n'est pas un objet de type chaîne de caractères comme si vous faisiez JSON.parse(JSON.stringify(object)) mais un ObjectId de type Mongoose, donc lors de la comparaison avec des chaînes de caractères, il est converti en chaîne de caractères avant : String(object._id) === otherStringId

18voto

Jalasem Points 6232

Une meilleure façon d'aborder un problème comme celui-ci est d'utiliser doc.toObject() comme ceci

doc.toObject({ getters: true })

d'autres options sont possibles :

  • getters: appliquer tous les getters (path et getters virtuels)
  • virtuals: appliquer des getters virtuels (peut remplacer l'option getters)
  • minimize: supprimer les objets vides (valeur par défaut : true)
  • transform: une fonction de transformation à appliquer au document résultant avant de le retourner
  • depopulate: dépeuple tous les chemins remplis, en les remplaçant par leurs références d'origine (la valeur par défaut est false).
  • versionKey: inclure ou non la clé de version (valeur par défaut : true)

Ainsi, par exemple, vous pouvez dire

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

et maintenant ça marche.

Pour référence, voir : http://mongoosejs.com/docs/api.html#document_Document-toObject

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X