Skip to content

Commit

Permalink
Merge pull request #14887 from Automattic/vkarpov15/gh-3027
Browse files Browse the repository at this point in the history
feat(query): cast $rename
  • Loading branch information
vkarpov15 authored Sep 17, 2024
2 parents 9705e73 + 176fb38 commit 32f8003
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
23 changes: 20 additions & 3 deletions lib/helpers/query/castUpdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const CastError = require('../../error/cast');
const MongooseError = require('../../error/mongooseError');
const SchemaString = require('../../schema/string');
const StrictModeError = require('../../error/strict');
const ValidationError = require('../../error/validation');
const castNumber = require('../../cast/number');
Expand Down Expand Up @@ -307,6 +308,20 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
continue;
}

hasKeys = true;
} else if (op === '$rename') {
const schematype = new SchemaString(`${prefix}${key}.$rename`);
try {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
} catch (error) {
aggregatedError = _appendError(error, context, key, aggregatedError);
}

if (obj[key] === void 0) {
delete obj[key];
continue;
}

hasKeys = true;
} else {
const pathToCheck = (prefix + key);
Expand Down Expand Up @@ -372,10 +387,12 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
delete obj[key];
}
} else {
// gh-1845 temporary fix: ignore $rename. See gh-3027 for tracking
// improving this.
if (op === '$rename') {
hasKeys = true;
if (obj[key] == null) {
throw new CastError('String', obj[key], `${prefix}${key}.$rename`);
}
const schematype = new SchemaString(`${prefix}${key}.$rename`);
obj[key] = schematype.castForQuery(null, obj[key], context);
continue;
}

Expand Down
26 changes: 23 additions & 3 deletions test/model.updateOne.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1078,9 +1078,29 @@ describe('model: updateOne:', function() {
const Model = db.model('Test', schema);

const update = { $rename: { foo: 'bar' } };
await Model.create({ foo: Date.now() });
const res = await Model.updateOne({}, update, { multi: true });
assert.equal(res.modifiedCount, 1);
const foo = Date.now();
const { _id } = await Model.create({ foo });
await Model.updateOne({}, update);
const doc = await Model.findById(_id);
assert.equal(doc.bar.valueOf(), foo.valueOf());
assert.equal(doc.foo, undefined);
});

it('throws CastError if $rename fails to cast to string (gh-1845)', async function() {
const schema = new Schema({ foo: Date, bar: Date });
const Model = db.model('Test', schema);

let err = await Model.updateOne({}, { $rename: { foo: { prop: 'baz' } } }).then(() => null, err => err);
assert.equal(err.name, 'CastError');
assert.ok(err.message.includes('foo.$rename'));

err = await Model.updateOne({}, { $rename: { foo: null } }).then(() => null, err => err);
assert.equal(err.name, 'CastError');
assert.ok(err.message.includes('foo.$rename'));

err = await Model.updateOne({}, { $rename: { foo: undefined } }).then(() => null, err => err);
assert.equal(err.name, 'CastError');
assert.ok(err.message.includes('foo.$rename'));
});

it('allows objects with positional operator (gh-3185)', async function() {
Expand Down

0 comments on commit 32f8003

Please sign in to comment.