Skip to content

Commit

Permalink
Merge pull request #13397 from Automattic/vkarpov15/gh-7511
Browse files Browse the repository at this point in the history
feat(query): add `translateAliases` option to automatically call translate aliases on query fields
  • Loading branch information
vkarpov15 authored May 15, 2023
2 parents c4977c0 + 198aec9 commit ca84162
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 13 deletions.
43 changes: 33 additions & 10 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -1855,20 +1855,24 @@ Model.discriminators;
*
* #### Example:
*
* Character
* .find(Character.translateAliases({
* '名': 'Eddard Stark' // Alias for 'name'
* })
* .exec(function(err, characters) {})
* await Character.find(Character.translateAliases({
* '名': 'Eddard Stark' // Alias for 'name'
* });
*
* By default, `translateAliases()` overwrites raw fields with aliased fields.
* So if `n` is an alias for `name`, `{ n: 'alias', name: 'raw' }` will resolve to `{ name: 'alias' }`.
* However, you can set the `errorOnDuplicates` option to throw an error if there are potentially conflicting paths.
* The `translateAliases` option for queries uses `errorOnDuplicates`.
*
* #### Note:
*
* Only translate arguments of object type anything else is returned raw
*
* @param {Object} fields fields/conditions that may contain aliased keys
* @param {Boolean} [errorOnDuplicates] if true, throw an error if there's both a key and an alias for that key in `fields`
* @return {Object} the translated 'pure' fields/conditions
*/
Model.translateAliases = function translateAliases(fields) {
Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
_checkContext(this, 'translateAliases');

const translate = (key, value) => {
Expand All @@ -1880,6 +1884,9 @@ Model.translateAliases = function translateAliases(fields) {
const name = fieldKeys[i];
if (currentSchema && currentSchema.aliases[name]) {
alias = currentSchema.aliases[name];
if (errorOnDuplicates && alias in fields) {
throw new MongooseError(`Provided object has both field "${name}" and its alias "${alias}"`);
}
// Alias found,
translated.push(alias);
} else {
Expand Down Expand Up @@ -1932,6 +1939,8 @@ Model.translateAliases = function translateAliases(fields) {
// Recursively translate nested queries
fields[key][i] = this.translateAliases(fields[key][i]);
}
} else {
this.translateAliases(fields[key]);
}
}
}
Expand Down Expand Up @@ -1961,6 +1970,7 @@ Model.translateAliases = function translateAliases(fields) {
*
* @param {Object} conditions
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @api public
*/
Expand Down Expand Up @@ -1995,6 +2005,7 @@ Model.deleteOne = function deleteOne(conditions, options) {
*
* @param {Object} conditions
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @api public
*/
Expand Down Expand Up @@ -2036,6 +2047,7 @@ Model.deleteMany = function deleteMany(conditions, options) {
* @param {Object|ObjectId} filter
* @param {Object|String|String[]} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see field selection https://mongoosejs.com/docs/api/query.html#Query.prototype.select()
* @see query casting https://mongoosejs.com/docs/tutorials/query_casting.html
Expand Down Expand Up @@ -2124,6 +2136,7 @@ Model.findById = function findById(id, projection, options) {
* @param {Object} [conditions]
* @param {Object|String|String[]} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.select())
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see field selection https://mongoosejs.com/docs/api/query.html#Query.prototype.select()
* @see lean queries https://mongoosejs.com/docs/tutorials/lean.html
Expand Down Expand Up @@ -2317,7 +2330,7 @@ Model.$where = function $where() {
};

/**
* Issues a mongodb findAndModify update command.
* Issues a mongodb findOneAndUpdate command.
*
* Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes if `callback` is passed else a Query object is returned.
*
Expand Down Expand Up @@ -2369,6 +2382,7 @@ Model.$where = function $where() {
* @param {Boolean} [options.runValidators] if true, runs [update validators](https://mongoosejs.com/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema
* @param {Boolean} [options.setDefaultsOnInsert=true] If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created
* @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Tutorial https://mongoosejs.com/docs/tutorials/findoneandupdate.html
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
Expand Down Expand Up @@ -2429,7 +2443,7 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
}

/**
* Issues a mongodb findAndModify update command by a document's _id field.
* Issues a mongodb findOneAndUpdate command by a document's _id field.
* `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
*
* Finds a matching document, updates it according to the `update` arg,
Expand Down Expand Up @@ -2487,6 +2501,7 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
* @param {Boolean} [options.new=false] if true, return the modified document rather than the original
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Model.findOneAndUpdate https://mongoosejs.com/docs/api/model.html#Model.findOneAndUpdate()
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
Expand Down Expand Up @@ -2547,6 +2562,7 @@ Model.findByIdAndUpdate = function(id, update, options) {
* @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @api public
*/
Expand Down Expand Up @@ -2582,6 +2598,7 @@ Model.findOneAndDelete = function(conditions, options) {
* @param {Object|Number|String} id value of `_id` to query by
* @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.setOptions())
* @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Model.findOneAndRemove https://mongoosejs.com/docs/api/model.html#Model.findOneAndRemove()
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
Expand Down Expand Up @@ -2625,6 +2642,7 @@ Model.findByIdAndDelete = function(id, options) {
* @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @api public
*/
Expand All @@ -2649,7 +2667,7 @@ Model.findOneAndReplace = function(filter, replacement, options) {
};

/**
* Issue a mongodb findAndModify remove command.
* Issue a mongodb findOneAndRemove command.
*
* Finds a matching document, removes it, and returns the found document (if any).
*
Expand Down Expand Up @@ -2682,6 +2700,7 @@ Model.findOneAndReplace = function(filter, replacement, options) {
* @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Number} [options.maxTimeMS] puts a time limit on the query - requires mongodb >= 2.6.0
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
* @api public
Expand All @@ -2707,7 +2726,7 @@ Model.findOneAndRemove = function(conditions, options) {
};

/**
* Issue a mongodb findAndModify remove command by a document's _id field. `findByIdAndRemove(id, ...)` is equivalent to `findOneAndRemove({ _id: id }, ...)`.
* Issue a mongodb findOneAndRemove command by a document's _id field. `findByIdAndRemove(id, ...)` is equivalent to `findOneAndRemove({ _id: id }, ...)`.
*
* Finds a matching document, removes it, and returns the found document (if any).
*
Expand All @@ -2729,6 +2748,7 @@ Model.findOneAndRemove = function(conditions, options) {
* @param {Object|String} [options.sort] if multiple docs are found by the conditions, sets the sort order to choose which doc to update.
* @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html)
* @param {Object|String} [options.select] sets the document fields to return.
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Model.findOneAndRemove https://mongoosejs.com/docs/api/model.html#Model.findOneAndRemove()
* @see mongodb https://www.mongodb.com/docs/manual/reference/command/findAndModify/
Expand Down Expand Up @@ -3739,6 +3759,7 @@ Model.hydrate = function(obj, projection, options) {
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
* @param {Object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Query docs https://mongoosejs.com/docs/queries.html
* @see MongoDB docs https://www.mongodb.com/docs/manual/reference/command/update/#update-command-output
Expand Down Expand Up @@ -3777,6 +3798,7 @@ Model.updateMany = function updateMany(conditions, doc, options) {
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
* @param {Object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Query docs https://mongoosejs.com/docs/queries.html
* @see MongoDB docs https://www.mongodb.com/docs/manual/reference/command/update/#update-command-output
Expand Down Expand Up @@ -3813,6 +3835,7 @@ Model.updateOne = function updateOne(conditions, doc, options) {
* @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
* @param {Object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
* @return {Query}
* @see Query docs https://mongoosejs.com/docs/queries.html
* @see UpdateResult https://mongodb.github.io/node-mongodb-native/4.9/interfaces/UpdateResult.html
Expand Down
Loading

0 comments on commit ca84162

Please # to comment.