简体   繁体   English

Mongoose/MongoDB 结果字段在 Javascript 中出现未定义

[英]Mongoose/MongoDB result fields appear undefined in Javascript

Is there something that I'm missing that would allow item to log as an object with a parameter, but when I try to access that parameter, it's undefined?有没有什么东西是我遗漏的,它允许 item 使用参数记录为 object,但是当我尝试访问该参数时,它是未定义的?

What I've tried so far:到目前为止我已经尝试过:

  • console.log(item) => { title: "foo", content: "bar" } , that's fine console.log(item) => { title: "foo", content: "bar" } ,没问题
  • console.log(typeof item) => object console.log(typeof item) => object
  • console.log(item.title) => "undefined" console.log(item.title) => "undefined"

I'll include some of the context just in case it's relevant to the problem.我将包括一些上下文,以防它与问题相关。

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

Based on suggestion I dropped debugger before this line to check what item actually is via the node repl debugger.根据建议,我在此行之前删除了debugger ,以通过节点 repl 调试器检查实际是什么项目。 This is what I found: http://hastebin.com/qatireweni.sm这是我发现的: http://hastebin.com/qatireweni.sm

From this I tried console.log(item._doc.title) and it works just fine.. So, this seems more like a mongoose question now than anything.由此我尝试了console.log(item._doc.title)并且它工作得很好.. 所以,这现在看起来更像是一个 mongoose 问题而不是任何问题。

There are questions similar to this, but they seem to be related to 'this' accessing of objects or they're trying to get the object outside the scope of the function. In this case, I don't think I'm doing either of those, but inform me if I'm wrong.有类似的问题,但它们似乎与对象的“this”访问有关,或者他们试图在 function 的 scope 之外获取 object。在这种情况下,我不认为我正在做任何事情这些,但如果我错了请告诉我。 Thanks谢谢

Solution解决方案

You can call the toObject method in order to access the fields.您可以调用toObject方法以访问字段。 For example:例如:

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

Why为什么

As you point out that the real fields are stored in the _doc field of the document .正如您指出的那样,实际字段存储在文档的_doc字段中

But why console.log(item) => { title: "foo", content: "bar" } ?但是为什么console.log(item) => { title: "foo", content: "bar" }

From the source code of mongoose(document.js) , we can find that the toString method of Document call the toObject method.toObject (document.js) 的源码中可以发现DocumenttoString方法调用了toObject方法。 So console.log will show fields 'correctly'.所以console.log将“正确”显示字段。 The source code is shown below:源代码如下所示:

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

Make sure that you have defined title in your schema:确保您在架构中定义了标题:

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

Try performing a for in loop over item and see if you can access values.尝试对item执行for in循环,看看您是否可以访问值。

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

If it works, it would mean your keys have some non-printable characters or something like this.如果它有效,则意味着您的密钥有一些non-printable字符或类似的东西。

From what you said in the comments, it looks like somehow item is an instance of a String primitive wrapper.从您在评论中所说的来看,它似乎以某种方式itemString原始包装器的实例。

Eg例如

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

To verify this theory, try this:为了验证这个理论,试试这个:

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

It could also be that item is an object that has a toString method that displays what you see.也可能是item是一个具有toString方法的对象,该方法显示您所看到的内容。

EDIT: To identify these issues quickly, you can use console.dir instead of console.log , since it display an interactive list of the object properties.编辑:要快速识别这些问题,您可以使用console.dir而不是console.log ,因为它显示对象属性的交互式列表。 You can also but a breakpoint and add a watch.您也可以只设置一个断点并添加一个监视。

Old question, but since I had a problem with this too, I'll answer it.老问题,但因为我也有这个问题,我会回答它。
This probably happened because you're using find() instead of findOne() .这可能是因为您使用的是find()而不是findOne() So in the end, you're calling a method for an array of documents instead of a document, resulting in finding an array and not a single document.所以最后,你是为一个文档数组而不是一个文档调用一个方法,导致找到一个数组而不是单个文档。 Using findOne() will let you get access the object normally.使用findOne()可以让您正常访问对象。

Use findOne() instead of find() .使用findOne()而不是find()

The find() method returns an array of values, even if you have only one possible result, you'll need to use item[0] to get it. find()方法返回一组值,即使您只有一个可能的结果,您也需要使用 item[0] 来获取它。

The findOne method returns one object or none, then you'll be able to access its properties with no issues. findOne方法返回一个对象或不返回一个对象,然后您就可以毫无问题地访问其属性。

A better way to tackle an issue like this is using doc.toObject() like this解决此类问题的更好方法是像这样使用doc.toObject()

doc.toObject({ getters: true })

other options include:其他选项包括:

  • getters: apply all getters (path and virtual getters) getters:应用所有 getters(路径和虚拟 getters)
  • virtuals: apply virtual getters (can override getters option) virtuals:应用虚拟吸气剂(可以覆盖吸气剂选项)
  • minimize: remove empty objects (defaults to true) minimize:删除空对象(默认为真)
  • transform: a transform function to apply to the resulting document before returning transform:在返回之前应用于结果文档的转换函数
  • depopulate: depopulate any populated paths, replacing them with their original refs (defaults to false) depopulate:人口任何填充的路径,用它们的原始引用替换它们(默认为false)
  • versionKey: whether to include the version key (defaults to true) versionKey:是否包含版本密钥(默认为true)

so for example you can say所以例如你可以说

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

and now it will work现在它会起作用

You don't have whitespace or funny characters in ' title' , do you? ' title'没有空格或有趣的字符,是吗? They can be defined if you've quoted identifiers into the object/map definition.如果您在对象/地图定义中引用了标识符,则可以定义它们。 For example:例如:

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

That might cause console.log(item) to display similar to what you're expecting, but cause your undefined problem when you access the title property without it's preceding space.这可能会导致console.log(item)显示与您期望的类似,但是当您访问title属性而没有前面的空格时会导致您undefined问题。

I think using 'find' method returns an array of Documents.I tried this and I was able to print the title我认为使用'find'方法返回一个文档数组。我试过这个,我能够打印标题

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

If you only want to get the info without all mongoose benefits, save ie, you can use .lean() in your query.如果您只想在没有猫鼬所有好处的情况下获取信息,请保存即,您可以在查询中使用 .lean() 。 It will get your info quicker and you'll can use it as an object directly.它将更快地获取您的信息,您可以直接将其用作对象。

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

As says in docs, this is the best to read-only scenarios.正如文档中所说,这是只读场景的最佳选择。

Are you initializing your object?你在初始化你的对象吗?

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

var myo1 = new MyObject();

If you do not initialize or have not set a title.如果没有初始化或者没有设置标题。 You will get undefined.你会得到未定义。

当您进行周二查询时,请使用.lean()例如

const order = await Order.findId("84578437").lean()

find returns an array of object, so to access element use indexing, like doc[0].title find 返回 object 的数组,因此要使用索引访问元素,如doc[0].title

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM