Mongoose/MongoDB 结果字段在 Javascript 中显示为未定义
Posted
技术标签:
【中文标题】Mongoose/MongoDB 结果字段在 Javascript 中显示为未定义【英文标题】:Mongoose/MongoDB result fields appear undefined in Javascript 【发布时间】:2013-09-13 15:20:27 【问题描述】:是否有什么我遗漏的东西可以让项目记录为带有参数的对象,但是当我尝试访问该参数时,它是未定义的?
到目前为止我已经尝试过:
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”访问有关,或者他们试图使对象超出函数的范围。在这种情况下,我不认为我在做任何一个,但如果我错了,请告诉我。谢谢
【问题讨论】:
【参考方案1】:tue查询时,使用.lean()
E.g
const order = await Order.findId("84578437").lean()
【讨论】:
【参考方案2】:如果您只想获取没有猫鼬所有好处的信息,请保存,即您可以在查询中使用 .lean()。它将更快地获取您的信息,您可以直接将其用作对象。
https://mongoosejs.com/docs/api.html#query_Query-lean
正如文档中所说,这是最好的只读方案。
【讨论】:
【参考方案3】:解决此类问题的更好方法是像这样使用doc.toObject()
doc.toObject( getters: true )
其他选项包括:
getters:
应用所有 getter(路径和虚拟 getter)
virtuals:
应用虚拟吸气剂(可以覆盖吸气剂选项)
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
)
现在它可以工作了
【讨论】:
【参考方案4】:使用findOne()
而不是find()
。
find()
方法返回一个值数组,即使您只有一个可能的结果,您也需要使用 item[0] 来获取它。
findOne
方法返回一个对象或不返回任何对象,然后您就可以毫无问题地访问其属性。
【讨论】:
就是这样,谢谢!!!没有注意到我正在处理一个数组!【参考方案5】:解决方案
您可以调用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)可以发现Document
的toString
方法调用了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());
;
【讨论】:
在 Mongo 3.2 上对我不起作用。说它没有toObject
方法。
@GeorgeRappel 通过引用Automattic/mongoose
的History
,在3.4.0 版本中添加了toObject
。 mongoose 的最新版本是 4.5.2。我认为您需要更新您的猫鼬模块...
我有 moongose 版本 4.8.4 并且收到相同的消息错误:“TypeError: user.toObject is not a function”
如果我这样做 toObject
我可以使用 obj (foo) 作为猫鼬对象,例如foo.save()
?我在查询 mongoose 时使用 .lean()
解决了这个问题【参考方案6】:
老问题,但由于我也有这个问题,所以我会回答它。
这可能是因为您使用的是find()
而不是findOne()
。所以最后,你调用的是一个文档数组而不是文档的方法,导致找到一个数组而不是单个文档。使用findOne()
可以让您正常访问该对象。
【讨论】:
【参考方案7】:确保您已在架构中定义标题:
var MyCollectionSchema = new mongoose.Schema(
_id: String,
title: String
);
【讨论】:
这是我的问题!!!该文档在数据库中是正确的,但由于架构不正确,即使它正确打印了整个对象,它也不会显示变量。【参考方案8】:我认为使用 'find' 方法会返回一个文档数组。我尝试了这个并且能够打印标题
for (var i = 0; i < doc.length; i++)
console.log("iteration " + i);
console.log('ID:' + docs[i]._id);
console.log(docs[i].title);
【讨论】:
【参考方案9】:尝试在item
上执行for in
循环,看看是否可以访问值。
for (var k in item)
console.log(item[k]);
如果有效,则意味着您的密钥有一些 non-printable
字符或类似的字符。
从您在 cmets 中所说的来看,item
似乎是 String
原始包装器的一个实例。
例如
var s = new String('test');
typeof s; //object
s instanceof String; //true
要验证这个理论,试试这个:
eval('(' + item + ')').title;
也可能是item
是一个具有toString
方法的对象,可以显示您所看到的内容。
编辑:要快速识别这些问题,您可以使用console.dir
而不是console.log
,因为它会显示对象属性的交互式列表。您还可以设置断点并添加监视。
【讨论】:
是的!有点。除非我这样做,否则它将对象作为字符串返回。前" title: 'foo'\n content: 'bar'"
您的意思是console.log(item[k])
显示您所说的内容?
它将项目显示为字符串,这使得对象的参数无法访问。我更新了这个问题,以更好地描述我对正在发生的事情的了解。
@tippenein,我更新了答案,以便您了解您得到的结果。我希望该对象具有用于打印自身的自定义 toString
函数。这可以解释混乱。
我很欣赏这些解释,但从我最近的发现来看,item._doc.title 会返回我所期望的。这证实了它是一个对象,但它以某种方式无法打印出它实际包含的内容。【参考方案10】:
你在初始化你的对象吗?
function MyObject()
this.Title = "";
this.Content = "";
var myo1 = new MyObject();
如果您没有初始化或没有设置标题。你会得到未定义的。
【讨论】:
对象由 mongoose collection.find() 返回,但也许你正在做某事。也许我初始化 TextController 有问题 我建议使用 chrome 或 firefox 开发工具放置一个断点,以便您检查对象的外观。【参考方案11】:' title'
中没有空格或有趣的字符,是吗?如果您在对象/地图定义中引用了标识符,则可以定义它们。例如:
var problem =
' title': 'Foo',
'content': 'Bar'
;
这可能会导致 console.log(item)
显示类似于您的预期,但是当您访问 title
属性时没有前面的空格时会导致您的 undefined
问题。
【讨论】:
doc
是 mongo db 查询的结果,所以我只是遍历这些对象。我确实尝试过 item['title'] 和 item['title']。没有运气以上是关于Mongoose/MongoDB 结果字段在 Javascript 中显示为未定义的主要内容,如果未能解决你的问题,请参考以下文章
在 Mongoose/MongoDB 的文档中过滤数组、子文档、数组、文档
Mongoose/Mongodb Aggregate - 对多个字段进行分组和平均
如何使用 Autopopulate Mongoose Mongodb 选择要检索的字段?
无法使用函数(req,res,next,id)mongoose(mongodb)中的动态id字段进行查询