@venizia/ignis-docs 0.2.1-0 → 0.2.1-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/best-practices/architectural-patterns.md +3 -3
- package/content/best-practices/code-style-standards/naming-conventions.md +1 -1
- package/content/best-practices/contribution-workflow.md +2 -2
- package/content/best-practices/error-handling.md +94 -89
- package/content/best-practices/security-guidelines.md +5 -5
- package/content/extensions/components/api-reference.md +22 -21
- package/content/extensions/components/authentication/api.md +64 -28
- package/content/extensions/components/authentication/errors.md +19 -5
- package/content/extensions/components/authentication/index.md +19 -18
- package/content/extensions/components/authentication/usage.md +55 -30
- package/content/extensions/components/authorization/api.md +351 -84
- package/content/extensions/components/authorization/errors.md +51 -17
- package/content/extensions/components/authorization/getting-started.md +227 -0
- package/content/extensions/components/authorization/index.md +24 -16
- package/content/extensions/components/authorization/usage.md +45 -21
- package/content/extensions/components/health-check.md +15 -9
- package/content/extensions/components/index.md +24 -90
- package/content/extensions/components/mail/api.md +105 -54
- package/content/extensions/components/mail/errors.md +12 -10
- package/content/extensions/components/mail/index.md +32 -13
- package/content/extensions/components/mail/usage.md +26 -18
- package/content/extensions/components/request-tracker.md +18 -14
- package/content/extensions/components/socket-io/api.md +377 -882
- package/content/extensions/components/socket-io/errors.md +49 -51
- package/content/extensions/components/socket-io/index.md +72 -88
- package/content/extensions/components/socket-io/usage.md +107 -117
- package/content/extensions/components/static-asset/api.md +83 -31
- package/content/extensions/components/static-asset/errors.md +18 -7
- package/content/extensions/components/static-asset/index.md +18 -11
- package/content/extensions/components/static-asset/usage.md +11 -6
- package/content/extensions/components/template/index.md +3 -3
- package/content/extensions/components/websocket/api.md +58 -27
- package/content/extensions/components/websocket/errors.md +3 -3
- package/content/extensions/components/websocket/index.md +8 -7
- package/content/extensions/components/websocket/usage.md +21 -8
- package/content/extensions/helpers/cron/index.md +8 -7
- package/content/extensions/helpers/crypto/index.md +16 -8
- package/content/extensions/helpers/crypto/reference.md +96 -24
- package/content/extensions/helpers/env/index.md +14 -10
- package/content/extensions/helpers/error/index.md +99 -23
- package/content/extensions/helpers/index.md +61 -47
- package/content/extensions/helpers/inversion/index.md +23 -6
- package/content/extensions/helpers/inversion/reference.md +30 -22
- package/content/extensions/helpers/kafka/admin.md +3 -2
- package/content/extensions/helpers/kafka/compile-binary.md +69 -44
- package/content/extensions/helpers/kafka/consumer.md +24 -21
- package/content/extensions/helpers/kafka/examples.md +22 -234
- package/content/extensions/helpers/kafka/index.md +30 -62
- package/content/extensions/helpers/kafka/producer.md +31 -26
- package/content/extensions/helpers/kafka/schema-registry.md +19 -14
- package/content/extensions/helpers/logger/hf-logger.md +49 -22
- package/content/extensions/helpers/logger/index.md +37 -12
- package/content/extensions/helpers/logger/pino.md +31 -11
- package/content/extensions/helpers/logger/reference.md +243 -52
- package/content/extensions/helpers/network/api.md +65 -30
- package/content/extensions/helpers/network/index.md +32 -11
- package/content/extensions/helpers/queue/index.md +17 -6
- package/content/extensions/helpers/queue/reference.md +52 -25
- package/content/extensions/helpers/redis/index.md +29 -11
- package/content/extensions/helpers/redis/reference.md +85 -28
- package/content/extensions/helpers/secrets/index.md +82 -12
- package/content/extensions/helpers/socket-io/api.md +40 -21
- package/content/extensions/helpers/socket-io/index.md +26 -10
- package/content/extensions/helpers/storage/api.md +42 -24
- package/content/extensions/helpers/storage/index.md +10 -7
- package/content/extensions/helpers/types/index.md +20 -7
- package/content/extensions/helpers/types/reference.md +53 -14
- package/content/extensions/helpers/uid/index.md +166 -10
- package/content/extensions/helpers/websocket/api.md +52 -13
- package/content/extensions/helpers/websocket/index.md +7 -4
- package/content/extensions/helpers/worker-thread/index.md +9 -5
- package/content/extensions/helpers/worker-thread/reference.md +20 -20
- package/content/extensions/index.md +38 -39
- package/content/extensions/src-details/mcp-server.md +96 -548
- package/content/guides/core-concepts/persistent/datasources.md +2 -2
- package/content/guides/core-concepts/persistent/index.md +5 -1
- package/content/guides/core-concepts/persistent/pglite.md +218 -0
- package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
- package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
- package/content/guides/core-concepts/persistent/search-typesense.md +26 -14
- package/content/guides/core-concepts/persistent/sqlite.md +296 -0
- package/content/guides/core-concepts/persistent/transactions.md +12 -11
- package/content/guides/get-started/5-minute-quickstart.md +59 -206
- package/content/guides/get-started/philosophy.md +135 -670
- package/content/guides/get-started/setup.md +53 -74
- package/content/guides/migrations/redis-helpers-migration.md +4 -3
- package/content/guides/migrations/scoped-rbac-migration.md +5 -5
- package/content/guides/migrations/unified-connectors-migration.md +7 -6
- package/content/guides/tutorials/realtime-chat.md +1 -1
- package/content/references/base/application.md +63 -21
- package/content/references/base/components.md +3 -3
- package/content/references/base/connectors.md +14 -14
- package/content/references/base/controllers.md +12 -12
- package/content/references/base/datasources-reference.md +32 -31
- package/content/references/base/datasources.md +6 -6
- package/content/references/base/dependency-injection.md +12 -11
- package/content/references/base/filter-system/application-usage.md +54 -30
- package/content/references/base/filter-system/array-operators.md +24 -46
- package/content/references/base/filter-system/comparison-operators.md +47 -67
- package/content/references/base/filter-system/default-filter.md +59 -53
- package/content/references/base/filter-system/fields-order-pagination.md +92 -146
- package/content/references/base/filter-system/index.md +25 -13
- package/content/references/base/filter-system/json-filtering.md +45 -184
- package/content/references/base/filter-system/list-operators.md +23 -53
- package/content/references/base/filter-system/logical-operators.md +63 -121
- package/content/references/base/filter-system/null-operators.md +34 -104
- package/content/references/base/filter-system/pattern-matching.md +40 -55
- package/content/references/base/filter-system/quick-reference.md +86 -198
- package/content/references/base/filter-system/range-operators.md +18 -46
- package/content/references/base/filter-system/tips.md +6 -6
- package/content/references/base/filter-system/use-cases.md +33 -15
- package/content/references/base/grpc-controllers.md +53 -17
- package/content/references/base/index.md +5 -3
- package/content/references/base/middlewares.md +11 -10
- package/content/references/base/models-reference.md +17 -17
- package/content/references/base/models.md +4 -3
- package/content/references/base/providers.md +8 -8
- package/content/references/base/repositories/advanced.md +224 -326
- package/content/references/base/repositories/index.md +19 -6
- package/content/references/base/repositories/mixins.md +5 -5
- package/content/references/base/repositories/relations.md +160 -293
- package/content/references/base/repositories/soft-deletable.md +16 -6
- package/content/references/base/secrets.md +17 -13
- package/content/references/base/services.md +6 -4
- package/content/references/configuration/environment-variables.md +31 -23
- package/content/references/configuration/index.md +6 -4
- package/content/references/index.md +1 -1
- package/content/references/utilities/duration.md +85 -0
- package/content/references/utilities/index.md +5 -1
- package/content/references/utilities/jsx-reference.md +11 -11
- package/content/references/utilities/jsx.md +2 -2
- package/content/references/utilities/module.md +78 -25
- package/content/references/utilities/request.md +2 -1
- package/content/references/utilities/retry.md +139 -0
- package/content/references/utilities/schema.md +2 -2
- package/content/references/utilities/statuses-reference.md +4 -4
- package/content/references/utilities/statuses.md +5 -5
- package/dist/mcp-server/index.js +0 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
- package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
- package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
- package/package.json +17 -16
|
@@ -2,274 +2,161 @@
|
|
|
2
2
|
title: Filter Operators Quick Reference
|
|
3
3
|
description: Single-page cheat sheet of all filter operators
|
|
4
4
|
difficulty: intermediate
|
|
5
|
-
lastUpdated: 2026-
|
|
5
|
+
lastUpdated: 2026-07-23
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Filter Operators Quick Reference
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Every `where` operator, one line each. For the `filter` shape and the mental model, start at the [Filter System Overview](./). For explanations and worked examples, follow the **See** link under each table.
|
|
11
11
|
|
|
12
12
|
## Comparison Operators
|
|
13
13
|
|
|
14
|
-
| Operator | SQL |
|
|
15
|
-
|
|
14
|
+
| Operator | SQL | Example | Description |
|
|
15
|
+
|---|---|---|---|
|
|
16
16
|
| `eq` | `=` | `{ status: { eq: 'active' } }` | Equal to |
|
|
17
17
|
| `ne` | `!=` | `{ status: { ne: 'deleted' } }` | Not equal to |
|
|
18
|
-
| `neq` | `!=` | `{ status: { neq: 'deleted' } }` |
|
|
18
|
+
| `neq` | `!=` | `{ status: { neq: 'deleted' } }` | Alias for `ne` |
|
|
19
19
|
| `gt` | `>` | `{ age: { gt: 18 } }` | Greater than |
|
|
20
20
|
| `gte` | `>=` | `{ age: { gte: 18 } }` | Greater than or equal |
|
|
21
21
|
| `lt` | `<` | `{ price: { lt: 100 } }` | Less than |
|
|
22
22
|
| `lte` | `<=` | `{ price: { lte: 100 } }` | Less than or equal |
|
|
23
23
|
|
|
24
24
|
> [!NOTE]
|
|
25
|
-
> `ne`/`neq` follow SQL three-valued logic
|
|
25
|
+
> `ne`/`neq` follow SQL three-valued logic. A row whose field is `NULL` never matches `{ field: { neq: value } }`, because `NULL <> value` is UNKNOWN, not TRUE. To include NULL rows too, use `{ or: [{ field: { neq: value } }, { field: null }] }`.
|
|
26
26
|
|
|
27
27
|
**See:** [Comparison Operators Guide](./comparison-operators.md)
|
|
28
28
|
|
|
29
|
+
## Null / Presence Operators
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
|
33
|
-
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
31
|
+
| Operator | SQL | Example | Description |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| `is` | `IS NULL` / `=` | `{ deletedAt: { is: null } }` | `IS NULL` when the value is `null`, equality otherwise |
|
|
34
|
+
| `isn` | `IS NOT NULL` / `!=` | `{ email: { isn: null } }` | `IS NOT NULL` when the value is `null`, not-equal otherwise |
|
|
35
|
+
| `exists` | `IS NOT NULL` / `IS NULL` | `{ deletedAt: { exists: false } }` | `exists: true` -> `IS NOT NULL`, `exists: false` -> `IS NULL` |
|
|
36
|
+
| `notExists` | `IS NULL` / `IS NOT NULL` | `{ verifiedAt: { notExists: true } }` | Inverse of `exists` |
|
|
36
37
|
|
|
37
|
-
**
|
|
38
|
+
**Shorthand:** a bare `null` is implicit `IS NULL`. `{ deletedAt: null }` is identical to `{ deletedAt: { eq: null } }` or `{ deletedAt: { is: null } }`.
|
|
38
39
|
|
|
40
|
+
**See:** [Null Operators Guide](./null-operators.md)
|
|
39
41
|
|
|
40
42
|
## List Operators
|
|
41
43
|
|
|
42
|
-
| Operator | SQL |
|
|
43
|
-
|
|
44
|
-
| `in` | `IN` | `{ status: { in: ['active', 'pending'] } }` | Value matches any in array |
|
|
44
|
+
| Operator | SQL | Example | Description |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| `in` | `IN` | `{ status: { in: ['active', 'pending'] } }` | Value matches any in the array |
|
|
45
47
|
| `inq` | `IN` | `{ status: { inq: ['active', 'pending'] } }` | Alias for `in` |
|
|
46
|
-
| `nin` | `NOT IN` | `{ status: { nin: ['deleted', 'banned'] } }` | Value
|
|
48
|
+
| `nin` | `NOT IN` | `{ status: { nin: ['deleted', 'banned'] } }` | Value matches none in the array |
|
|
49
|
+
|
|
50
|
+
> [!NOTE]
|
|
51
|
+
> An empty array is a hard edge. `{ in: [] }` / `{ inq: [] }` match no rows; `{ nin: [] }` matches every row, because an empty exclusion list excludes nothing.
|
|
47
52
|
|
|
48
53
|
**See:** [List Operators Guide](./list-operators.md)
|
|
49
54
|
|
|
55
|
+
## Range Operators
|
|
56
|
+
|
|
57
|
+
| Operator | SQL | Example | Description |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `between` | `BETWEEN` | `{ age: { between: [18, 65] } }` | Value is within range, inclusive |
|
|
60
|
+
| `notBetween` | `NOT BETWEEN` | `{ age: { notBetween: [0, 18] } }` | Value is outside range |
|
|
61
|
+
|
|
62
|
+
Both require a 2-element array `[min, max]` - anything else throws.
|
|
63
|
+
|
|
64
|
+
**See:** [Range Operators Guide](./range-operators.md)
|
|
50
65
|
|
|
51
66
|
## Pattern Matching Operators
|
|
52
67
|
|
|
53
|
-
| Operator | SQL |
|
|
54
|
-
|
|
55
|
-
| `like` | `LIKE` | `{ name: { like: '%john%' } }` | Pattern match
|
|
56
|
-
| `nlike` | `NOT LIKE` | `{ name: { nlike: '%test%' } }` | Inverse
|
|
57
|
-
| `ilike` | `ILIKE` | `{ email: { ilike: '%@gmail.com' } }` | Pattern match
|
|
58
|
-
| `nilike` | `NOT ILIKE` | `{ email: { nilike: '%spam%' } }` | Inverse
|
|
68
|
+
| Operator | SQL | Example | Description |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| `like` | `LIKE` | `{ name: { like: '%john%' } }` | Pattern match, case-sensitive |
|
|
71
|
+
| `nlike` | `NOT LIKE` | `{ name: { nlike: '%test%' } }` | Inverse, case-sensitive |
|
|
72
|
+
| `ilike` | `ILIKE` | `{ email: { ilike: '%@gmail.com' } }` | Pattern match, case-insensitive |
|
|
73
|
+
| `nilike` | `NOT ILIKE` | `{ email: { nilike: '%spam%' } }` | Inverse, case-insensitive |
|
|
59
74
|
| `regexp` | `~` | `{ code: { regexp: '^[A-Z]{3}$' } }` | Regular expression (PostgreSQL) |
|
|
60
75
|
| `iregexp` | `~*` | `{ code: { iregexp: '^[a-z]{3}$' } }` | Case-insensitive regex (PostgreSQL) |
|
|
61
76
|
|
|
62
|
-
**
|
|
63
|
-
- `%` - Matches any sequence of characters
|
|
64
|
-
- `_` - Matches any single character
|
|
77
|
+
**Wildcards:** `%` matches any sequence of characters, `_` matches any single character.
|
|
65
78
|
|
|
66
79
|
**See:** [Pattern Matching Guide](./pattern-matching.md)
|
|
67
80
|
|
|
68
|
-
|
|
69
|
-
## Null Check Operators
|
|
70
|
-
|
|
71
|
-
| Operator | SQL | TypeScript Example | Description |
|
|
72
|
-
|----------|-----|-------------------|-------------|
|
|
73
|
-
| `is` | `IS NULL` / `=` | `{ deletedAt: { is: null } }` | IS NULL when value is `null`, equality otherwise |
|
|
74
|
-
| `isn` | `IS NOT NULL` / `!=` | `{ email: { isn: null } }` | IS NOT NULL when value is `null`, not-equal otherwise |
|
|
75
|
-
|
|
76
|
-
**Shorthand Syntax:**
|
|
77
|
-
```typescript
|
|
78
|
-
// Direct null assignment (implicit IS NULL)
|
|
79
|
-
{ deletedAt: null }
|
|
80
|
-
// SQL: WHERE "deleted_at" IS NULL
|
|
81
|
-
|
|
82
|
-
// Using eq with null
|
|
83
|
-
{ deletedAt: { eq: null } }
|
|
84
|
-
// SQL: WHERE "deleted_at" IS NULL
|
|
85
|
-
|
|
86
|
-
// Using ne with null
|
|
87
|
-
{ deletedAt: { ne: null } }
|
|
88
|
-
// SQL: WHERE "deleted_at" IS NOT NULL
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
**See:** [Null Operators Guide](./null-operators.md)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
## Presence & Negation Operators
|
|
95
|
-
|
|
96
|
-
| Operator | SQL | TypeScript Example | Description |
|
|
97
|
-
|----------|-----|-------------------|-------------|
|
|
98
|
-
| `exists` | `IS NOT NULL` / `IS NULL` | `{ deletedAt: { exists: false } }` | `exists: true` -> IS NOT NULL, `exists: false` -> IS NULL |
|
|
99
|
-
| `notExists` | `IS NULL` / `IS NOT NULL` | `{ verifiedAt: { notExists: true } }` | Inverse of `exists` (`notExists: true` -> IS NULL) |
|
|
100
|
-
| `not` | `NOT (...)` | `{ status: { not: 'archived' } }` / `{ views: { not: { gt: 100 } } }` | Negates the nested condition; a bare value negates `eq` |
|
|
101
|
-
|
|
102
|
-
`exists`/`notExists`/`not` are supported on the PostgreSQL connector. `not` recurses: `{ not: { gt: 100 } }` becomes `NOT (col > 100)`, and `{ not: 5 }` becomes `NOT (col = 5)`. `exists` also works over JSON paths on PostgreSQL (`{ 'metadata.score': { exists: true } }`).
|
|
103
|
-
|
|
104
|
-
**See:** [Null Operators Guide](./null-operators.md) (`exists`/`notExists`), [Logical Operators Guide](./logical-operators.md) (`not`)
|
|
105
|
-
|
|
106
|
-
|
|
107
81
|
## Logical Operators
|
|
108
82
|
|
|
109
|
-
| Operator | SQL |
|
|
110
|
-
|
|
111
|
-
| `and` | `AND` | `{ and: [{ age: { gt: 18 } }, { status: 'active' }] }` |
|
|
83
|
+
| Operator | SQL | Example | Description |
|
|
84
|
+
|---|---|---|---|
|
|
85
|
+
| `and` | `AND` | `{ and: [{ age: { gt: 18 } }, { status: 'active' }] }` | Every condition must be true |
|
|
112
86
|
| `or` | `OR` | `{ or: [{ role: 'admin' }, { role: 'moderator' }] }` | At least one condition must be true |
|
|
113
|
-
| `
|
|
87
|
+
| `not` | `NOT (...)` | `{ status: { not: 'archived' } }` / `{ views: { not: { gt: 100 } } }` | Negates the nested condition; a bare value negates `eq` |
|
|
88
|
+
| (implicit) | `AND` | `{ status: 'active', age: { gte: 18 } }` | Multiple top-level `where` keys are ANDed together |
|
|
89
|
+
| `and: []` | (dropped) | `{ and: [] }` | Vacuously true - no condition added |
|
|
114
90
|
| `or: []` | `false` | `{ or: [] }` | Vacuously false - matches no rows |
|
|
115
91
|
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
// Multiple fields = implicit AND
|
|
119
|
-
{
|
|
120
|
-
status: 'active',
|
|
121
|
-
age: { gte: 18 },
|
|
122
|
-
role: 'user'
|
|
123
|
-
}
|
|
124
|
-
// WHERE status = 'active' AND age >= 18 AND role = 'user'
|
|
125
|
-
```
|
|
92
|
+
`not` recurses: `{ not: { gt: 100 } }` becomes `NOT (col > 100)`; `{ not: 5 }` becomes `NOT (col = 5)`; `{ not: null }` becomes `IS NOT NULL`.
|
|
126
93
|
|
|
127
|
-
|
|
94
|
+
`exists`/`notExists` also work over JSON paths (`{ 'metadata.score': { exists: true } }`).
|
|
128
95
|
|
|
129
96
|
**See:** [Logical Operators Guide](./logical-operators.md)
|
|
130
97
|
|
|
98
|
+
## Array Operators (PostgreSQL)
|
|
131
99
|
|
|
132
|
-
|
|
100
|
+
For array columns (`varchar[]`, `text[]`, `integer[]`, and so on) - not to be confused with `in`/`nin`, which match a scalar against a list.
|
|
133
101
|
|
|
134
|
-
|
|
102
|
+
| Operator | SQL | Example | Description |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| `contains` | `@>` | `{ tags: { contains: ['typescript', 'nodejs'] } }` | Column array contains ALL given elements |
|
|
105
|
+
| `containedBy` | `<@` | `{ tags: { containedBy: ['ts', 'js', 'go', 'rust'] } }` | Column array is a subset of the given array |
|
|
106
|
+
| `overlaps` | `&&` | `{ tags: { overlaps: ['react', 'vue', 'angular'] } }` | Arrays share at least one element |
|
|
135
107
|
|
|
136
|
-
|
|
137
|
-
|----------|------------|-------------------|-------------|
|
|
138
|
-
| `contains` | `@>` | `{ tags: { contains: ['typescript', 'nodejs'] } }` | Array contains **ALL** specified elements |
|
|
139
|
-
| `containedBy` | `<@` | `{ tags: { containedBy: ['ts', 'js', 'go', 'rust'] } }` | Array is subset of specified array |
|
|
140
|
-
| `overlaps` | `&&` | `{ tags: { overlaps: ['react', 'vue', 'angular'] } }` | Arrays have at least one common element |
|
|
141
|
-
|
|
142
|
-
**Important:** These are array-specific operators, not to be confused with `in`/`nin` which match scalar values against an array.
|
|
108
|
+
A scalar operand is wrapped into a single-element array automatically.
|
|
143
109
|
|
|
144
110
|
**See:** [Array Operators Guide](./array-operators.md)
|
|
145
111
|
|
|
112
|
+
## JSON Path Operators (PostgreSQL)
|
|
146
113
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
Query nested fields within JSON/JSONB columns using dot notation as the key.
|
|
150
|
-
|
|
151
|
-
### JSON Path Syntax
|
|
114
|
+
A dot-notation key targets a JSON/JSONB column instead of a top-level one.
|
|
152
115
|
|
|
153
116
|
| Syntax | Example | Description |
|
|
154
|
-
|
|
155
|
-
| Dot notation | `{ 'metadata.user.name': 'John' }` | Access nested
|
|
156
|
-
| Array index | `{ 'metadata.tags[0]': 'urgent' }` | Access array
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| Dot notation | `{ 'metadata.user.name': 'John' }` | Access a nested property |
|
|
119
|
+
| Array index | `{ 'metadata.tags[0]': 'urgent' }` | Access an array element |
|
|
157
120
|
| Combined | `{ 'metadata.users[0].email': value }` | Nested arrays and objects |
|
|
158
121
|
|
|
159
|
-
|
|
122
|
+
**Supported operators:** `eq`, `ne`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `inq`, `nin`, `like`, `nlike`, `ilike`, `nilike`, `between`, `notBetween`, `regexp`, `iregexp`, `is`, `isn`, `exists`, `notExists`, `not`. That's the same set as top-level columns, minus the array operators (`contains`/`containedBy`/`overlaps`), which need a real array column.
|
|
160
123
|
|
|
161
|
-
|
|
162
|
-
// Equality (string comparison via #>>)
|
|
163
|
-
{ 'metadata.user.role': 'admin' }
|
|
164
|
-
// SQL: "metadata" #>> '{user,role}' = 'admin'
|
|
165
|
-
|
|
166
|
-
// Numeric comparison (safe casting via CASE/numeric)
|
|
167
|
-
{ 'metadata.score': { gt: 80 } }
|
|
168
|
-
|
|
169
|
-
// Pattern matching
|
|
170
|
-
{ 'metadata.level': { ilike: '%high%' } }
|
|
171
|
-
// SQL: "metadata" #>> '{level}' ILIKE '%high%'
|
|
172
|
-
|
|
173
|
-
// Multiple JSON conditions
|
|
174
|
-
{
|
|
175
|
-
and: [
|
|
176
|
-
{ 'metadata.user.age': { gt: 18 } },
|
|
177
|
-
{ 'metadata.user.country': 'US' }
|
|
178
|
-
]
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Supported Operators with JSON Paths
|
|
183
|
-
|
|
184
|
-
All comparison operators work with JSON path queries:
|
|
185
|
-
- `eq`, `ne`, `neq`, `gt`, `gte`, `lt`, `lte`
|
|
186
|
-
- `in`, `inq`, `nin`
|
|
187
|
-
- `like`, `nlike`, `ilike`, `nilike`
|
|
188
|
-
- `between`, `notBetween`
|
|
189
|
-
- `regexp`, `iregexp`
|
|
190
|
-
- `is`, `isn`
|
|
191
|
-
- `exists`, `notExists`, `not`
|
|
192
|
-
|
|
193
|
-
Numeric operators (`gt`, `gte`, `lt`, `lte`, `between`, `notBetween`) use safe numeric casting to handle mixed JSON value types.
|
|
124
|
+
Numeric operators cast the extracted text to `numeric` automatically: `gt`, `gte`, `lt`, `lte`, `between`, `notBetween`, and `eq`/`ne`/`neq`/`in`/`inq`/`nin` when the operand is a number. So `{ 'metadata.score': { gt: 80 } }` compares as a number, not a string.
|
|
194
125
|
|
|
195
126
|
**See:** [JSON Filtering Guide](./json-filtering.md)
|
|
196
127
|
|
|
128
|
+
## Fields, Order & Pagination
|
|
197
129
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Ordering
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
// Single field
|
|
215
|
-
{ order: ['createdAt DESC'] }
|
|
216
|
-
|
|
217
|
-
// Multiple fields
|
|
218
|
-
{ order: ['status ASC', 'createdAt DESC'] }
|
|
219
|
-
|
|
220
|
-
// Default direction is ASC
|
|
221
|
-
{ order: ['name'] } // Same as 'name ASC'
|
|
222
|
-
|
|
223
|
-
// JSON path ordering
|
|
224
|
-
{ order: ['metadata.priority DESC'] }
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Pagination
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
{
|
|
231
|
-
limit: 10, // Max records to return (default: 10)
|
|
232
|
-
skip: 20, // Skip first 20 records (alias: offset)
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Page 3 with 10 items per page
|
|
236
|
-
{
|
|
237
|
-
limit: 10,
|
|
238
|
-
skip: 20, // (page - 1) * limit = (3 - 1) * 10
|
|
239
|
-
}
|
|
240
|
-
```
|
|
130
|
+
| Property | Syntax | Example | Result |
|
|
131
|
+
|---|---|---|---|
|
|
132
|
+
| `fields` (array) | `string[]` | `fields: ['id', 'name', 'email']` | `SELECT` only those columns |
|
|
133
|
+
| `fields` (object) | `{ field: true }` | `fields: { id: true, name: true }` | Same - inclusion-only, `false` is ignored |
|
|
134
|
+
| `order` | `'field ASC'` / `'field DESC'` | `order: ['createdAt DESC']` | `ORDER BY`; default direction is `ASC` (`order: ['name']` = `'name ASC'`) |
|
|
135
|
+
| `order` (JSON path) | `'a.b DESC'` | `order: ['metadata.priority DESC']` | `ORDER BY` on a JSON path |
|
|
136
|
+
| `limit` | number | `limit: 10` | `LIMIT`; omitted -> `query.limit ?? settings.defaultLimit ?? 10` |
|
|
137
|
+
| `skip` | number | `skip: 20` | `OFFSET`; alias of `offset` - `skip` wins if both are given |
|
|
138
|
+
| `offset` | number | `offset: 20` | `OFFSET`; alias of `skip` |
|
|
241
139
|
|
|
242
140
|
**See:** [Fields, Ordering & Pagination Guide](./fields-order-pagination.md)
|
|
243
141
|
|
|
142
|
+
## Default Filter
|
|
244
143
|
|
|
245
|
-
|
|
144
|
+
A model's `settings.defaultFilter` merges into every read, update, and delete for that model.
|
|
246
145
|
|
|
247
|
-
|
|
146
|
+
| Collision shape | Result |
|
|
147
|
+
|---|---|
|
|
148
|
+
| Different keys | AND-composed - `{ isDeleted: false }` default + `{ status: 'published' }` caller filter -> `WHERE "isDeleted" = false AND "status" = 'published'` |
|
|
149
|
+
| Same key, scalar vs. scalar | Caller wins - the one override escape, no `shouldSkipDefaultFilter` needed |
|
|
150
|
+
| Same key, scalar vs. operator object (either side) | AND-composed |
|
|
151
|
+
| Same key, both `and` | Concatenated - both groups hold |
|
|
152
|
+
| Same key, both `or` | Kept as two separate conjuncts, never unioned |
|
|
248
153
|
|
|
249
154
|
```typescript
|
|
250
|
-
|
|
251
|
-
type: 'entity',
|
|
252
|
-
settings: {
|
|
253
|
-
defaultFilter: {
|
|
254
|
-
where: { isDeleted: false },
|
|
255
|
-
limit: 100,
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
})
|
|
259
|
-
export class User extends BaseEntity<typeof User.schema> {
|
|
260
|
-
static override schema = userTable;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// All queries automatically include the default filter
|
|
264
|
-
await userRepository.find({ filter: {} });
|
|
265
|
-
// WHERE isDeleted = false LIMIT 100
|
|
266
|
-
|
|
267
|
-
// Skip default filter for admin operations
|
|
155
|
+
// Skip the default filter entirely
|
|
268
156
|
await userRepository.find({
|
|
269
|
-
filter: {},
|
|
157
|
+
filter: { where: { status: 'published' } },
|
|
270
158
|
options: { shouldSkipDefaultFilter: true },
|
|
271
159
|
});
|
|
272
|
-
// No automatic filter applied
|
|
273
160
|
```
|
|
274
161
|
|
|
275
162
|
**See:** [Default Filter Guide](./default-filter.md)
|
|
@@ -280,5 +167,6 @@ await userRepository.find({
|
|
|
280
167
|
|
|
281
168
|
**Files:**
|
|
282
169
|
|
|
283
|
-
- [`packages/core/src/connectors/
|
|
284
|
-
- [`packages/core/src/
|
|
170
|
+
- [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, translates `TFilter` to Drizzle/SQL
|
|
171
|
+
- [`packages/core-server/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, one handler per operator
|
|
172
|
+
- [`packages/filter/src/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/filter/src/common/operators.ts) - `QueryOperators`/`Sorts` constants
|
|
@@ -6,76 +6,48 @@ difficulty: intermediate
|
|
|
6
6
|
|
|
7
7
|
# Range Operators
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Matches a field against a `[min, max]` range.
|
|
10
10
|
|
|
11
|
+
| Operator | SQL | Meaning |
|
|
12
|
+
|----------|-----|---------|
|
|
13
|
+
| `between` | `BETWEEN ... AND ...` | Value is within the range (inclusive) |
|
|
14
|
+
| `notBetween` | `NOT (... BETWEEN ... AND ...)` | Value is outside the range |
|
|
11
15
|
|
|
12
16
|
## between
|
|
13
17
|
|
|
14
|
-
Find values within a range (inclusive):
|
|
15
|
-
|
|
16
18
|
```typescript
|
|
17
|
-
// Numeric range
|
|
18
19
|
{ where: { price: { between: [100, 500] } } }
|
|
19
20
|
// SQL: WHERE "price" BETWEEN 100 AND 500
|
|
20
|
-
|
|
21
|
-
// Date range
|
|
22
|
-
{
|
|
23
|
-
where: {
|
|
24
|
-
createdAt: {
|
|
25
|
-
between: [new Date('2024-01-01'), new Date('2024-12-31')]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
// SQL: WHERE "created_at" BETWEEN '2024-01-01' AND '2024-12-31'
|
|
30
|
-
|
|
31
|
-
// String range (lexicographic)
|
|
32
|
-
{ where: { lastName: { between: ['A', 'M'] } } }
|
|
33
|
-
// SQL: WHERE "last_name" BETWEEN 'A' AND 'M'
|
|
34
21
|
```
|
|
35
22
|
|
|
36
|
-
|
|
37
|
-
> The value MUST be an array with exactly 2 elements `[min, max]`. Invalid values throw an error:
|
|
38
|
-
> ```
|
|
39
|
-
> Error: [BETWEEN] Invalid value: expected array of 2 elements, got ...
|
|
40
|
-
> ```
|
|
23
|
+
**Notice:** both bounds are inclusive.
|
|
41
24
|
|
|
25
|
+
**Edge cases:**
|
|
26
|
+
- The value must be a 2-element array `[min, max]`; anything else throws `[PostgresQueryOperators][BETWEEN] Invalid value: expected array of 2 elements, got ...`.
|
|
27
|
+
- If either bound is `null`, the condition matches no rows (SQL `NULL` comparison).
|
|
28
|
+
- If `min > max`, the condition matches no rows.
|
|
42
29
|
|
|
43
30
|
## notBetween
|
|
44
31
|
|
|
45
|
-
Find values outside a range:
|
|
46
|
-
|
|
47
32
|
```typescript
|
|
48
33
|
{ where: { score: { notBetween: [40, 60] } } }
|
|
49
34
|
// SQL: WHERE NOT ("score" BETWEEN 40 AND 60)
|
|
50
|
-
// Matches: scores < 40 OR scores > 60
|
|
51
35
|
```
|
|
52
36
|
|
|
53
|
-
|
|
54
|
-
> Same validation as `between` -- the value MUST be an array with exactly 2 elements.
|
|
55
|
-
|
|
37
|
+
**Notice:** matches values strictly outside the range.
|
|
56
38
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// Equivalent to between: [100, 500]
|
|
63
|
-
{ where: { price: { gte: 100, lte: 500 } } }
|
|
64
|
-
// SQL: WHERE "price" >= 100 AND "price" <= 500
|
|
65
|
-
|
|
66
|
-
// Exclusive range (not including boundaries)
|
|
67
|
-
{ where: { price: { gt: 100, lt: 500 } } }
|
|
68
|
-
// SQL: WHERE "price" > 100 AND "price" < 500
|
|
69
|
-
```
|
|
39
|
+
**Edge cases:**
|
|
40
|
+
- Same 2-element array validation as `between`, throwing `[PostgresQueryOperators][NOT_BETWEEN] Invalid value: expected array of 2 elements, got ...`.
|
|
41
|
+
- A `NULL` column matches neither `between` nor `notBetween`.
|
|
70
42
|
|
|
71
43
|
## See also
|
|
72
44
|
|
|
73
45
|
- [Filter System Overview](./) - the `filter` shape and the full `where` operator table
|
|
74
|
-
- [Comparison Operators](./comparison-operators) - `gt`/`gte`/`lt`/`lte`, the
|
|
46
|
+
- [Comparison Operators](./comparison-operators) - `gt`/`gte`/`lt`/`lte`, which can express the same range as an alternative to `between`/`notBetween`
|
|
75
47
|
- [Quick Reference](./quick-reference) - every operator, one line each
|
|
76
48
|
|
|
77
49
|
**Files:**
|
|
78
50
|
|
|
79
|
-
- [`packages/core/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, per-operator SQL builders
|
|
80
|
-
- [`packages/core/src/connectors/
|
|
81
|
-
- [`packages/
|
|
51
|
+
- [`packages/core-server/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, per-operator SQL builders
|
|
52
|
+
- [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, translates `TFilter` to Drizzle/SQL
|
|
53
|
+
- [`packages/filter/src/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/filter/src/common/operators.ts) - `QueryOperators` constants
|
|
@@ -6,11 +6,11 @@ difficulty: intermediate
|
|
|
6
6
|
|
|
7
7
|
# Pro Tips & Edge Cases
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
A filter can return the wrong rows even when every operator name looks right. Each entry below is verified against `FilterBuilder`/`PostgresQueryOperators` in `packages/core-server`.
|
|
10
10
|
|
|
11
11
|
## `NOT IN` and `!=` silently exclude `NULL`
|
|
12
12
|
|
|
13
|
-
SQL three-valued logic, not an IGNIS quirk
|
|
13
|
+
This is SQL three-valued logic, not an IGNIS quirk. A row whose column is `NULL` never matches `nin`, `ne`, or `neq`, because `NULL <> value` evaluates to UNKNOWN rather than TRUE.
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
16
|
{ where: { status: { nin: ['deleted'] } } }
|
|
@@ -38,7 +38,7 @@ if (ids.length === 0) {
|
|
|
38
38
|
|
|
39
39
|
## JSON numeric comparisons need actual JSON numbers
|
|
40
40
|
|
|
41
|
-
A JSON path comparison casts safely with `CASE WHEN (...) ~ '^-?[0-9]+(\.[0-9]+)?$' THEN (...)::numeric ELSE NULL END
|
|
41
|
+
A JSON path comparison casts safely with `CASE WHEN (...) ~ '^-?[0-9]+(\.[0-9]+)?$' THEN (...)::numeric ELSE NULL END`. The regex has to match, or the cast yields `NULL` and the row is excluded:
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
44
|
// { "priority": "3" } (string) - regex matches "3" -> casts to numeric 3 -> 3 > 2 matches
|
|
@@ -84,7 +84,7 @@ Store numbers as JSON numbers (`{ "priority": 3 }`), not numeric strings, to avo
|
|
|
84
84
|
```typescript
|
|
85
85
|
{ fields: { id: true, name: true, email: true } }
|
|
86
86
|
|
|
87
|
-
// Setting a key to `false` does NOT exclude it - the key is
|
|
87
|
+
// Setting a key to `false` does NOT exclude it - the key is ignored.
|
|
88
88
|
// To exclude fields, list only the ones you want, as an array:
|
|
89
89
|
{ fields: ['id', 'name', 'email'] }
|
|
90
90
|
```
|
|
@@ -150,5 +150,5 @@ const products = await productRepository.find({
|
|
|
150
150
|
|
|
151
151
|
**Files:**
|
|
152
152
|
|
|
153
|
-
- [`packages/core/src/connectors/
|
|
154
|
-
- [`packages/core/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, empty-array and array-operator handling
|
|
153
|
+
- [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, JSON path casting, `toColumns`
|
|
154
|
+
- [`packages/core-server/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, empty-array and array-operator handling
|