|
| 1 | +# Filtering |
| 2 | + |
| 3 | +ArrayQuery provides a powerful and flexible filtering engine that allows you to apply complex conditions to your data. The filtering system supports a wide range of match modes, nested conditions, and logical grouping with built-in array handling. |
| 4 | + |
| 5 | +## Filter Structure |
| 6 | + |
| 7 | +Filters in ArrayQuery can be either an array of individual filter conditions or an array of filter groups. Here's the updated filter structure: |
| 8 | + |
| 9 | +```ts |
| 10 | +export type FilterOptions = Array<QueryFilterGroup> | Array<QueryFilter> |
| 11 | + |
| 12 | +interface QueryFilter { |
| 13 | + key: string |
| 14 | + value: any |
| 15 | + operator?: Operator |
| 16 | + matchMode: FilterMatchMode |
| 17 | + params?: ComparatorParams | ObjectMapFilterParams |
| 18 | +} |
| 19 | + |
| 20 | +interface QueryFilterGroup { |
| 21 | + operator: Operator |
| 22 | + filters: QueryFilter[] |
| 23 | +} |
| 24 | + |
| 25 | +type Operator = 'AND' | 'OR' | (() => 'AND' | 'OR') |
| 26 | +``` |
| 27 | +
|
| 28 | +## Basic Usage |
| 29 | +
|
| 30 | +Here's a simple example of how to use the filter feature with ArrayQuery: |
| 31 | +
|
| 32 | +```ts twoslash |
| 33 | +import { query } from '@chronicstone/array-query' |
| 34 | + |
| 35 | +const users = [ |
| 36 | + { id: 1, name: 'John Doe', age: 30, roles: ['admin', 'user'] }, |
| 37 | + { id: 2, name: 'Jane Smith', age: 25, roles: ['user'] }, |
| 38 | + { id: 3, name: 'Bob Johnson', age: 35, roles: ['manager', 'user'] } |
| 39 | +] |
| 40 | + |
| 41 | +const result = query(users, { |
| 42 | + filter: [ |
| 43 | + { key: 'age', matchMode: 'greaterThan', value: 25 } |
| 44 | + ] |
| 45 | +}) |
| 46 | +``` |
| 47 | + |
| 48 | +This query will return users older than 25. |
| 49 | + |
| 50 | +## Advanced Filtering |
| 51 | + |
| 52 | +ArrayQuery supports complex filtering scenarios, including logical groups and built-in array handling. |
| 53 | + |
| 54 | +### Multiple Conditions with Regular Filters |
| 55 | + |
| 56 | +When you use an array of regular filters, all conditions must be met for a row to be included in the result: |
| 57 | + |
| 58 | +```ts twoslash |
| 59 | +import { query } from '@chronicstone/array-query' |
| 60 | + |
| 61 | +const users = [ |
| 62 | + { id: 1, name: 'John Doe', age: 30, roles: ['admin', 'user'] }, |
| 63 | + { id: 2, name: 'Jane Smith', age: 25, roles: ['user'] }, |
| 64 | + { id: 3, name: 'Bob Johnson', age: 35, roles: ['manager', 'user'] } |
| 65 | +] |
| 66 | + |
| 67 | +const result = query(users, { |
| 68 | + filter: [ |
| 69 | + { key: 'age', matchMode: 'greaterThan', value: 25 }, |
| 70 | + { key: 'name', matchMode: 'contains', value: 'John' } |
| 71 | + ] |
| 72 | +}) |
| 73 | +``` |
| 74 | + |
| 75 | +This query will return users who are older than 25 AND have 'John' in their name. |
| 76 | + |
| 77 | +### Logical Groups |
| 78 | + |
| 79 | +You can use filter groups to create more complex conditions. When using filter groups, a row will be included if it matches at least one of the groups: |
| 80 | + |
| 81 | +```ts twoslash |
| 82 | +import { query } from '@chronicstone/array-query' |
| 83 | + |
| 84 | +const users = [ |
| 85 | + { id: 1, name: 'John Doe', age: 30, roles: ['admin', 'user'] }, |
| 86 | + { id: 2, name: 'Jane Smith', age: 25, roles: ['user'] }, |
| 87 | + { id: 3, name: 'Bob Johnson', age: 35, roles: ['manager', 'user'] }, |
| 88 | + { id: 4, name: 'Alice Williams', age: 65, roles: ['user'] } |
| 89 | +] |
| 90 | + |
| 91 | +const result = query(users, { |
| 92 | + filter: [ |
| 93 | + { |
| 94 | + operator: 'AND', |
| 95 | + filters: [ |
| 96 | + { key: 'age', matchMode: 'greaterThan', value: 18 }, |
| 97 | + { key: 'age', matchMode: 'lessThan', value: 45 } |
| 98 | + ] |
| 99 | + }, |
| 100 | + { |
| 101 | + operator: 'AND', |
| 102 | + filters: [ |
| 103 | + { key: 'age', matchMode: 'greaterThan', value: 60 }, |
| 104 | + { key: 'age', matchMode: 'lessThan', value: 90 } |
| 105 | + ] |
| 106 | + } |
| 107 | + ] |
| 108 | +}) |
| 109 | +``` |
| 110 | + |
| 111 | +This example filters users who are either between 18 and 45 years old, OR between 60 and 90 years old. The row will be included if it matches either of these groups. |
| 112 | + |
| 113 | +### Built-in Array Handling |
| 114 | + |
| 115 | +ArrayQuery automatically handles array values in the data. When a filter is applied to a field that contains an array, the filter condition is checked against each element of the array: |
| 116 | + |
| 117 | +```ts twoslash |
| 118 | +import { query } from '@chronicstone/array-query' |
| 119 | + |
| 120 | +const users = [ |
| 121 | + { id: 1, name: 'John Doe', age: 30, roles: ['admin', 'user'] }, |
| 122 | + { id: 2, name: 'Jane Smith', age: 25, roles: ['user'] }, |
| 123 | + { id: 3, name: 'Bob Johnson', age: 35, roles: ['manager', 'user'] } |
| 124 | +] |
| 125 | + |
| 126 | +const result = query(users, { |
| 127 | + filter: [ |
| 128 | + { |
| 129 | + key: 'roles', |
| 130 | + matchMode: 'equals', |
| 131 | + value: 'admin', |
| 132 | + operator: 'OR' |
| 133 | + } |
| 134 | + ] |
| 135 | +}) |
| 136 | +``` |
| 137 | + |
| 138 | +In this example: |
| 139 | +- For a user with `roles: ['admin', 'manager']`, the filter will return true because at least one element ("admin") matches the condition. |
| 140 | +- The `operator: "OR"` means that if any element in the array matches, the condition is considered true. |
| 141 | +- If `operator: "AND"` was used, all elements in the array would need to match the condition. |
| 142 | + |
| 143 | +### Nested Object Filtering |
| 144 | + |
| 145 | +You can filter based on nested object properties using dot notation: |
| 146 | + |
| 147 | +```ts twoslash |
| 148 | +import { query } from '@chronicstone/array-query' |
| 149 | + |
| 150 | +const users = [ |
| 151 | + { id: 1, name: 'John Doe', age: 30, address: { city: 'New York', country: 'USA' } }, |
| 152 | + { id: 2, name: 'Jane Smith', age: 25, address: { city: 'London', country: 'UK' } }, |
| 153 | + { id: 3, name: 'Bob Johnson', age: 35, address: { city: 'Paris', country: 'France' } } |
| 154 | +] |
| 155 | + |
| 156 | +const result = query(users, { |
| 157 | + filter: [ |
| 158 | + { key: 'address.city', matchMode: 'equals', value: 'New York' } |
| 159 | + ] |
| 160 | +}) |
| 161 | +``` |
| 162 | + |
| 163 | +## Match Modes |
| 164 | + |
| 165 | +ArrayQuery supports various match modes for different types of comparisons. Each match mode has its own dedicated documentation page for detailed usage. The available match modes include: |
| 166 | + |
| 167 | +- 'contains' |
| 168 | +- 'between' |
| 169 | +- 'equals' |
| 170 | +- 'notEquals' |
| 171 | +- 'greaterThan' |
| 172 | +- 'greaterThanOrEqual' |
| 173 | +- 'lessThan' |
| 174 | +- 'lessThanOrEqual' |
| 175 | +- 'exists' |
| 176 | +- 'arrayLength' |
| 177 | +- 'objectMatch' |
0 commit comments