diff --git a/lib/aggregate.js b/lib/aggregate.js index 7faea5eeb66..a506cf20cf0 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -13,7 +13,7 @@ const readConcern = Query.prototype.readConcern; /** * Aggregate constructor used for building aggregation pipelines. Do not - * instantiate this class directly, use [Model.aggregate()](/docs/api.html#aggregate_aggregate) instead. + * instantiate this class directly, use [Model.aggregate()](/docs/api.html#model_Model.aggregate) instead. * * ####Example: * diff --git a/lib/helpers/query/castUpdate.js b/lib/helpers/query/castUpdate.js index d0fe88955c6..7cd9c5aa5ad 100644 --- a/lib/helpers/query/castUpdate.js +++ b/lib/helpers/query/castUpdate.js @@ -411,7 +411,7 @@ function castUpdateVal(schema, val, op, $conditional, context, path) { return schema.castForQueryWrapper({ val: val, context: context, - $skipQueryCastForUpdate: val != null && schema.$isMongooseArray + $skipQueryCastForUpdate: val != null && schema.$isMongooseArray && schema.$parentSchema }); } diff --git a/lib/schema.js b/lib/schema.js index f6550e3a28d..8afef3ca9e1 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -853,8 +853,12 @@ Schema.prototype.hasMixedParent = function(path) { * @api private */ Schema.prototype.setupTimestamp = function(timestamps) { - const childHasTimestamp = this.childSchemas. - find(s => s.schema.options.timestamps != null); + const childHasTimestamp = this.childSchemas.find(withTimestamp); + + function withTimestamp(s) { + const ts = s.schema.options.timestamps; + return ts == true || ts == null; + } if (!timestamps && !childHasTimestamp) { return; diff --git a/test/model.update.test.js b/test/model.update.test.js index 9ce93be7409..d18efa7d9dd 100644 --- a/test/model.update.test.js +++ b/test/model.update.test.js @@ -2536,6 +2536,48 @@ describe('model: update:', function() { catch(done); }); + it('doesn\'t skip casting the query on nested arrays (gh-7098)', function() { + const nestedSchema = new Schema({ + xyz: [[Number]] + }); + const schema = new Schema({ + xyz: [[{ type: Number }]], + nested: nestedSchema + }); + + const Model = db.model('gh-7098', schema); + + const test = new Model({ + xyz: [ + [0, 1], + [2, 3], + [4, 5] + ], + nested: { + xyz: [ + [0, 1], + [2, 3], + [4, 5] + ], + } + }); + + const cond = { _id: test._id }; + const update = { $set: { 'xyz.1.0': '200', 'nested.xyz.1.0': '200' } }; + const opts = { new: true }; + + return co(function*() { + let inserted = yield test.save(); + inserted = inserted.toObject(); + assert.deepStrictEqual(inserted.xyz, [[0, 1], [2, 3], [4, 5]]); + assert.deepStrictEqual(inserted.nested.xyz, [[0, 1], [2, 3], [4, 5]]); + let updated = yield Model.findOneAndUpdate(cond, update, opts); + updated = updated.toObject(); + assert.deepStrictEqual(updated.xyz, [[0, 1], [200, 3], [4, 5]]); + assert.deepStrictEqual(updated.nested.xyz, [[0, 1], [200, 3], [4, 5]]); + }); + }); + it('defaults with overwrite and no update validators (gh-5384)', function(done) { const testSchema = new mongoose.Schema({ name: String, diff --git a/test/timestamps.test.js b/test/timestamps.test.js index fe0564e3ef8..8c574dbd0ba 100644 --- a/test/timestamps.test.js +++ b/test/timestamps.test.js @@ -4,6 +4,7 @@ const assert = require('assert'); const start = require('./common'); const mongoose = start.mongoose; +const Schema = mongoose.Schema; describe('timestamps', function() { let db; @@ -162,4 +163,21 @@ describe('timestamps', function() { }); }); }); + + it('no timestamps added when parent/child timestamps explicitly false (gh-7202)', function(done) { + const subSchema = new Schema({}, { timestamps: false }); + const schema = new Schema({ sub: subSchema }, { timestamps: false }); + + const Test = db.model('gh7202', schema); + const test = new Test({ sub: {} }); + + test.save((err, saved) => { + assert.ifError(err); + assert.strictEqual(saved.createdAt, undefined); + assert.strictEqual(saved.updatedAt, undefined); + assert.strictEqual(saved.sub.createdAt, undefined); + assert.strictEqual(saved.sub.updatedAt, undefined); + done(); + }); + }); });