it-swarm.com.de

Mongoose/MongoDB-Ergebnisfelder werden in Javascript undefiniert angezeigt

Gibt es etwas, was ich vermisse, das es einem Element erlauben würde, sich als Objekt mit einem Parameter zu protokollieren, aber wenn ich versuche, auf diesen Parameter zuzugreifen, ist er undefiniert.

Was ich bisher ausprobiert habe:

  • console.log(item) => { title: "foo", content: "bar" }, das ist in Ordnung
  • console.log(typeof item) => Objekt
  • console.log(item.title) => "undefined"

Ich werde etwas von dem Kontext einschließen, falls es für das Problem relevant ist.

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

Basierend auf einem Vorschlag habe ich debugger vor dieser Zeile abgelegt, um zu prüfen, ob das Element tatsächlich über den Node-Repl-Debugger ist. Folgendes habe ich gefunden: http://hastebin.com/qatireweni.sm

Von hier aus habe ich console.log(item._doc.title) ausprobiert und es funktioniert einwandfrei .. Also, dies scheint jetzt eher wie eine Mungo-Frage als alles andere.

Es gibt ähnliche Fragen wie diese, aber sie scheinen sich auf den Zugriff auf Objekte zu beziehen, die auf diese Objekte zugreifen, oder sie versuchen, das Objekt außerhalb des Funktionsbereichs der Funktion zu erhalten. In diesem Fall glaube ich nicht, dass ich beide mache, aber informiere mich, wenn ich falsch liege. Vielen Dank

24
tippenein

Lösung

Sie können die Methode toObject aufrufen, um auf die Felder zuzugreifen. Zum Beispiel:

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

Warum

Wenn Sie darauf hinweisen, dass die realen Felder im Feld _doc des Dokuments gespeichert sind .

Aber warum console.log(item) => { title: "foo", content: "bar" }?

Aus dem Quellcode von mongoose (document.js) können wir feststellen, dass die toString-Methode von Document die toObject-Methode aufruft. console.log zeigt die Felder also "korrekt" an. Der Quellcode wird unten gezeigt:

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

Stellen Sie sicher, dass Sie den Titel in Ihrem Schema definiert haben:

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

Versuchen Sie, eine for in-Schleife über item auszuführen, und prüfen Sie, ob Sie auf Werte zugreifen können.

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

Wenn es funktioniert, bedeutet dies, dass Ihre Schlüssel non-printable-Zeichen oder ähnliches haben.

Nach dem, was Sie in den Kommentaren gesagt haben, sieht es aus, als wäre item eine Instanz eines String primitiven Wrappers.

Z.B. 

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

Um diese Theorie zu überprüfen, versuchen Sie Folgendes:

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

Es kann auch sein, dass item ein Objekt ist, das über eine toString-Methode verfügt, die anzeigt, was Sie sehen.

BEARBEITEN: Um diese Probleme schnell zu erkennen, können Sie console.dir anstelle von console.log verwenden, da hier eine interaktive Liste der Objekteigenschaften angezeigt wird. Sie können aber auch einen Haltepunkt und eine Uhr hinzufügen.

4
plalx

Ich glaube, die 'find'-Methode gibt ein Array von Dokumenten zurück. Ich habe es versucht und konnte den Titel ausdrucken

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

Sie haben kein Leerzeichen oder lustige Zeichen in ' title', oder? Sie können definiert werden, wenn Sie Bezeichner in der Objekt-/Map-Definition angegeben haben. Zum Beispiel:

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

Dies kann dazu führen, dass console.log(item) ähnlich angezeigt wird, was Sie erwarten, aber das undefined-Problem verursacht, wenn Sie auf die title-Eigenschaft ohne vorausgehenden Speicherplatz zugreifen.

2
Thomas W

Alte Frage, aber da ich auch ein Problem damit hatte, werde ich es beantworten.
Dies ist wahrscheinlich darauf zurückzuführen, dass Sie find() anstelle von findOne() verwenden. Am Ende rufen Sie eine Methode für ein Array von Dokumenten anstelle eines Dokuments auf, wodurch ein Array und nicht ein einzelnes Dokument gefunden wird. Mit findOne() erhalten Sie normalerweise Zugriff auf das Objekt.

2
user5887278

Wenn Sie nur die Informationen ohne alle Vorteile von mongoose abrufen möchten, speichern Sie d. H. Sie können .lean () in Ihrer Abfrage verwenden. Ihre Informationen werden schneller erhalten und Sie können sie direkt als Objekt verwenden.

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

Wie in Dokumenten beschrieben, ist dies das beste Szenario, das nur gelesen werden kann.

1
LordRasta

Verwenden Sie findOne() anstelle von find().

Die find()-Methode gibt ein Array von Werten zurück, selbst wenn Sie nur ein mögliches Ergebnis haben, müssen Sie item [0] verwenden, um es zu erhalten.

Die findOne-Methode gibt ein Objekt oder keines zurück. Sie können dann ohne Probleme auf die Eigenschaften zugreifen.

1
George

Initialisieren Sie Ihr Objekt?

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

var myo1 = new MyObject();

Wenn Sie nicht initialisieren oder keinen Titel festgelegt haben. Sie werden undefiniert erhalten.

0
Valamas

Ein besserer Weg, um ein Problem wie dieses zu lösen, ist die Verwendung von doc.toObject()

doc.toObject({ getters: true })

weitere Optionen sind:

  • getters: alle Getter anwenden (Pfad und virtuelle Getter)
  • virtuals: virtuelle Getter anwenden (kann die Getter-Option außer Kraft setzen)
  • minimize: entferne leere Objekte (Standardeinstellung ist true)
  • transform: eine Transformationsfunktion, die vor der Rückgabe auf das resultierende Dokument angewendet werden soll
  • depopulate: entvölkere alle aufgefüllten Pfade und ersetze sie durch ihre ursprünglichen Refs (Standardeinstellung ist false)
  • versionKey:, ob der Versionsschlüssel enthalten sein soll (Standardeinstellung ist "true")

so kann man zum beispiel sagen 

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

und jetzt wird es funktionieren

0
Jalasem