@@ -220,13 +220,14 @@ for more examples.
220
220
GIN indexes
221
221
-----------
222
222
223
- JsQuery extension contains two operator classes (opclasses) for GIN which
223
+ JsQuery extension contains three operator classes (opclasses) for GIN which
224
224
provide different kinds of query optimization.
225
225
226
226
* ` jsonb_path_value_ops `
227
+ * ` jsonb_laxpath_value_ops `
227
228
* ` jsonb_value_path_ops `
228
229
229
- In each of two GIN opclasses jsonb documents are decomposed into entries. Each
230
+ In each of GIN opclasses jsonb documents are decomposed into entries. Each
230
231
entry is associated with particular value and it's path. Difference between
231
232
opclasses is in the entry representation, comparison and usage for search
232
233
optimization.
@@ -247,7 +248,7 @@ same `#` sign in the path.
247
248
248
249
Major problem in the entries representation is its size. In the given example
249
250
key "a" is presented three times. In the large branchy documents with long
250
- keys size of naive entries representation becomes unreasonable. Both opclasses
251
+ keys size of naive entries representation becomes unreasonable. All opclasses
251
252
address this issue but in a slightly different way.
252
253
253
254
### ` jsonb_path_value_ops `
@@ -263,6 +264,21 @@ is hashed and it is higher part of entry we need to know the full path to
263
264
the value in order to use it for search. However, once path is specified
264
265
we can use both exact and range searches very efficiently.
265
266
267
+ ### ` jsonb_laxpath_value_ops `
268
+
269
+ ` jsonb_laxpath_value_ops ` differs from the ` jsonb_path_value_ops ` only in
270
+ that it skips array path items from the hashing. So, the jsonb document above
271
+ would be decomposed into following entries:
272
+
273
+ * ` (hash("a", "b"); "xyz") `
274
+ * ` (hash("a", "c"); true) `
275
+ * ` (hash("a"); 10) `
276
+ * ` (hash("d", "e"); 7) `
277
+ * ` (hash("d", "e"); false) `
278
+
279
+ Skipping array items greatly simplifies extraction of lax JSON path queries –
280
+ there is no need to extract all possible unwrapped paths (see example for
281
+ ` gin_debug_jsonpath_path_value() ` below).
266
282
267
283
### ` jsonb_value_path_ops `
268
284
@@ -287,8 +303,15 @@ Unfortunately, opclasses aren't allowed to do any custom output to the
287
303
EXPLAIN. That's why JsQuery provides following functions which allows to see
288
304
how particular opclass optimizes given query.
289
305
290
- * gin\_ debug\_ query\_ path\_ value(jsquery) – for jsonb\_ path\_ value\_ ops
291
- * gin\_ debug\_ query\_ value\_ path(jsquery) – for jsonb\_ value\_ path\_ ops
306
+ * ` jsonb_path_value_ops ` :
307
+ - ` gin_debug_query_path_value(jsquery) `
308
+ - ` gin_debug_jsonpath_path_value(jsonpath) `
309
+ * ` jsonb_laxpath_value_ops ` :
310
+ - ` gin_debug_query_laxpath_value(jsquery) `
311
+ - ` gin_debug_jsonpath_laxpath_value(jsonpath) `
312
+ * ` jsonb_value_path_ops ` :
313
+ - ` gin_debug_query_value_path(jsquery) `
314
+ - ` gin_debug_jsonpath_value_path(jsonpath) `
292
315
293
316
Result of these functions is a textual representation of query tree which
294
317
leafs are GIN search entries. Following examples show different results of
@@ -308,6 +331,31 @@ query optimization by different opclasses.
308
331
*.y = 1 , entry 1 +
309
332
y = 2 , entry 2 +
310
333
334
+ Examples for nearly equivalent JSON path query:
335
+
336
+ # SELECT gin_debug_jsonpath_value_path('$.x == 1 && ($.**.y == 1 || $.y == 2)');
337
+ gin_debug_jsonpath_value_path
338
+ -------------------------------
339
+ AND +
340
+ OR +
341
+ *.y = 1 , entry 0 +
342
+ y = 2 , entry 1 +
343
+ x = 1 , entry 2 +
344
+
345
+ # SELECT gin_debug_jsonpath_path_value('$.x == 1 && ($.**.y == 1 || $.y == 2)');
346
+ gin_debug_jsonpath_path_value
347
+ -------------------------------
348
+ OR +
349
+ #.x = 1 , entry 0 +
350
+ #.x.# = 1 , entry 1 +
351
+ x = 1 , entry 2 +
352
+ x.# = 1 , entry 3 +
353
+
354
+ # SELECT gin_debug_jsonpath_laxpath_value('$.x == 1 && ($.**.y == 1 || $.y == 2)');
355
+ gin_debug_jsonpath_laxpath_value
356
+ ----------------------------------
357
+ x = 1 , entry 0 +
358
+
311
359
Unfortunately, jsonb have no statistics yet. That's why JsQuery optimizer has
312
360
to do imperative decision while selecting conditions to be evaluated using
313
361
index. This decision is made by assumption that some condition types are less
0 commit comments