HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlpostgresqlModeratepending

PostgreSQL JSON/JSONB querying and indexing

Submitted by: @anonymous··
0
Viewed 0 times
jsonbgin indexcontainmentjsonb_setjson querypostgres json

Problem

Need to efficiently query, filter, and index JSONB columns in PostgreSQL.

Solution

JSONB operations and indexing:

-- Sample table
CREATE TABLE events (
  id SERIAL PRIMARY KEY,
  data JSONB NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- INSERT
INSERT INTO events (data) VALUES
  ('{"type": "click", "page": "/home", "user": {"id": 1, "name": "Alice"}}'),
  ('{"type": "view", "page": "/about", "tags": ["nav", "info"]}');

-- ACCESS OPERATORS
SELECT
  data->>'type' AS type,           -- text value (->>' for text)
  data->'user'->>'name' AS user,   -- nested access
  data#>>'{user,name}' AS user2,   -- path access (text)
  data->'tags'->0 AS first_tag,    -- array index (jsonb)
  data->'tags'->>0 AS first_tag_text -- array index (text)
FROM events;

-- FILTER
SELECT * FROM events WHERE data->>'type' = 'click';
SELECT * FROM events WHERE data->'user'->>'id' = '1';
SELECT * FROM events WHERE (data->>'count')::int > 5;

-- CONTAINMENT (@>)
SELECT * FROM events WHERE data @> '{"type": "click"}';
SELECT * FROM events WHERE data @> '{"user": {"id": 1}}';

-- EXISTENCE (?)
SELECT * FROM events WHERE data ? 'tags';       -- has key
SELECT * FROM events WHERE data ?| ARRAY['type','page']; -- has any
SELECT * FROM events WHERE data ?& ARRAY['type','page']; -- has all

-- ARRAY OPERATIONS
SELECT * FROM events WHERE data->'tags' ? 'nav';  -- array contains

-- INDEXING

-- GIN index for containment and existence operators
CREATE INDEX idx_events_data ON events USING GIN (data);
-- Supports: @>, ?, ?|, ?&

-- GIN with jsonb_path_ops (smaller, faster for @> only)
CREATE INDEX idx_events_data_path ON events
  USING GIN (data jsonb_path_ops);
-- Only supports @>, but 2-3x faster

-- B-tree index on specific JSON field
CREATE INDEX idx_events_type ON events ((data->>'type'));
-- For: WHERE data->>'type' = 'click'

-- JSONB_EACH: Expand to rows
SELECT key, value FROM events, jsonb_each(data) WHERE id = 1;

-- JSONB_ARRAY_ELEMENTS: Expand array
SELECT elem FROM events, jsonb_array_elements(data->'tags') AS elem;

-- UPDATE specific field
UPDATE events SET data = jsonb_set(data, '{user,name}', '"Bob"');

-- REMOVE key
UPDATE events SET data = data - 'temporary_field';

Why

JSONB combines schema flexibility with query performance. Proper indexing (GIN for containment, B-tree for specific fields) makes JSONB queries fast even on large tables.

Context

PostgreSQL with semi-structured data

Revisions (0)

No revisions yet.