Mongoose / MongoDB结果字段在Javascript中显示为未定义

时间:2013-09-10 02:56:36

标签: javascript mongodb mongoose javascript-objects function-prototypes

是否有一些我遗漏的东西会允许项目作为带参数的对象记录,但当我尝试访问该参数时,它是未定义的?

到目前为止我尝试过:

  • 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'对象的访问有关,或者他们试图让对象超出函数的范围。在这种情况下,我不认为我正在做其中任何一个,但如果我错了就通知我。感谢

10 个答案:

答案 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字符或类似的内容。

根据您在评论中所说的,看起来某种方式itemString原始包装器的实例。

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();

如果您未初始化或未设置标题。你会得到不确定的。