-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
refactor: reuse sort logic between Query and Aggregate #15818
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
Open
singhankit001
wants to merge
4
commits into
Automattic:master
Choose a base branch
from
singhankit001:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+142
−129
Open
Changes from 3 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
6ab7553
refactor: reuse sort logic between Query and Aggregate
singhankit001 4412bee
Fixed requested changes
singhankit001 e15aa7e
fix: lint errors in aggregate.test.js
singhankit001 4c1bc94
style(query): use strict equality and avoid optional chaining in cast…
singhankit001 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| 'use strict'; | ||
|
|
||
| const specialProperties = require('../specialProperties'); | ||
|
|
||
| /** | ||
| * Casts a sort argument to a MongoDB sort object. | ||
| * | ||
| * @param {Object|String|Array|Map} arg The sort argument. | ||
| * @return {Object} The cast sort object. | ||
| */ | ||
| module.exports = function castSort(arg) { | ||
| const sort = {}; | ||
|
|
||
| if (typeof arg === 'string') { | ||
| const properties = arg.indexOf(' ') === -1 ? [arg] : arg.split(' '); | ||
| for (let property of properties) { | ||
| if (!property) { | ||
| continue; | ||
| } | ||
| const ascend = '-' == property[0] ? -1 : 1; | ||
| if (ascend === -1) { | ||
| property = property.slice(1); | ||
| } | ||
| if (specialProperties.has(property)) { | ||
| continue; | ||
| } | ||
| sort[property] = ascend; | ||
| } | ||
| } else if (Array.isArray(arg)) { | ||
| for (const pair of arg) { | ||
| if (!Array.isArray(pair)) { | ||
| throw new TypeError('Invalid sort() argument, must be array of arrays'); | ||
| } | ||
| const key = '' + pair[0]; | ||
| if (specialProperties.has(key)) { | ||
| continue; | ||
| } | ||
| sort[key] = _handleSortValue(pair[1], key); | ||
| } | ||
| } else if (typeof arg === 'object' && arg != null && !(arg instanceof Map)) { | ||
| for (const key of Object.keys(arg)) { | ||
| if (specialProperties.has(key)) { | ||
| continue; | ||
| } | ||
| sort[key] = _handleSortValue(arg[key], key); | ||
| } | ||
| } else if (arg instanceof Map) { | ||
| for (let key of arg.keys()) { | ||
| key = '' + key; | ||
| if (specialProperties.has(key)) { | ||
| continue; | ||
| } | ||
| sort[key] = _handleSortValue(arg.get(key), key); | ||
| } | ||
| } else if (arg != null) { | ||
| throw new TypeError('Invalid sort() argument. Must be a string, object, array, or map.'); | ||
| } | ||
|
|
||
| return sort; | ||
| }; | ||
|
|
||
| function _handleSortValue(val, key) { | ||
| if (val === 1 || val === 'asc' || val === 'ascending') { | ||
| return 1; | ||
| } | ||
| if (val === -1 || val === 'desc' || val === 'descending') { | ||
| return -1; | ||
| } | ||
| if (val?.$meta != null) { | ||
| return { $meta: val.$meta }; | ||
| } | ||
| throw new TypeError('Invalid sort value: { ' + key + ': ' + val + ' }'); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ const applyWriteConcern = require('./helpers/schema/applyWriteConcern'); | |
| const cast = require('./cast'); | ||
| const castArrayFilters = require('./helpers/update/castArrayFilters'); | ||
| const castNumber = require('./cast/number'); | ||
| const castSort = require('./helpers/query/castSort'); | ||
| const castUpdate = require('./helpers/query/castUpdate'); | ||
| const clone = require('./helpers/clone'); | ||
| const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue'); | ||
|
|
@@ -35,7 +36,7 @@ const sanitizeFilter = require('./helpers/query/sanitizeFilter'); | |
| const sanitizeProjection = require('./helpers/query/sanitizeProjection'); | ||
| const selectPopulatedFields = require('./helpers/query/selectPopulatedFields'); | ||
| const setDefaultsOnInsert = require('./helpers/setDefaultsOnInsert'); | ||
| const specialProperties = require('./helpers/specialProperties'); | ||
|
|
||
| const updateValidators = require('./helpers/updateValidators'); | ||
| const util = require('util'); | ||
| const utils = require('./utils'); | ||
|
|
@@ -1349,24 +1350,24 @@ Query.prototype.read = function read(mode, tags) { | |
|
|
||
| Query.prototype.toString = function toString() { | ||
| if (this.op === 'count' || | ||
| this.op === 'countDocuments' || | ||
| this.op === 'find' || | ||
| this.op === 'findOne' || | ||
| this.op === 'deleteMany' || | ||
| this.op === 'deleteOne' || | ||
| this.op === 'findOneAndDelete' || | ||
| this.op === 'remove') { | ||
| this.op === 'countDocuments' || | ||
| this.op === 'find' || | ||
| this.op === 'findOne' || | ||
| this.op === 'deleteMany' || | ||
| this.op === 'deleteOne' || | ||
| this.op === 'findOneAndDelete' || | ||
| this.op === 'remove') { | ||
|
Comment on lines
+1353
to
+1359
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those are also unrelated style changes, though from what i can tell, it is not caught by the lint currently. |
||
| return `${this.model.modelName}.${this.op}(${util.inspect(this._conditions)})`; | ||
| } | ||
| if (this.op === 'distinct') { | ||
| return `${this.model.modelName}.distinct('${this._distinct}', ${util.inspect(this._conditions)})`; | ||
| } | ||
| if (this.op === 'findOneAndReplace' || | ||
| this.op === 'findOneAndUpdate' || | ||
| this.op === 'replaceOne' || | ||
| this.op === 'update' || | ||
| this.op === 'updateMany' || | ||
| this.op === 'updateOne') { | ||
| this.op === 'findOneAndUpdate' || | ||
| this.op === 'replaceOne' || | ||
| this.op === 'update' || | ||
| this.op === 'updateMany' || | ||
| this.op === 'updateOne') { | ||
| return `${this.model.modelName}.${this.op}(${util.inspect(this._conditions)}, ${util.inspect(this._update)})`; | ||
| } | ||
|
|
||
|
|
@@ -2105,9 +2106,9 @@ Query.prototype._optionsForExec = function(model) { | |
| } | ||
|
|
||
| const readPreference = model && | ||
| model.schema && | ||
| model.schema.options && | ||
| model.schema.options.read; | ||
| model.schema && | ||
| model.schema.options && | ||
| model.schema.options.read; | ||
| if (!('readPreference' in options) && readPreference) { | ||
| options.readPreference = readPreference; | ||
| } | ||
|
|
@@ -2481,7 +2482,7 @@ Query.prototype._find = async function _find() { | |
|
|
||
| Query.prototype.find = function(conditions) { | ||
| if (typeof conditions === 'function' || | ||
| typeof arguments[1] === 'function') { | ||
| typeof arguments[1] === 'function') { | ||
| throw new MongooseError('Query.prototype.find() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -2760,9 +2761,9 @@ Query.prototype._findOne = async function _findOne() { | |
|
|
||
| Query.prototype.findOne = function(conditions, projection, options) { | ||
| if (typeof conditions === 'function' || | ||
| typeof projection === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[3] === 'function') { | ||
| typeof projection === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[3] === 'function') { | ||
| throw new MongooseError('Query.prototype.findOne() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -2888,7 +2889,7 @@ Query.prototype._estimatedDocumentCount = async function _estimatedDocumentCount | |
|
|
||
| Query.prototype.estimatedDocumentCount = function(options) { | ||
| if (typeof options === 'function' || | ||
| typeof arguments[1] === 'function') { | ||
| typeof arguments[1] === 'function') { | ||
| throw new MongooseError('Query.prototype.estimatedDocumentCount() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -2941,8 +2942,8 @@ Query.prototype.estimatedDocumentCount = function(options) { | |
|
|
||
| Query.prototype.countDocuments = function(conditions, options) { | ||
| if (typeof conditions === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[2] === 'function') { | ||
| typeof options === 'function' || | ||
| typeof arguments[2] === 'function') { | ||
| throw new MongooseError('Query.prototype.countDocuments() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -3005,9 +3006,9 @@ Query.prototype.__distinct = async function __distinct() { | |
|
|
||
| Query.prototype.distinct = function(field, conditions, options) { | ||
| if (typeof field === 'function' || | ||
| typeof conditions === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[3] === 'function') { | ||
| typeof conditions === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[3] === 'function') { | ||
| throw new MongooseError('Query.prototype.distinct() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -3078,48 +3079,9 @@ Query.prototype.sort = function(arg, options) { | |
| if (options && options.override) { | ||
| this.options.sort = {}; | ||
| } | ||
| const sort = this.options.sort; | ||
| if (typeof arg === 'string') { | ||
| const properties = arg.indexOf(' ') === -1 ? [arg] : arg.split(' '); | ||
| for (let property of properties) { | ||
| const ascend = '-' == property[0] ? -1 : 1; | ||
| if (ascend === -1) { | ||
| property = property.slice(1); | ||
| } | ||
| if (specialProperties.has(property)) { | ||
| continue; | ||
| } | ||
| sort[property] = ascend; | ||
| } | ||
| } else if (Array.isArray(arg)) { | ||
| for (const pair of arg) { | ||
| if (!Array.isArray(pair)) { | ||
| throw new TypeError('Invalid sort() argument, must be array of arrays'); | ||
| } | ||
| const key = '' + pair[0]; | ||
| if (specialProperties.has(key)) { | ||
| continue; | ||
| } | ||
| sort[key] = _handleSortValue(pair[1], key); | ||
| } | ||
| } else if (typeof arg === 'object' && arg != null && !(arg instanceof Map)) { | ||
| for (const key of Object.keys(arg)) { | ||
| if (specialProperties.has(key)) { | ||
| continue; | ||
| } | ||
| sort[key] = _handleSortValue(arg[key], key); | ||
| } | ||
| } else if (arg instanceof Map) { | ||
| for (let key of arg.keys()) { | ||
| key = '' + key; | ||
| if (specialProperties.has(key)) { | ||
| continue; | ||
| } | ||
| sort[key] = _handleSortValue(arg.get(key), key); | ||
| } | ||
| } else if (arg != null) { | ||
| throw new TypeError('Invalid sort() argument. Must be a string, object, array, or map.'); | ||
| } | ||
|
|
||
| const sort = castSort(arg); | ||
| Object.assign(this.options.sort, sort); | ||
|
|
||
| return this; | ||
| }; | ||
|
|
@@ -3128,18 +3090,6 @@ Query.prototype.sort = function(arg, options) { | |
| * Convert sort values | ||
| */ | ||
|
|
||
| function _handleSortValue(val, key) { | ||
| if (val === 1 || val === 'asc' || val === 'ascending') { | ||
| return 1; | ||
| } | ||
| if (val === -1 || val === 'desc' || val === 'descending') { | ||
| return -1; | ||
| } | ||
| if (val?.$meta != null) { | ||
| return { $meta: val.$meta }; | ||
| } | ||
| throw new TypeError('Invalid sort value: { ' + key + ': ' + val + ' }'); | ||
| } | ||
|
|
||
| /** | ||
| * Declare and/or execute this query as a `deleteOne()` operation. Works like | ||
|
|
@@ -3413,9 +3363,9 @@ function prepareDiscriminatorCriteria(query) { | |
|
|
||
| Query.prototype.findOneAndUpdate = function(filter, update, options) { | ||
| if (typeof filter === 'function' || | ||
| typeof update === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[3] === 'function') { | ||
| typeof update === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[3] === 'function') { | ||
| throw new MongooseError('Query.prototype.findOneAndUpdate() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -3592,8 +3542,8 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() { | |
|
|
||
| Query.prototype.findOneAndDelete = function(filter, options) { | ||
| if (typeof filter === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[2] === 'function') { | ||
| typeof options === 'function' || | ||
| typeof arguments[2] === 'function') { | ||
| throw new MongooseError('Query.prototype.findOneAndDelete() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -3693,9 +3643,9 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() { | |
|
|
||
| Query.prototype.findOneAndReplace = function(filter, replacement, options) { | ||
| if (typeof filter === 'function' || | ||
| typeof replacement === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[4] === 'function') { | ||
| typeof replacement === 'function' || | ||
| typeof options === 'function' || | ||
| typeof arguments[4] === 'function') { | ||
| throw new MongooseError('Query.prototype.findOneAndReplace() no longer accepts a callback'); | ||
| } | ||
|
|
||
|
|
@@ -4398,8 +4348,8 @@ function _update(query, op, filter, doc, options, callback) { | |
| } | ||
|
|
||
| if (!(filter instanceof Query) && | ||
| filter != null && | ||
| filter.toString() !== '[object Object]') { | ||
| filter != null && | ||
| filter.toString() !== '[object Object]') { | ||
| query.error(new ObjectParameterError(filter, 'filter', op)); | ||
| } else { | ||
| query.merge(filter); | ||
|
|
@@ -4812,8 +4762,8 @@ Query.prototype._castUpdate = function _castUpdate(obj) { | |
| const discriminatorKey = schema.options.discriminatorKey; | ||
| const baseSchema = schema._baseSchema ? schema._baseSchema : schema; | ||
| if (this._mongooseOptions.overwriteDiscriminatorKey && | ||
| obj[discriminatorKey] != null && | ||
| baseSchema.discriminators) { | ||
| obj[discriminatorKey] != null && | ||
| baseSchema.discriminators) { | ||
| const _schema = Object.values(baseSchema.discriminators).find( | ||
| discriminator => discriminator.discriminatorMapping.value === obj[discriminatorKey] | ||
| ); | ||
|
|
@@ -4995,7 +4945,7 @@ Query.prototype.cast = function(model, obj) { | |
| model = model || this.model; | ||
| const discriminatorKey = model.schema.options.discriminatorKey; | ||
| if (obj != null && | ||
| obj.hasOwnProperty(discriminatorKey)) { | ||
| obj.hasOwnProperty(discriminatorKey)) { | ||
| model = getDiscriminatorByValue(model.discriminators, obj[discriminatorKey]) || model; | ||
| } | ||
|
|
||
|
|
@@ -5372,7 +5322,7 @@ Query.prototype.near = function() { | |
| } | ||
| } else if (arguments.length === 3) { | ||
| if (typeof arguments[0] === 'string' && typeof arguments[1] === 'number' | ||
| && typeof arguments[2] === 'number') { | ||
| && typeof arguments[2] === 'number') { | ||
| params.push(arguments[0]); | ||
| params.push({ center: [arguments[1], arguments[2]], spherical: sphere }); | ||
| } else { | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.