update español javascript mongodb mongoose javascript-objects function-prototypes

español - Los campos de resultados de Mongoose/MongoDB aparecen indefinidos en Javascript



mongoose schema (10)

¿Hay algo que me esté perdiendo que permita que el elemento se registre como un objeto con un parámetro, pero cuando intento acceder a ese parámetro, no está definido?

Lo que he probado hasta ahora:

  • console.log(item) => { title: "foo", content: "bar" } , eso está bien
  • console.log(typeof item) => objeto
  • console.log(item.title) => "undefined"

Incluiré parte del contexto en caso de que sea relevante para el problema.

var TextController = function(myCollection) { this.myCollection = myCollection } TextController.prototype.list = function(req, res, next) { this.myCollection.find({}).exec(function(err, doc) { var set = new Set([]) doc.forEach(function(item) { console.log(item) // Here item shows the parameter console.log(item.title) // "undefined" set.add(item.title) }) res.json(set.get()); }) }

Según la sugerencia, dejé el debugger antes de esta línea para comprobar qué elemento es realmente a través del depurador de respuesta de nodo. Esto es lo que encontré: http://hastebin.com/qatireweni.sm

A partir de esto probé console.log(item._doc.title) y funciona bien ... Entonces, esto parece más una pregunta de mangosta ahora que cualquier otra cosa.

Hay preguntas similares a esto, pero parecen estar relacionadas con el acceso a los objetos ''este'' o están tratando de obtener el objeto fuera del alcance de la función. En este caso, no creo que esté haciendo nada de eso, pero infórmame si estoy equivocado. Gracias


Solución

Puede llamar al método toObject para acceder a los campos. Por ejemplo:

var itemObject = item.toObject(); console.log(itemObject.title); // "foo"

Por qué

A medida que señala que los campos reales se almacenan en el campo _doc del documento .

Pero ¿por qué console.log(item) => { title: "foo", content: "bar" } ?

Del código fuente de mongoose (document.js) , podemos encontrar que el método toString de Document llama al método toObject . Así que console.log mostrará los campos ''correctamente''. El código fuente se muestra a continuación:

var inspect = require(''util'').inspect; ... /** * Helper for console.log * * @api public */ Document.prototype.inspect = function(options) { var isPOJO = options && utils.getFunctionName(options.constructor) === ''Object''; var opts; if (isPOJO) { opts = options; } else if (this.schema.options.toObject) { opts = clone(this.schema.options.toObject); } else { opts = {}; } opts.minimize = false; opts.retainKeyOrder = true; return this.toObject(opts); }; /** * Helper for console.log * * @api public * @method toString */ Document.prototype.toString = function() { return inspect(this.inspect()); };


¿Estás inicializando tu objeto?

function MyObject() { this.Title = ""; this.Content = ""; } var myo1 = new MyObject();

Si no inicializa o no ha establecido un título. Usted obtendrá indefinido.


Asegúrese de que ha definido el título en su esquema:

var MyCollectionSchema = new mongoose.Schema({ _id: String, title: String });


Creo que usar el método ''buscar'' devuelve una serie de Documentos. Intenté esto y pude imprimir el título

for (var i = 0; i < doc.length; i++) { console.log("iteration " + i); console.log(''ID:'' + docs[i]._id); console.log(docs[i].title); }


Intente realizar un bucle for in sobre el item y ver si puede acceder a los valores.

for (var k in item) { console.log(item[k]); }

Si funciona, significaría que sus claves tienen algunos caracteres non-printable o algo así.

Por lo que dijiste en los comentarios, parece que de alguna manera el item es una instancia de un contenedor primitivo String .

P.ej

var s = new String(''test''); typeof s; //object s instanceof String; //true

Para verificar esta teoría, prueba esto:

eval(''('' + item + '')'').title;

También podría ser que el item sea ​​un objeto que tenga un método toString que muestre lo que ve.

EDITAR: para identificar estos problemas rápidamente, puede usar console.dir lugar de console.log , ya que muestra una lista interactiva de las propiedades del objeto. También puede hacer un punto de interrupción y agregar un reloj.


No tienes espacios en blanco ni personajes divertidos en '' title'' , ¿verdad? Se pueden definir si ha citado identificadores en la definición de objeto / mapa. Por ejemplo:

var problem = { '' title'': ''Foo'', ''content'': ''Bar'' };

Eso podría hacer que console.log(item) muestre similar a lo que está esperando, pero puede causar undefined problema undefined cuando accede a la propiedad del title sin su espacio anterior.


Pregunta antigua, pero como también tuve un problema con esto, la responderé.
Esto probablemente sucedió porque estás usando find() lugar de findOne() . Entonces, al final, está llamando a un método para una matriz de documentos en lugar de un documento, lo que resulta en encontrar una matriz y no un solo documento. El uso de findOne() le permitirá acceder al objeto normalmente.


Si solo desea obtener la información sin todos los beneficios de la mangosta, guarde, por ejemplo, puede usar .lean () en su consulta. Obtendrá su información más rápido y podrá usarla como un objeto directamente.

https://mongoosejs.com/docs/api.html#query_Query-lean

Como se indica en los documentos, este es el mejor para escenarios de solo lectura.


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

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 (por defecto es verdadero)
  • transform: una función de transformación para aplicar al documento resultante antes de regresar
  • depopulate: despoblar las rutas pobladas, reemplazándolas con sus referencias originales (el valor predeterminado es falso)
  • versionKey: si se incluye la clave de la versión (el valor predeterminado es verdadero)

así que por ejemplo puedes decir

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

y ahora funcionará


Use findOne() lugar de find() .

El método find() devuelve una matriz de valores, incluso si solo tiene un posible resultado, deberá usar el elemento [0] para obtenerlo.

El método findOne devuelve un objeto o ninguno, entonces podrá acceder a sus propiedades sin problemas.