Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add mongoose default option to set returnOriginal #9189

Merged
merged 12 commits into from Jul 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -147,6 +147,7 @@ Mongoose.prototype.driver = require('./driver');
*
* Currently supported options are:
* - 'debug': If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arugments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
* - 'returnOriginal': If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`, `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to setting the `new` option to `true` for `findOneAndX()` calls by default. Read our [`findOneAndUpdate()` tutorial](/docs/tutorials/findoneandupdate.html) for more information.
* - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
* - 'useCreateIndex': false by default. Set to `true` to make Mongoose's default index build use `createIndex()` instead of `ensureIndex()` to avoid deprecation warnings from the MongoDB driver.
* - 'useFindAndModify': true by default. Set to `false` to make `findOneAndUpdate()` and `findOneAndRemove()` use native `findOneAndUpdate()` rather than `findAndModify()`.
Expand Down
6 changes: 3 additions & 3 deletions lib/model.js
Expand Up @@ -2445,7 +2445,7 @@ Model.$where = function $where() {
* @param {Object} [conditions]
* @param {Object} [update]
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
* @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied.
* @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied. To change the default to `true`, use `mongoose.set('returnOriginal', false);`.
* @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
Expand Down Expand Up @@ -2588,7 +2588,7 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
* @param {Object|Number|String} id value of `_id` to query by
* @param {Object} [update]
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
* @param {Boolean} [options.new=false] By default, `findByIdAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied.
* @param {Boolean} [options.new=false] By default, `findByIdAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied. To change the default to `true`, use `mongoose.set('returnOriginal', false);`.
* @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
Expand Down Expand Up @@ -2787,7 +2787,7 @@ Model.findByIdAndDelete = function(id, options, callback) {
* @param {Object} filter Replace the first document that matches this filter
* @param {Object} [replacement] Replace with this document
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
* @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied.
* @param {Boolean} [options.new=false] By default, `findOneAndReplace()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndReplace()` will instead give you the object after `update` was applied. To change the default to `true`, use `mongoose.set('returnOriginal', false);`.
* @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
* @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
Expand Down
36 changes: 24 additions & 12 deletions lib/query.js
Expand Up @@ -3004,20 +3004,25 @@ Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) {
this._mergeUpdate(doc);
}

if (options) {
options = utils.clone(options);
if (options.projection) {
this.select(options.projection);
delete options.projection;
}
if (options.fields) {
this.select(options.fields);
delete options.fields;
}
options = options ? utils.clone(options) : {};

this.setOptions(options);
if (options.projection) {
this.select(options.projection);
delete options.projection;
}
if (options.fields) {
this.select(options.fields);
delete options.fields;
}


const returnOriginal = get(this, 'model.base.options.returnOriginal');
if (options.returnOriginal == null && returnOriginal != null) {
options.returnOriginal = returnOriginal;
}

this.setOptions(options);

if (!callback) {
return this;
}
Expand Down Expand Up @@ -3335,7 +3340,14 @@ Query.prototype.findOneAndReplace = function(filter, replacement, options, callb
this._mergeUpdate(replacement);
}

options && this.setOptions(options);
options = options || {};

const returnOriginal = get(this, 'model.base.options.returnOriginal');
if (options.returnOriginal == null && returnOriginal != null) {
options.returnOriginal = returnOriginal;
}

this.setOptions(options);

if (!callback) {
return this;
Expand Down
5 changes: 3 additions & 2 deletions lib/validoptions.js
Expand Up @@ -14,19 +14,20 @@ const VALID_OPTIONS = Object.freeze([
'debug',
'maxTimeMS',
'objectIdGetter',
'returnOriginal',
'runValidators',
'selectPopulatedPaths',
'setDefaultsOnInsert',
'strict',
'strictQuery',
'toJSON',
'toObject',
'typePojoToMixed',
'useCreateIndex',
'useFindAndModify',
'useNewUrlParser',
'usePushEach',
'useUnifiedTopology',
'typePojoToMixed'
'useUnifiedTopology'
]);

module.exports = VALID_OPTIONS;
53 changes: 53 additions & 0 deletions test/model.test.js
Expand Up @@ -6868,4 +6868,57 @@ describe('Model', function() {
assert.deepEqual(user.friends, ['Sam']);
});
});

describe('returnOriginal (gh-9183)', function() {
const originalValue = mongoose.get('returnOriginal');
beforeEach(() => {
mongoose.set('returnOriginal', false);
});

afterEach(() => {
mongoose.set('returnOriginal', originalValue);
});

it('Setting `returnOriginal` works', function() {
return co(function*() {
const userSchema = new Schema({
name: { type: String }
});

const User = db.model('User', userSchema);

const createdUser = yield User.create({ name: 'Hafez' });

const user1 = yield User.findOneAndUpdate({ _id: createdUser._id }, { name: 'Hafez1' });
assert.equal(user1.name, 'Hafez1');

const user2 = yield User.findByIdAndUpdate(createdUser._id, { name: 'Hafez2' });
assert.equal(user2.name, 'Hafez2');

const user3 = yield User.findOneAndReplace({ _id: createdUser._id }, { name: 'Hafez3' });
assert.equal(user3.name, 'Hafez3');
});
});

it('`returnOriginal` can be overwritten', function() {
return co(function*() {
const userSchema = new Schema({
name: { type: String }
});

const User = db.model('User', userSchema);

const createdUser = yield User.create({ name: 'Hafez' });

const user1 = yield User.findOneAndUpdate({ _id: createdUser._id }, { name: 'Hafez1' }, { new: false });
assert.equal(user1.name, 'Hafez');

const user2 = yield User.findByIdAndUpdate(createdUser._id, { name: 'Hafez2' }, { new: false });
assert.equal(user2.name, 'Hafez1');

const user3 = yield User.findOneAndReplace({ _id: createdUser._id }, { name: 'Hafez3' }, { new: false });
AbdelrahmanHafez marked this conversation as resolved.
Show resolved Hide resolved
assert.equal(user3.name, 'Hafez2');
});
});
});
});