32

Mongoose は、内部で非常にファンキーなことを行っているようです。

var Foo = new mongoose.model('Foo', new mongoose.Schema({a: String, b: Number}));
var foo = new Foo({a: 'test'; b: 42}); 
var obj = {c: 1};
foo.goo = obj;                  // simple object assignment. obj should be 
                                  //   passed by reference to foo.goo. recall goo
                                  //   is not defined in the Foo model schema

console.log(foo.goo === obj);   // comparison directly after the assignment
    // => false, doesn't behave like normal JS object

基本的に、Mongoose モデルのプロパティを処理しようとすると、

a) モデルのスキーマで定義されている、または

b) 同じ型 (array、obj、..) として定義されている ... モデルは通常の Javascript オブジェクトのようには動作しません。

4行目を に切り替えるfoo._doc.goo = objと、コンソール出力が になりますtrue

編集:奇妙さを再現しようとしています

例 1 :

 // Customer has a property 'name', but no property 'text'
 // I do this because I need to transform my data slightly before sending it
 // to client.
 models.Customer.find({}, function(err, data) {
     for (var i=0, len=data.length; i<len; ++i) {
        data[i] = data[i]._doc;            // if I don't do this, returned data
                                           // has no 'text' property
        data[i].text = data[i].name;       
    }
    res.json({success: err, response:data});
});
4

7 に答える 7

9

アップデート

元の質問を誤解したのかもしれませんが、質問の性質が変わったようですので、以下の情報は関係ありませんが、残します。:)

私はあなたのコードをテストしましたが、うまくいきました。スキーマの一部ではないプロパティ (またはその他のいくつかの特別なプロパティ) を設定しても、Mongoose は特別なコードを実行しません。gooJavaScript は現在、まだ存在しないプロパティのコードの呼び出しをサポートしていません (たとえば 、Mongoose がプロパティのセットを邪魔することはありません)。

したがって、プロパティを設定すると、次のようになります。

foo.goo = { c: 1 };

マングースは関係ありません。表示されたコードとは異なるものである場合、console.log誤って報告される可能性があることがわかりました。

さらに、send結果が JSON として返されると、 Mongoose モデルJSON.stringifyが呼び出されます。toStringその場合、Mongoose はスキーマで定義されたプロパティのみを使用します。そのため、デフォルトでは、追加のプロパティは返されません。dataただし、Mongoose データを直接指すように配列の性質を変更したため、その問題は回避されます。

通常動作の詳細

Mongoose を使用してプロパティを設定するとgoo、かなりのことが起こります。Mongoose は、Object.defineProperty(一部のドキュメント) を介してプロパティのゲッター/セッターを作成します。したがって、gooとして定義したプロパティを設定する[String]と、いくつかのことが起こります。

  1. Mongoose コードは、値がオブジェクト インスタンスに設定される前に呼び出されます (単純な JavaScript オブジェクトとは異なります)。
  2. Mongoose は、(オプションで) 配列を作成してMongooseArray、配列データを含むデータ (a ) を格納します。提供した例では、配列を渡さなかったため、作成されます。
  3. Mongoose は、データを正しい型にキャストしようとします
  4. toStringキャストの一部として渡されたデータを呼び出します。

その結果、toString渡したオブジェクトのバージョンを含む配列がドキュメントに含まれるようになります。

プロパティの内容を確認するgooと、1 つの要素を持つ配列になっていることがわかります。これは、 を含む文字列です[object Object]。より基本的なタイプを選択するか、宛先プロパティ ストレージ タイプと一致する場合は、基本的な等価性チェックが機能することがわかります。

于 2013-09-16T16:19:21.267 に答える