¿Cómo convertir un documento de Mangosta en un objeto simple?

200

Tengo un documento de un hallazgo de mangosta que quiero extender antes de la codificación JSON y enviarlo como respuesta. Si intento agregar propiedades al documento, se ignora. Las propiedades no aparecen al Object.getOwnPropertyNames(doc)hacer que una extensión normal no sea posible. Lo extraño es que JSON.parse(JSON.encode(doc))funciona y devuelve un objeto con todas las propiedades correctas. ¿Hay una mejor manera de hacer esto?

respectTheCode
fuente

Respuestas:

292

Las mangostas Models heredan de Documents, que tienen un toObject()método. Creo que lo que estás buscando debería ser el resultado doc.toObject().

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

jmar777
fuente
1
finalmente lo tengo. Para los que tienen un objeto indefinido, asegúrese de llamar al documento en lugar del modelo. es decir, modelName._doc.toObject ()
John
1
Esto está bien, pero se prefiere lean ().
Jason Sebring
¿Funciona si devuelve una matriz en Model.find({})los documentos? Return es una matriz. ¿Puedes docs.toObject?
Jack en blanco
55
@jackblank si tiene una variedad de Modelos, entonces debería poder mapear sobre ellos:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777
@ jmar777, creo que su sugerencia pertenece como una edición de esta respuesta.
r3wt
201

Otra forma de hacer esto es decirle a Mongoose que todo lo que necesita es una versión simple de JavaScript del documento devuelto mediante el uso lean()en la cadena de consulta. De esta forma, Mongoose omite el paso de crear la instancia completa del modelo y obtiene directamente un docque puede modificar:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});
JohnnyHK
fuente
17
El uso de @Startec leanes generalmente más eficiente porque se saltea la sobrecarga de crear primero el documento completo de Mongoose.
JohnnyHK
3
eres un campeón :) corrígeme si me equivoco, pero siempre debes inclinar () tus find () s si no tienes la intención de modificar y guardar el documento que acabas de recibir (por ejemplo, si solo estás intentando acceder al doc. y envíelo de vuelta a su cliente)
Amarsh
1
@Amarsh Sí, aunque eso también supone que no necesita ninguno de los métodos de instancia o virtuales definidos en el esquema.
JohnnyHK
1
sin embargo ... esto podría haber sido una opción con find () ... a menudo es demasiado común para leer un documento de un mongodb y enviarlo de vuelta a un navegador web. Me pregunto si find (). lean () en realidad significa find () primero y luego aplica un lean () de cada elemento en el resultado, en cuyo caso, la combinación find (). lean () en realidad sería más lenta que find () sí mismo.
Amarsh
44
@Amarsh No, el encadenamiento lean()en la consulta establece la opción antes de que la consulta se ejecute realmente (por exec) para que los resultados estén directamente en su forma "ajustada". Consulte esta pregunta para conocer el lado positivo del impacto en el rendimiento de las llamadas lean.
JohnnyHK
29

La forma rápida si la propiedad no está en el modelo:

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

alban maillere
fuente
55
sí ... y por sorprendente que parezca, sigo pensando que esto podría ser útil. Por ejemplo, conserva todas las primitivas de su objeto.
alban maillere
Gracias por esta respuesta, era lo que estaba buscando :)
datUser
6

Una mejor manera de abordar un problema como este es usar doc.toObject()así

doc.toObject({ getters: true })

otras opciones incluyen:

  • getters: aplicar todos los captadores (ruta y captadores virtuales)
  • virtuals: aplicar captadores virtuales (puede anular la opción de captadores)
  • minimize: eliminar objetos vacíos (el valor predeterminado es verdadero)
  • transform: una función de transformación para aplicar al documento resultante antes de regresar
  • depopulate: despoblar las rutas pobladas y reemplazarlas con sus referencias originales (el valor predeterminado es falso)
  • versionKey: si se incluye la clave de versión (el valor predeterminado es verdadero)

así, por ejemplo, puedes decir

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

y ahora funcionará

Para referencia, consulte: http://mongoosejs.com/docs/api.html#document_Document-toObject

Jalasem
fuente
3

Para obtener un objeto simple del documento Mongoose, utilicé la _docpropiedad de la siguiente manera

mongooseDoc._doc  //returns plain json object

Lo intenté toObjectpero me dio funciones, argumentos y todas las demás cosas que no necesito.

dd619
fuente
3
Acceder a propiedades o métodos _al principio no es la solución ideal. Usar lean podría resolver su caso.
Arthur Costa
@ArthurBrito sí. ¡No es una solución ideal pero sigue siendo una SOLUCIÓN! . No es necesario rechazar la respuesta. He usado la _docpropiedad muchas veces sin enfrentar ningún problema. Y el uso del leanmétodo le proporciona un objeto simple en el que no puede realizar operaciones de modelo de mangosta.
dd619
tienes razón. Solo agregue su respuesta que no es la solución ideal, luego eliminaré el voto negativo (no puedo eliminarlo a menos que lo haya editado)
Arthur Costa
2

También puede stringificar el objeto y luego volver a analizarlo para crear el objeto normal. Por ejemplo como: -

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