Proper Index for Querying Structures in Arrays in Postgres JSONB
To effectively index and query arrays of structured data stored in a Postgres JSONB field, consider the following steps:
1. Correct Array Access:
Use the correct syntax to access array elements in a JSONB context. For example:
e->0->>'event_slug'
2. Custom Operators for JSONB:
Utilize jsonpath operators for greater-than or less-than comparisons on JSONB fields. In Postgres 12 or later, use @?:
e->0->>'end_time' @> '2014-10-13'
Or, in older versions, use jsonb_path_ops:
CREATE INDEX events_gin_idx ON locations USING GIN (events jsonb_path_ops);
3. Basic Solution for Postgres 12 :
For equality checks, use the @? operator:
SELECT l.* FROM locations l WHERE l.events @? '$[*] ? (@.event_slug == "test_1")';
For OR-type filters, use the following syntax:
SELECT l.* FROM locations l WHERE l.events @? '$[*] ? (@.event_slug == "test_1") ? (@.start_time.datetime() < "2014-10-13".datetime() || @.end_time.datetime() < "2014-10-13".datetime())';
4. Basic Solution for Any Postgres Version:
For equality checks, use the @> operator:
SELECT * FROM locations WHERE events @> '[{"event_slug":"test_1"}]';
For greater-than-or-equal checks, use a subquery:
SELECT l.* FROM locations l JOIN jsonb_array_elements(l.events) e ON l.events @> '[{"event_slug":"test_1"}]' WHERE (e->>'end_time')::timestamp >= '2014-10-30 14:04:06'::timestamptz;
5. Advanced Solution Using Materialized View:
For optimal performance on complex queries, consider creating a materialized view that stores relevant data in normalized form:
CREATE MATERIALIZED VIEW loc_event AS SELECT l.location_id, e.event_slug, e.end_time FROM locations l, jsonb_populate_recordset(null::event_type, l.events) e;
6. Index and Query the Materialized View:
CREATE INDEX loc_event_idx ON loc_event (event_slug, end_time, location_id);
SELECT * FROM loc_event WHERE event_slug = 'test_1' AND end_time >= '2014-10-30 14:04:06 -0400'::timestamptz;
The above is the detailed content of How to Efficiently Index and Query JSONB Arrays in PostgreSQL?. For more information, please follow other related articles on the PHP Chinese website!