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.