@travetto/model-query 3.0.2 → 3.0.3
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/README.md +27 -37
- package/package.json +5 -5
- package/support/doc.support.tsx +29 -0
- package/support/doc.support.ts +0 -29
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<!-- This file was generated by @travetto/doc and should not be modified directly -->
|
|
2
|
-
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/model-query/DOC.
|
|
2
|
+
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/model-query/DOC.tsx and execute "npx trv doc" to rebuild -->
|
|
3
3
|
# Data Model Querying
|
|
4
|
+
|
|
4
5
|
## Datastore abstraction for advanced query support.
|
|
5
6
|
|
|
6
7
|
**Install: @travetto/model-query**
|
|
@@ -16,7 +17,7 @@ This module provides an enhanced query contract for [Data Modeling Support](http
|
|
|
16
17
|
|
|
17
18
|
## Contracts
|
|
18
19
|
|
|
19
|
-
###
|
|
20
|
+
### Query
|
|
20
21
|
This contract provides the ability to apply the query support to return one or many items, as well as providing counts against a specific query.
|
|
21
22
|
|
|
22
23
|
**Code: Query**
|
|
@@ -44,7 +45,7 @@ export interface ModelQuerySupport {
|
|
|
44
45
|
}
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
###
|
|
48
|
+
### Crud
|
|
48
49
|
Reinforcing the complexity provided in these contracts, the [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/crud.ts#L11) contract allows for bulk update/deletion by query. This requires the underlying implementation to support these operations.
|
|
49
50
|
|
|
50
51
|
**Code: Query Crud**
|
|
@@ -66,10 +67,10 @@ export interface ModelQueryCrudSupport extends ModelCrudSupport, ModelQuerySuppo
|
|
|
66
67
|
}
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
###
|
|
70
|
+
### Facet
|
|
70
71
|
With the complex nature of the query support, the ability to find counts by groups is a common and desirable pattern. This contract allows for faceting on a given field, with query filtering.
|
|
71
72
|
|
|
72
|
-
**Code: Facet**
|
|
73
|
+
**Code: Query Facet**
|
|
73
74
|
```typescript
|
|
74
75
|
export interface ModelQueryFacetSupport extends ModelQuerySupport {
|
|
75
76
|
/**
|
|
@@ -82,10 +83,10 @@ export interface ModelQueryFacetSupport extends ModelQuerySupport {
|
|
|
82
83
|
}
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
###
|
|
86
|
+
### Suggest
|
|
86
87
|
Additionally, this same pattern avails it self in a set of suggestion methods that allow for powering auto completion and type-ahead functionalities.
|
|
87
88
|
|
|
88
|
-
**Code: Suggest**
|
|
89
|
+
**Code: Query Suggest**
|
|
89
90
|
```typescript
|
|
90
91
|
export interface ModelQuerySuggestSupport extends ModelQuerySupport {
|
|
91
92
|
/**
|
|
@@ -110,37 +111,36 @@ export interface ModelQuerySuggestSupport extends ModelQuerySupport {
|
|
|
110
111
|
```
|
|
111
112
|
|
|
112
113
|
## Implementations
|
|
113
|
-
|
|
114
114
|
|Service|Query|QueryCrud|QueryFacet|
|
|
115
115
|
|-------|-----|---------|----------|
|
|
116
116
|
|[Elasticsearch Model Source](https://github.com/travetto/travetto/tree/main/module/model-elasticsearch#readme "Elasticsearch backing for the travetto model module, with real-time modeling support for Elasticsearch mappings.")|X|X|X|
|
|
117
|
-
|[MongoDB Model Support](https://github.com/travetto/travetto/tree/main/module/model-mongo#readme "Mongo backing for the travetto model module.")|X|X|X|
|
|
118
|
-
|[SQL Model Service](https://github.com/travetto/travetto/tree/main/module/model-sql#readme "SQL backing for the travetto model module, with real-time modeling support for SQL schemas.")|X|X|X|
|
|
117
|
+
|[MongoDB Model Support](https://github.com/travetto/travetto/tree/main/module/model-mongo#readme "Mongo backing for the travetto model module.")|X'|X'|X'|
|
|
118
|
+
|[SQL Model Service](https://github.com/travetto/travetto/tree/main/module/model-sql#readme "SQL backing for the travetto model module, with real-time modeling support for SQL schemas.")|X'|X'|X'|
|
|
119
119
|
|
|
120
120
|
## Querying
|
|
121
|
-
|
|
122
121
|
One of the complexities of abstracting multiple storage mechanisms, is providing a consistent query language. The query language the module uses is a derivation of [mongodb](https://mongodb.com)'s query language, with some restrictions, additions, and caveats. Additionally, given the nature of typescript, all queries are statically typed, and will catch type errors at compile time.
|
|
123
122
|
|
|
124
123
|
### General Fields
|
|
125
|
-
|
|
124
|
+
|
|
126
125
|
* `field: { $eq: T }` to determine if a field is equal to a value
|
|
127
126
|
* `field: { $ne: T }` to determine if a field is not equal to a value
|
|
128
127
|
* `field: { $exists: boolean }` to determine if a field exists or not
|
|
129
|
-
* `field: T` to see if the field is equal to whatever value is passed in
|
|
128
|
+
* `field: T` to see if the field is equal to whatever value is passed in`
|
|
130
129
|
|
|
131
130
|
### General Single Valued Fields
|
|
132
|
-
|
|
131
|
+
|
|
133
132
|
* `field: { $in: T[] }` to see if a record's value appears in the array provided to `$in`
|
|
134
133
|
* `field: { $nin: T[] }` to see if a record's value does not appear in the array provided to `$in`
|
|
135
134
|
|
|
136
135
|
### Ordered Numeric Fields
|
|
137
|
-
|
|
136
|
+
|
|
138
137
|
* `field: { $lt: number }` checks if value is less than
|
|
139
138
|
* `field: { $lte: number }` checks if value is less than or equal to
|
|
140
139
|
* `field: { $gt: number }` checks if value is greater than
|
|
141
140
|
* `field: { $gte: number }` checks if value is greater than or equal to
|
|
141
|
+
|
|
142
142
|
### Ordered Date Fields
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
* `field: { $lt: Date | RelativeTime }` checks if value is less than
|
|
145
145
|
* `field: { $lte: Date | RelativeTime }` checks if value is less than or equal to
|
|
146
146
|
* `field: { $gt: Date | RelativeTime }` checks if value is greater than
|
|
@@ -149,24 +149,23 @@ One of the complexities of abstracting multiple storage mechanisms, is providing
|
|
|
149
149
|
**Note**: Relative times are strings consisting of a number and a unit. e.g. -1w or 30d. These times are always relative to Date.now, but should make building queries more natural.
|
|
150
150
|
|
|
151
151
|
### Array Fields
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
* `field: { $all: T[]] }` checks to see if the records value contains everything within `$all`
|
|
154
154
|
|
|
155
155
|
### String Fields
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
* `field: { $regex: RegExp | string; }` checks the field against the regular expression
|
|
158
158
|
|
|
159
159
|
### Geo Point Fields
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
* `field: { $geoWithin: Point[] }` determines if the value is within the bounding region of the points
|
|
162
|
-
* `field: {
|
|
162
|
+
* `field: {$near: Point, $maxDistance: number, $unit: 'km' | 'm' | 'mi' | 'ft' }` searches at a point, and looks out radially
|
|
163
163
|
|
|
164
164
|
### Groupings
|
|
165
|
-
|
|
166
|
-
* `{ $and: [] }` provides a grouping in which all sub clauses are required
|
|
167
|
-
* `{ $or: [] }` provides a grouping in which at least one of the sub clauses is required
|
|
168
|
-
* `{ $not: { } }` negates a clause
|
|
169
165
|
|
|
166
|
+
* `{ $and: [] }` provides a grouping in which all sub clauses are require,
|
|
167
|
+
* `{ $or: [] }` provides a grouping in which at least one of the sub clauses is require,
|
|
168
|
+
* `{ $not: { } }` negates a clause
|
|
170
169
|
A sample query for `User`'s might be:
|
|
171
170
|
|
|
172
171
|
**Code: Using the query structure for specific queries**
|
|
@@ -203,11 +202,7 @@ export class UserSearch {
|
|
|
203
202
|
This would find all users who are over `35` and that have the `contact` field specified.
|
|
204
203
|
|
|
205
204
|
## Query Language
|
|
206
|
-
|
|
207
|
-
In addition to the standard query interface, the module also supports querying by query language to facilitate end-user queries. This is meant to act as an interface that is simpler to write than the default object structure.
|
|
208
|
-
|
|
209
|
-
The language itself is fairly simple, boolean logic, with parenthetical support. The operators supported are:
|
|
210
|
-
|
|
205
|
+
In addition to the standard query interface, the module also supports querying by query language to facilitate end - user queries.This is meant to act as an interface that is simpler to write than the default object structure. The language itself is fairly simple, boolean logic, with parenthetical support.The operators supported are:
|
|
211
206
|
* `<`, `<=` - Less than, and less than or equal to
|
|
212
207
|
* `>`, `>=` - Greater than, and greater than or equal to
|
|
213
208
|
* `!=`, `==` - Not equal to, and equal to
|
|
@@ -216,8 +211,7 @@ The language itself is fairly simple, boolean logic, with parenthetical support.
|
|
|
216
211
|
* `in`, `not-in` - Supports checking if a field is in a list of literal values
|
|
217
212
|
* `and`, `&&` - Intersection of clauses
|
|
218
213
|
* `or`, `||` - Union of clauses
|
|
219
|
-
|
|
220
|
-
All sub fields are dot separated for access, e.g. `user.address.city`. A query language version of the previous query could look like:
|
|
214
|
+
All sub fields are dot separated for access, e.g. `user.address.city`.A query language version of the previous query could look like:
|
|
221
215
|
|
|
222
216
|
**Code: Query language with boolean checks and exists check**
|
|
223
217
|
```sql
|
|
@@ -232,14 +226,10 @@ user.role in ['admin', 'root'] && (user.address.state == 'VA' || user.address.ci
|
|
|
232
226
|
```
|
|
233
227
|
|
|
234
228
|
### Regular Expression
|
|
235
|
-
|
|
236
|
-
When querying with regular expressions,patterns can be specified as `'strings'` or as `/patterns/`. The latter allows for the case insensitive modifier: `/pattern/i`. Supporting the insensitive flag is up to the underlying model implementation.
|
|
229
|
+
When querying with regular expressions, patterns can be specified as `'strings'` or as `/patterns/`. The latter allows for the case insensitive modifier: `/pattern/i`. Supporting the insensitive flag is up to the underlying model implementation.
|
|
237
230
|
|
|
238
231
|
## Custom Model Query Service
|
|
239
|
-
In addition to the provided contracts, the module also provides common utilities and shared test suites.
|
|
240
|
-
repetitive functionality, that is unable to be shared due to not relying upon inheritance (this was an intentional design decision). This allows for all the [Data Model Querying](https://github.com/travetto/travetto/tree/main/module/model-query#readme "Datastore abstraction for advanced query support.") implementations to completely own the functionality and also to be able to provide additional/unique functionality that goes beyond the interface.
|
|
241
|
-
|
|
242
|
-
To enforce that these contracts are honored, the module provides shared test suites to allow for custom implementations to ensure they are adhering to the contract's expected behavior.
|
|
232
|
+
In addition to the provided contracts, the module also provides common utilities and shared test suites.The common utilities are useful for repetitive functionality, that is unable to be shared due to not relying upon inheritance(this was an intentional design decision).This allows for all the [Data Model Querying](https://github.com/travetto/travetto/tree/main/module/model-query#readme "Datastore abstraction for advanced query support.") implementations to completely own the functionality and also to be able to provide additional / unique functionality that goes beyond the interface. To enforce that these contracts are honored, the module provides shared test suites to allow for custom implementations to ensure they are adhering to the contract's expected behavior.
|
|
243
233
|
|
|
244
234
|
**Code: MongoDB Service Test Configuration**
|
|
245
235
|
```typescript
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-query",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Datastore abstraction for advanced query support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"datastore",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"directory": "module/model-query"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/di": "^3.0.
|
|
31
|
-
"@travetto/model": "^3.0.
|
|
32
|
-
"@travetto/schema": "^3.0.
|
|
30
|
+
"@travetto/di": "^3.0.3",
|
|
31
|
+
"@travetto/model": "^3.0.3",
|
|
32
|
+
"@travetto/schema": "^3.0.3"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@travetto/test": "^3.0.
|
|
35
|
+
"@travetto/test": "^3.0.3"
|
|
36
36
|
},
|
|
37
37
|
"peerDependenciesMeta": {
|
|
38
38
|
"@travetto/test": {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** @jsxImportSource @travetto/doc */
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
import { RootIndex } from '@travetto/manifest';
|
|
5
|
+
import { d, DocJSXElementByFn, DocJSXElement } from '@travetto/doc';
|
|
6
|
+
|
|
7
|
+
export const Links = {
|
|
8
|
+
QueryCrud: d.codeLink('Query Crud', '@travetto/model-query/src/service/crud.ts', /export interface/),
|
|
9
|
+
QueryFacet: d.codeLink('Facet', '@travetto/model-query/src/service/facet.ts', /export interface/),
|
|
10
|
+
QuerySuggest: d.codeLink('Suggest', '@travetto/model-query/src/service/suggest.ts', /export interface/),
|
|
11
|
+
Query: d.codeLink('Query', '@travetto/model-query/src/service/query.ts', /export interface/),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const ModelQueryTypes = (file: string | Function): DocJSXElement[] => {
|
|
15
|
+
if (typeof file !== 'string') {
|
|
16
|
+
file = RootIndex.getFunctionMetadata(file)!.source;
|
|
17
|
+
}
|
|
18
|
+
const contents = readFileSync(file, 'utf8');
|
|
19
|
+
const found: DocJSXElementByFn<'CodeLink'>[] = [];
|
|
20
|
+
const seen = new Set();
|
|
21
|
+
for (const [, key] of contents.matchAll(/Model(Query(Suggest|Facet|Crud)?)Support/g)) {
|
|
22
|
+
if (!seen.has(key)) {
|
|
23
|
+
seen.add(key);
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
25
|
+
found.push(Links[key as keyof typeof Links]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return found.map(v => <li>{v}</li>);
|
|
29
|
+
};
|
package/support/doc.support.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
2
|
-
|
|
3
|
-
import { RootIndex } from '@travetto/manifest';
|
|
4
|
-
import { d } from '@travetto/doc';
|
|
5
|
-
import { AllTypeMap } from '@travetto/doc/src/nodes';
|
|
6
|
-
|
|
7
|
-
export const Links = {
|
|
8
|
-
QueryCrud: d.SnippetLink('Query Crud', '@travetto/model-query/src/service/crud.ts', /export interface/),
|
|
9
|
-
QueryFacet: d.SnippetLink('Facet', '@travetto/model-query/src/service/facet.ts', /export interface/),
|
|
10
|
-
QuerySuggest: d.SnippetLink('Suggest', '@travetto/model-query/src/service/suggest.ts', /export interface/),
|
|
11
|
-
Query: d.SnippetLink('Query', '@travetto/model-query/src/service/query.ts', /export interface/),
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const ModelQueryTypes = (file: string | Function): AllTypeMap['SnippetLink'][] => {
|
|
15
|
-
if (typeof file !== 'string') {
|
|
16
|
-
file = RootIndex.getFunctionMetadata(file)!.source;
|
|
17
|
-
}
|
|
18
|
-
const contents = readFileSync(file, 'utf8');
|
|
19
|
-
const found: AllTypeMap['SnippetLink'][] = [];
|
|
20
|
-
const seen = new Set();
|
|
21
|
-
for (const [, key] of contents.matchAll(/Model(Query(Suggest|Facet|Crud)?)Support/g)) {
|
|
22
|
-
if (!seen.has(key)) {
|
|
23
|
-
seen.add(key);
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
25
|
-
found.push(Links[key as keyof typeof Links]);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return found;
|
|
29
|
-
};
|