Mongoose: what's up with "

It seems Mongoose is doing something really funky internally.

1 var Foo = new mongoose.model('Foo', new mongoose.Schema({a: String, b: Number}));
2 var foo = new Foo({a: 'test; b: 42}); 
3 var obj = {c: 1};
4 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

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

Essentially, any time you try to deal with properties of a Mongoose model that arn't a) defined in the model's schema or b) defined as the same type (array, obj, ..) ... the model doesn't even behave like a normal Javascript object.

Switching line 4 to foo._doc.goo = obj makes the console output true .

edit : trying to reproduce weirdness

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

Update

Maybe I misunderstood your original question, but now it looks like the nature of your question changed, so the below information isn't relevant, but I'm leaving it. :)

I tested your code and it works fine for me. Mongoose doesn't execute any special code when you set properties that aren't part of the schema (or a few other special properties). JavaScript currently doesn't support calling code for properties that don't yet exist (so Mongoose can't get in the way of the set of the goo property for example).

So, when you set the property:

foo.goo = { c: 1 };

Mongoose isn't involved. If your console.log was something other than the code you displayed, I could see that it might report incorrectly.

Additionally, when you send the results back as JSON, JSON.stringify is being called, which calls toString on your Mongoose Model. When that happens, Mongoose only uses the properties defined on the schema. So, no additional properties are being sent back by default. You've changed the nature of the data array though to directly point at the Mongoose data, so it avoids that problem.

Details about normal behavior

When you set the property goo using Mongoose, quite a few things happen. Mongoose creates property getters/setters via the Object.defineProperty (some docs). So, when you set the goo property, which you've defined as a [String] , a few things happen:

  • Mongoose code is called prior to the value being set onto the object instance (unlike a simple JavaScript object)
  • Mongoose creates an array (optionally) to store the data (a MongooseArray ) which will contain the array data. In the example you provided, since you didn't pass an array, it will be created.
  • Mongoose will attempt to cast your data to the right type
  • It will call toString on the data passed as part of the cast.
  • So, the results are that the document now contains an array with a toString version of the object you passed.

    If you checked the contents of the goo property, you'd see that it's now an array with a single element, which is a string that contains [object Object] . If you'd picked a more basic type or matched the destination property storage type, you would see that a basic equality check would have worked.

    链接地址: http://www.djcxy.com/p/15842.html

    上一篇: Safari图像重叠问题

    下一篇: 猫鼬:怎么了“