Поля результатов Mongoose/MongoDB в Javascript не определены

есть ли что-то, что мне не хватает, что позволило бы элементу регистрироваться как объект с параметром, но когда я пытаюсь получить доступ к этому параметру, он не определен?

что я пробовал до сих пор:

  • console.log(item) =>{ title: "foo", content: "bar" } это нормально
  • console.log(typeof item) => объект
  • console.log(item.title) = > "undefined"

я включу некоторые из контекста на всякий случай, если это имеет отношение к проблеме.

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 до этой линии, чтобы проверить, что элемент на самом деле через узел отладчика.расх. Вот что я нашел : http://hastebin.com/qatireweni.sm

из этого я пробовал console.log(item._doc.title) и он работает просто отлично.. Теперь это больше похоже на вопрос мангуста, чем на что-либо другое.

есть вопросы, подобные этому, но они, похоже, связаны с "этим" доступом к объектам или они пытаются получить объект за пределами области действия функции. В этом случае я не думаю, что делаю что-то из этого, но сообщите мне, если я ошибаюсь. Спасибо

9 ответов


решение

можно назвать toObject метод для доступа к полям. Например:

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

почему

как вы указали, что реальные поля хранятся в _doc поле документа.

а зачем console.log(item) =>{ title: "foo", content: "bar" }?

С исходный код мангуста(документ.в 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());
};

убедитесь, что вы определили название в схеме:

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

попробуйте for in цикл item и посмотреть, если вы можете получить доступ к ценностям.

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

если он работает, это будет означать, что ваши ключи имеют некоторые non-printable символы или что-то подобное.

от того, что вы сказали в комментариях, это выглядит как-то item экземпляр String примитивный фантик.

Е. Г.

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

чтобы проверить эту теорию, попробуйте это:

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

это также может быть, что item - это объект, который имеет toString метод, который отображает то, что вы видите.

EDIT:чтобы быстро определить эти проблемы, вы можете использовать console.dir вместо console.log, так как он отображает интерактивный список свойств объекта. Вы также можете только точку останова и добавить часы.


у вас нет пробелов или забавных персонажей в ' title', да? Они могут быть определены, если вы ввели идентификаторы в определение объекта/карты. Например:

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

что может вызвать console.log(item) для отображения аналогично тому, что вы ожидаете, но вызвать ваш undefined проблема при доступе к 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);
}

старый вопрос, но так как у меня тоже была проблема с этим, я отвечу на него.
Вероятно, это произошло потому, что вы используете find() вместо findOne(). Таким образом, в конце концов вы вызываете метод для массива документов вместо документа, в результате чего находите массив, а не один документ. Используя findOne() позволит вам получить доступ к объекту нормально.


использовать findOne() вместо find().

на find() метод возвращает массив значений, даже если у вас есть только один возможный результат, вам нужно будет использовать item[0], чтобы получить его.

на findOne метод возвращает один объект или нет, тогда вы сможете получить доступ к его свойствам без проблем.


вы инициализируете свой объект?

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

var myo1 = new MyObject();

Если вы не инициализируете или не установили заголовок. Вы получите неопределенность.


лучший способ решить такую проблему-использовать doc.toObject() такой

doc.toObject({ getters: true })

другие функции включают в себя:

  • getters: применить все геттеры (путь и виртуальные геттеры)
  • 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
   }
})

и теперь он будет работать