@graffy/pg 0.15.12 → 0.15.14-alpha.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/Readme.md +131 -3
- package/index.cjs +225 -162
- package/index.mjs +226 -163
- package/package.json +7 -5
- package/types/Db.d.ts +1 -0
- package/types/filter/getSql.d.ts +1 -3
- package/types/index.d.ts +2 -2
- package/types/sql/clauses.d.ts +2 -1
- package/types/sql/getArgSql.d.ts +2 -1
- package/types/sql/getMeta.d.ts +1 -0
- package/types/sql/select.d.ts +2 -2
- package/types/sql/upsert.d.ts +1 -0
package/Readme.md
CHANGED
|
@@ -10,9 +10,137 @@ import pg from '@graffy/pg';
|
|
|
10
10
|
graffyStore.use(pg(options));
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Uses the [pg](https://github.com/brianc/node-postgres) library.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Query filters
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Query filters are passed in `$key` and are JSON-based, somewhat like MongoDB.
|
|
18
18
|
|
|
19
|
+
1. Filters expressions follow a **property**, **operator**, **value** order. Values are scalar values (strings or numbers).
|
|
20
|
+
2. Property names are always object keys. They may be strings with dots `.`.
|
|
21
|
+
3. Operators are placed in objects as well and have a leading `$`.
|
|
22
|
+
4. Values are JSON values.
|
|
23
|
+
5. Multiple properties in an object are combined with `AND`. Items in an arrays are combined with `OR`.
|
|
24
|
+
6. The supported operators are:
|
|
25
|
+
- `$eq`: optional in most cases.
|
|
26
|
+
- `$lt`, `$lte`, `$gt`, `$gte`: Ranges
|
|
27
|
+
- `$re`, `$ire`: Regex match (case sensitive and insensitive versions)
|
|
28
|
+
- `$text`: Full text search, always case insensitive
|
|
29
|
+
- `$not`: Modifies other filters or inverts a condition
|
|
30
|
+
- `$and`, `$or`: Combines conditions; optional in most cases
|
|
31
|
+
- `$all`, `$has`, `$any`: Apply conditions to the elements of a collection (list or map)
|
|
32
|
+
|
|
33
|
+
#### Basic
|
|
34
|
+
|
|
35
|
+
1. `{ foo: 5 }` and `{ foo: { $eq: 5 } }` compile to SQL `foo = 5`.
|
|
36
|
+
2. `{ foo: { $gt: 5, $lt: 6 } }` becomes `foo > 5 AND foo < 6`.
|
|
37
|
+
3. `{ foo: { $ire: '^wor.*' } }` becomes `foo ~* "^wor.*"`.
|
|
38
|
+
4. `{ foo: { $text: 'potatoes' } }` becomes `foo @@ websearch_to_tsquery('potatoes')`.
|
|
39
|
+
For this to work, `foo` must be a TSVector column.
|
|
40
|
+
|
|
41
|
+
#### Or
|
|
42
|
+
|
|
43
|
+
1. `{ foo: [5, 6] }` means *foo equals 5 or foo equals 6*, and the compiler is smart enough to simplify this to `foo IN (5, 6)`. There is no separate $in.
|
|
44
|
+
2. `{ foo: [ 5, { $gt: 6 } ] }` becomes `foo = 5 OR foo > 6`
|
|
45
|
+
3. `[ { foo: 6 }, { bar: 7 } ]` becomes `foo = 6 OR bar = 7`
|
|
46
|
+
|
|
47
|
+
#### Not
|
|
48
|
+
|
|
49
|
+
1. `{ foo: { $not: 6 } }` becomes `foo <> 6` (the SQL not equals operator)
|
|
50
|
+
2. `{ foo: { $not: [5, 6] }` becomes `foo NOT IN (5, 6)`
|
|
51
|
+
3. `{ foo: { $not: [ 5, { $gt: 6 } ] } }` becomes `NOT (foo = 5 OR foo > 6)`
|
|
52
|
+
|
|
53
|
+
#### Logic
|
|
54
|
+
|
|
55
|
+
1. By default, objects mean `AND` and arrays mean `OR`:
|
|
56
|
+
`[ { foo: 5, bar: 6 }, { baz: 7, qux: 4 } ]` becomes
|
|
57
|
+
`(foo = 5 AND bar = 6) OR (baz = 7 AND qux = 4)`
|
|
58
|
+
2. Use `$and` and `$or` operators explicitly to use any structure in either context:
|
|
59
|
+
|
|
60
|
+
`{ $and: [ { $or: { foo: 5, bar: 6 } }, { $or: { baz: 7, qux: 4 } } ] }` becomes
|
|
61
|
+
`(foo = 5 OR bar = 6) AND (baz = 7 OR qux = 4)`.
|
|
62
|
+
|
|
63
|
+
#### Contains and Contained by
|
|
64
|
+
|
|
65
|
+
1. `{ tags: { $cts: ['foo', 'bar'] } }` becomes `tags @> '{"foo","bar"}'`.
|
|
66
|
+
Tags must contain both *foo* and *bar*. Note that the array of conditions here does not have `OR` semantics.
|
|
67
|
+
2. `{ tags: { $ctd: ['foo', 'bar', 'baz'] } }` becomes `tags <@ '{"foo","bar","baz"}'`.
|
|
68
|
+
Every tag must be one of *foo*, *bar* or *baz*.
|
|
69
|
+
|
|
70
|
+
#### Notes
|
|
71
|
+
|
|
72
|
+
1. We drop several MongoDB operators while retaining the capability:
|
|
73
|
+
- `$ne`: Use $not instead.
|
|
74
|
+
- `$in`: Use an array of values; it is a combination of implicit $or and $eq.
|
|
75
|
+
- `$nin`: Use $not and an array of values.
|
|
76
|
+
- `$exists`: Use `null` or `{ $not: null }`. Postgres does not distinguish between `undefined` and `null`, and neither does Graffy (in this context at least; it's complicated.)
|
|
77
|
+
2. Graffy `$has` is equivalent to MongoDB `$all` (each of the provided conditions is met by at least one element in the array). Graffy `$all` (every element of the array meets a condition) has no direct MongoDB equivalent, but can be expressed as `{ $not: { $elemMatch: { $not: (cond) } } }`
|
|
78
|
+
3. Graffy has a separate operator for case-insensitive regex, and configures the text search locale in the database object rather than the query. This makes MongoDB's regex `$options`, full text `$language` etc. unnecessary.
|
|
79
|
+
4. Graffy does not have equivalents for MongoDB operators `$type`, `$expr`, `$jsonSchema`, `$where`, `$mod`, `$size` and the geospatial operators.
|
|
80
|
+
|
|
81
|
+
### Order by
|
|
82
|
+
|
|
83
|
+
The root of the Graffy filter object must be an object. (Use `$or` if required.) The property `$order` specifies the order. Its value must be an array of order specifiers, each of which may be a string property name or an object with property names, sort direction, collation and text search relevance. (TBD)
|
|
84
|
+
|
|
85
|
+
### Full Text Search
|
|
86
|
+
|
|
87
|
+
A full-text search query typically has three requirements:
|
|
88
|
+
|
|
89
|
+
- Filter: `{ tsv: { $text: 'query' } }`. Return only results that match.
|
|
90
|
+
- Order: `{ $order: [{ $text: ['tsv', 'query'] }], ... }`. Sort results by relevance.
|
|
91
|
+
- Projection: `{ tsv: { query: true } }`. Return snippets of the document surrounding matches.
|
|
92
|
+
|
|
93
|
+
In all three, `tsv` is a computed column of type TSVector.
|
|
94
|
+
|
|
95
|
+
### Aggregations
|
|
96
|
+
|
|
97
|
+
In Graffy PG, aggregations are specified using the `$group` argument in $key, and special properties like `$count`, `$sum` etc. in the projection. `$group` may be `true` or an array.
|
|
98
|
+
|
|
99
|
+
Consider a table of books with columns `authorId` and `copiesSold`. We want the to compute aggregates on the `copiesSold` column.
|
|
100
|
+
|
|
101
|
+
#### Without Group By
|
|
102
|
+
|
|
103
|
+
Let's say we want the total copies sold of all the books in our database. We use `$group: true`, like:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
{
|
|
107
|
+
books: {
|
|
108
|
+
$key: { $group: true },
|
|
109
|
+
$sum: { copiesSold: true }
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Note how the field to sum is specified; this way, multiple fields may be specified.
|
|
114
|
+
|
|
115
|
+
As always, the result will mirror the query:
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
books: [{
|
|
119
|
+
$key: { $group: true },
|
|
120
|
+
$sum: { copiesSold: 12345 }
|
|
121
|
+
}]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### With Group By
|
|
125
|
+
|
|
126
|
+
Now let's say we want the separate totals for each author. As we might have a very large number of authors, we might need to paginate over the results.
|
|
127
|
+
|
|
128
|
+
The grouping properties (e.g. `authorId`) may also be included in the projection, and these values may even be used to construct links.
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
{
|
|
132
|
+
books: {
|
|
133
|
+
$key: { $group: ['authorId'], $first: 30 },
|
|
134
|
+
authorId: true,
|
|
135
|
+
author: { namme: true }, // Link to ['users', authorId]
|
|
136
|
+
$sum: { copiesSold: true }
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Aggregate functions
|
|
141
|
+
|
|
142
|
+
Graffy supports the following aggregate functions.
|
|
143
|
+
|
|
144
|
+
- `$count` of rows; this is just specified as `$count: true`, without any fields under it. (All other aggregate functions require fields to be specified.)
|
|
145
|
+
- `$sum`, `$avg`, `$max`, `$min`
|
|
146
|
+
- `$card` (cardinality), or the number of unique values in a column
|