是否有一些我遗漏的东西会允许项目作为带参数的对象记录,但当我尝试访问该参数时,它是未定义的?
到目前为止我尝试过:
console.log(item)
=> { title: "foo", content: "bar" }
,没关系console.log(typeof item)
=>对象console.log(item.title)
=> “未定义”我将包含一些上下文,以防它与问题相关。
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());
})
}
根据建议我在此行之前删除了debugger
,以通过节点repl调试器检查实际上是什么项目。这就是我发现的:http://hastebin.com/qatireweni.sm
由此我尝试了console.log(item._doc.title)
并且它运作得很好..所以,现在看起来更像是一个猫鼬问题。
有类似的问题,但它们似乎与'this'对象的访问有关,或者他们试图让对象超出函数的范围。在这种情况下,我不认为我正在做其中任何一个,但如果我错了就通知我。感谢
答案 0 :(得分:33)
您可以调用toObject
方法来访问字段。例如:
var itemObject = item.toObject();
console.log(itemObject.title); // "foo"
当您指出时,实际字段存储在文档的_doc
字段中。
但为什么console.log(item)
=> { title: "foo", content: "bar" }
?
从the source code of mongoose(document.js),我们可以发现toString
Document
方法调用toObject
方法。因此console.log
会正确显示字段'。源代码如下所示:
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());
};
答案 1 :(得分:7)
确保您在架构中定义了标题:
var MyCollectionSchema = new mongoose.Schema({
_id: String,
title: String
});
答案 2 :(得分:4)
尝试在for in
上执行item
循环,看看您是否可以访问值。
for (var k in item) {
console.log(item[k]);
}
如果有效,则表示您的密钥有一些non-printable
字符或类似的内容。
根据您在评论中所说的,看起来某种方式item
是String
原始包装器的实例。
E.g。
var s = new String('test');
typeof s; //object
s instanceof String; //true
要验证这一理论,请尝试以下方法:
eval('(' + item + ')').title;
也可能是item
是一个具有toString
方法的对象,可以显示您看到的内容。
编辑:要快速识别这些问题,您可以使用console.dir
代替console.log
,因为它会显示对象属性的交互式列表。您也可以断点并添加手表。
答案 3 :(得分:2)
' title'
中没有空格或有趣的字符,是吗?如果您已将标识符引用到对象/地图定义中,则可以定义它们。例如:
var problem = {
' title': 'Foo',
'content': 'Bar'
};
这可能会导致console.log(item)
显示与您期望的相似,但在访问undefined
属性时会导致title
问题,而不会显示前一个空格。
答案 4 :(得分:2)
我认为使用'find'方法会返回一个Documents的数组。我尝试了这个并且我能够打印标题
for (var i = 0; i < doc.length; i++) {
console.log("iteration " + i);
console.log('ID:' + docs[i]._id);
console.log(docs[i].title);
}
答案 5 :(得分:2)
老问题,但由于我也有这个问题,我会回答。
这可能是因为您使用的是find()
而不是findOne()
。因此,最后,您正在调用一个文档数组而不是文档的方法,从而导致查找数组而不是单个文档。使用findOne()
可以让您正常访问该对象。
答案 6 :(得分:1)
使用findOne()
代替find()
。
find()
方法返回一个值数组,即使您只有一个可能的结果,也需要使用item [0]来获取它。
findOne
方法返回一个对象或没有对象,然后您就可以无问题地访问其属性。
答案 7 :(得分:1)
解决此类问题的更好方法是使用doc.toObject()
这样的
doc.toObject({ getters: true })
其他选项包括:
getters:
应用所有getter(路径和虚拟getter)virtuals:
应用虚拟getter(可以覆盖getter选项)minimize:
删除空对象(默认为true)transform:
转换函数,在返回depopulate:
取消填充所有填充的路径,将其替换为原始引用(默认为false)versionKey:
是否包含版本密钥(默认为true)所以例如你可以说
Model.findOne().exec((err, doc) => {
if (!err) {
doc.toObject({ getters: true })
console.log('doc _id:', doc._id) // or title
}
})
现在它将起作用
答案 8 :(得分:1)
如果您只想获取所有猫鼬收益所不及的信息,请保存,即可以在查询中使用.lean()。它将更快地获取您的信息,您可以将其直接用作对象。
https://mongoosejs.com/docs/api.html#query_Query-lean
正如在文档中所述,这是最好的只读方案。
答案 9 :(得分:0)
你在初始化你的对象吗?
function MyObject()
{
this.Title = "";
this.Content = "";
}
var myo1 = new MyObject();
如果您未初始化或未设置标题。你会得到不确定的。