Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixed; depopulation of mixed documents

closes #1471
  • Loading branch information...
commit 66e222408af6f9eaada00dc9bbfea806a1da569e 1 parent fb5d602
@aheckmann aheckmann authored
View
10 lib/document.js
@@ -1427,12 +1427,9 @@ Document.prototype.$__doQueue = function () {
*/
Document.prototype.toObject = function (options) {
- if (options && options.depopulate && !options.isParent) {
- // populated paths that we set to a document?
- Embedded || (Embedded = require('./types/embedded'));
- if (!(this instanceof Embedded)) {
- return clone(this._id, options);
- }
+ if (options && options.depopulate && this.$__.wasPopulated) {
+ // populated paths that we set to a document
+ return clone(this._id, options);
}
// When internally saving this document we always pass options,
@@ -1444,7 +1441,6 @@ Document.prototype.toObject = function (options) {
}
;('minimize' in options) || (options.minimize = this.schema.options.minimize);
- options.isParent = false;
var ret = clone(this._doc, options);
View
5 lib/internal.js
@@ -19,8 +19,9 @@ function InternalCache () {
this.version = undefined;
this.getters = {};
this._id = undefined;
- this.populate = undefined;
- this.populated = undefined;
+ this.populate = undefined; // what we want to populate in this doc
+ this.populated = undefined;// the _ids that have been populated
+ this.wasPopulated = false; // if this doc was the result of a population
this.scope = undefined;
this.activePaths = new ActiveRoster;
View
6 lib/model.js
@@ -170,7 +170,7 @@ Model.prototype.save = function save (fn) {
if (this.isNew) {
// send entire doc
- var obj = this.toObject({ depopulate: 1, isParent: 1 });
+ var obj = this.toObject({ depopulate: 1 });
this.$__version(true, obj);
this.collection.insert(obj, options, complete);
this.$__reset();
@@ -1867,6 +1867,7 @@ function populate (model, docs, options, cb) {
Model.find(match, select, options.options, function (err, vals) {
if (err) return cb(err);
+ var lean = options.options && options.options.lean;
var len = vals.length;
var rawOrder = {};
var rawDocs = {}
@@ -1881,6 +1882,9 @@ function populate (model, docs, options, cb) {
key = String(utils.getValue('_id', val));
rawDocs[key] = val;
rawOrder[key] = i;
+
+ // flag each as result of population
+ if (!lean) val.$__.wasPopulated = true;
}
assignVals({
View
8 lib/schema/buffer.js
@@ -56,10 +56,15 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document
+ if (null == value) {
+ return value;
+ }
+
// lazy load
Document || (Document = require('./../document'));
- if (value instanceof Document || null == value) {
+ if (value instanceof Document) {
+ value.$__.wasPopulated = true;
return value;
}
@@ -77,6 +82,7 @@ SchemaBuffer.prototype.cast = function (value, doc, init) {
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
var ret = new pop.options.model(value);
+ ret.$__.wasPopulated = true;
return ret;
}
View
11 lib/schema/number.js
@@ -115,10 +115,15 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document
+ if (null == value) {
+ return value;
+ }
+
// lazy load
Document || (Document = require('./../document'));
- if (value instanceof Document || null == value) {
+ if (value instanceof Document) {
+ value.$__.wasPopulated = true;
return value;
}
@@ -135,7 +140,9 @@ SchemaNumber.prototype.cast = function (value, doc, init) {
var path = doc.$__fullPath(this.path);
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
- return new pop.options.model(value);
+ var ret = new pop.options.model(value);
+ ret.$__.wasPopulated = true;
+ return ret;
}
var val = value && value._id
View
11 lib/schema/objectid.js
@@ -55,10 +55,15 @@ ObjectId.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document
+ if (null == value) {
+ return value;
+ }
+
// lazy load
Document || (Document = require('./../document'));
- if (value instanceof Document || null == value) {
+ if (value instanceof Document) {
+ value.$__.wasPopulated = true;
return value;
}
@@ -75,7 +80,9 @@ ObjectId.prototype.cast = function (value, doc, init) {
var path = doc.$__fullPath(this.path);
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
- return new pop.options.model(value);
+ var ret = new pop.options.model(value);
+ ret.$__.wasPopulated = true;
+ return ret;
}
if (value === null) return value;
View
11 lib/schema/string.js
@@ -197,10 +197,15 @@ SchemaString.prototype.cast = function (value, doc, init) {
if (SchemaType._isRef(this, value, doc, init)) {
// wait! we may need to cast this to a document
+ if (null == value) {
+ return value;
+ }
+
// lazy load
Document || (Document = require('./../document'));
- if (value instanceof Document || null == value) {
+ if (value instanceof Document) {
+ value.$__.wasPopulated = true;
return value;
}
@@ -217,7 +222,9 @@ SchemaString.prototype.cast = function (value, doc, init) {
var path = doc.$__fullPath(this.path);
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
var pop = owner.populated(path, true);
- return new pop.options.model(value);
+ var ret = new pop.options.model(value);
+ ret.$__.wasPopulated = true;
+ return ret;
}
if (value === null) {
View
5 lib/types/array.js
@@ -634,14 +634,13 @@ MongooseArray.prototype.set = function set (i, val) {
MongooseArray.prototype.toObject = function (options) {
if (options && options.depopulate) {
return this.map(function (doc) {
- // this is called on populated arrays too
return doc instanceof Document
- ? doc._id
+ ? doc.toObject(options)
: doc
});
}
- return this.slice()
+ return this.slice();
}
/**
View
58 test/model.populate.test.js
@@ -2298,4 +2298,62 @@ describe('model: populate:', function(){
});
});
})
+
+ describe('leaves Documents within Mixed properties alone (gh-1471)', function(){
+ var db;
+ var Cat;
+ var Litter;
+
+ before(function(){
+ db = start();
+ Cat = db.model('cats', new Schema({ name: String }));
+ var litterSchema = new Schema({name: String, cats: {}, o: {}, a: []});
+ Litter = db.model('litters', litterSchema);
+ });
+
+ after(function(done){
+ db.close(done);
+ });
+
+ it('when saving new docs', function(done){
+ Cat.create({name:'new1'},{name:'new2'},{name:'new3'}, function (err, a, b, c) {
+ if (err) return done(err);
+
+ Litter.create({
+ name: 'new'
+ , cats:[a]
+ , o: b
+ , a: [c]
+ }, confirm(done));
+ })
+ })
+
+ it('when saving existing docs 5T5', function(done){
+ Cat.create({name:'ex1'},{name:'ex2'},{name:'ex3'}, function (err, a, b, c) {
+ if (err) return done(err);
+
+ Litter.create({name:'existing'}, function (err, doc) {
+ doc.cats = [a];
+ doc.o = b;
+ doc.a = [c]
+ doc.save(confirm(done));
+ });
+ });
+ })
+
+ function confirm (done) {
+ return function (err, litter) {
+ if (err) return done(err);
+ Litter.findById(litter).lean().exec(function (err, doc) {
+ if (err) return done(err);
+ assert.ok(doc.o._id);
+ assert.ok(doc.cats[0]);
+ assert.ok(doc.cats[0]._id);
+ assert.ok(doc.a[0]);
+ assert.ok(doc.a[0]._id);
+ done();
+ })
+ }
+ }
+ })
});

0 comments on commit 66e2224

Please sign in to comment.
Something went wrong with that request. Please try again.