simplifyQuery
Category
Tags
Export size
min 3.27 kB · gzip 1.35 kB
See also
Normalizes the logical structure of a Feathers query without changing what it matches: empty $and/$or are dropped, duplicate branches removed, nested same-operator branches hoisted ($and-in-$and, pure $or-in-$or), $or branches on the same property collapsed into a single $in, single-value $in/$nin written as an equality/$ne, and branches merged up into the parent where it is safe — all of an $and when no key collides, a single-branch $or. Runs recursively. Inputs are not mutated; a query with nothing to simplify is returned unchanged.
ts
import { simplifyQuery } from 'feathers-utils/utils';Examples
Example 1
ts
import { simplifyQuery } from 'feathers-utils/utils'
// non-colliding $and branches (here also a hoisted nested $and) merge up
simplifyQuery({ $and: [{ id: 1 }, { $and: [{ status: 'a' }] }] })
// => { id: 1, status: 'a' }
simplifyQuery({ $or: [{ id: 1 }] })
// => { id: 1 }
// a colliding key keeps the $and intact
simplifyQuery({ $and: [{ price: { $gt: 1 } }, { price: { $lt: 9 } }] })
// => { $and: [{ price: { $gt: 1 } }, { price: { $lt: 9 } }] }Example 2
ts
// an $or over the same property is an $in over the union of its values
simplifyQuery({ $or: [{ role: { $in: ['a'] } }, { role: { $in: ['b'] } }] })
// => { role: { $in: ['a', 'b'] } }
simplifyQuery({ $or: [{ role: 'a' }, { role: 'b' }, { status: 'active' }] })
// => { $or: [{ role: { $in: ['a', 'b'] } }, { status: 'active' }] }
simplifyQuery({ $or: [{ role: 'a' }, { role: 'b' }] }, { collapseOrToIn: false })
// => { $or: [{ role: 'a' }, { role: 'b' }] }Example 3
ts
// a $in / $nin over a single value is an equality / $ne
simplifyQuery({ role: { $in: ['admin'] } })
// => { role: 'admin' }
simplifyQuery({ role: { $nin: ['admin'] } })
// => { role: { $ne: 'admin' } }
// ... but not over a single array value, which is a different condition
simplifyQuery({ roles: { $in: [['admin']] } })
// => { roles: { $in: [['admin']] } }Type declaration
Show Type Declarations
ts
export interface SimplifyQueryOptions {
/**
* Dissolve a top-level single-branch `$and` by merging its branch up into the
* query (only when no key would collide). Nested levels are always dissolved.
*
* @default true
*/
replaceAnd?: boolean
/**
* Dissolve a top-level single-branch `$or` by merging its branch up into the
* query (only when no key would collide). Nested levels are always dissolved.
*
* @default true
*/
replaceOr?: boolean
/**
* Collapse `$or` branches that constrain the same single property with an
* equality or `$in` into one `$in` over the union of their values. Turn this
* off when `$in` is not an option for that property — it is the one
* simplification that can introduce an operator the query did not use.
*
* @default true
*/
collapseOrToIn?: boolean
/**
* Rewrite a single-value `$in`/`$nin` query value to the plain condition it already
* is: `{ $in: [x] }` to `x`, `{ $nin: [x] }` to `{ $ne: x }`. Applies to every
* property, not just the ones an `$or` touches. A single *array* value keeps its
* list operator, since that is a different condition.
*
* @default true
*/
collapseToEqOrNe?: boolean
}
/**
* Normalizes the logical structure of a Feathers query without changing what it
* matches: empty `$and`/`$or` are dropped, duplicate branches removed, nested
* same-operator branches hoisted (`$and`-in-`$and`, pure `$or`-in-`$or`), `$or`
* branches on the same property collapsed into a single `$in`, single-value `$in`/`$nin`
* written as an equality/`$ne`, and branches merged up into the parent where it is
* safe — all of an `$and` when no key collides, a single-branch `$or`. Runs
* recursively. Inputs are not mutated; a query with nothing to simplify is returned
* unchanged.
*
* @param query the query to simplify (a falsy query is returned as-is)
* @param options
* @returns the simplified query
*
* @example
* ```ts
*
*
* // non-colliding $and branches (here also a hoisted nested $and) merge up
* simplifyQuery({ $and: [{ id: 1 }, { $and: [{ status: 'a' }] }] })
* // => { id: 1, status: 'a' }
*
* simplifyQuery({ $or: [{ id: 1 }] })
* // => { id: 1 }
*
* // a colliding key keeps the $and intact
* simplifyQuery({ $and: [{ price: { $gt: 1 } }, { price: { $lt: 9 } }] })
* // => { $and: [{ price: { $gt: 1 } }, { price: { $lt: 9 } }] }
* ```
*
* @example
* ```ts
* // an $or over the same property is an $in over the union of its values
* simplifyQuery({ $or: [{ role: { $in: ['a'] } }, { role: { $in: ['b'] } }] })
* // => { role: { $in: ['a', 'b'] } }
*
* simplifyQuery({ $or: [{ role: 'a' }, { role: 'b' }, { status: 'active' }] })
* // => { $or: [{ role: { $in: ['a', 'b'] } }, { status: 'active' }] }
*
* simplifyQuery({ $or: [{ role: 'a' }, { role: 'b' }] }, { collapseOrToIn: false })
* // => { $or: [{ role: 'a' }, { role: 'b' }] }
* ```
*
* @example
* ```ts
* // a $in / $nin over a single value is an equality / $ne
* simplifyQuery({ role: { $in: ['admin'] } })
* // => { role: 'admin' }
*
* simplifyQuery({ role: { $nin: ['admin'] } })
* // => { role: { $ne: 'admin' } }
*
* // ... but not over a single array value, which is a different condition
* simplifyQuery({ roles: { $in: [['admin']] } })
* // => { roles: { $in: [['admin']] } }
* ```
*
* @see https://utils.feathersjs.com/utils/simplify-query.html
*/
export declare function simplifyQuery<Q extends Query | null | undefined>(
query: Q,
options?: SimplifyQueryOptions,
): Q| Argument | Type | Description |
|---|---|---|
| query | Q | |
| options | SimplifyQueryOptions |
