JSONPath ile JSONB Sorgulama
Dizin desteğiyle iç içe değerleri filtrelemek ve çıkarmak için SQL/JSON yol ifadelerini uygulayın.
JSONPath ile JSONB Sorgulama, CoddyKit'te ücretsiz bir PostgreSQL Performance & Query Optimization dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, PostgreSQL Performance & Query Optimization öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. PostgreSQL Performance & Query Optimization kursu toplamda 4 dersten oluşur.
Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.
Why JSONPath for JSONB
PostgreSQL stores semi-structured data in the jsonb type. Pulling nested values with the classic -> and ->> operators works, but gets clumsy fast for deep paths, arrays, and conditional filters.
The SQL/JSON path language (added in PostgreSQL 12) gives you a compact, expressive way to navigate and filter JSON. It powers two key functions:
jsonb_path_query/jsonb_path_query_array— extract matching valuesjsonb_path_existsand the@?/@@operators — test predicates
Best of all, those operators can be accelerated by a GIN index, which is exactly what this lesson is about.
A sample JSONB document
Imagine an orders table with a data jsonb column. A single row might hold a document like the one below.
Throughout this lesson we will navigate into customer, iterate over the items array, and filter by numeric and string conditions.
SELECT '{
"id": 1042,
"status": "shipped",
"customer": { "name": "Mara", "tier": "gold" },
"items": [
{ "sku": "A-1", "qty": 2, "price": 19.90 },
{ "sku": "B-7", "qty": 1, "price": 4.50 }
]
}'::jsonb AS data;The $ root and dot navigation
Every JSONPath expression starts at $, the context item (the whole document). From there you use dot notation for object keys.
$.status→ the value of thestatuskey$.customer.name→ a nested value
jsonb_path_query returns each match as a jsonb value. Note that string results keep their quotes; use jsonb_path_query_first(...) #>> '{}' or a cast if you need plain text.
SELECT jsonb_path_query(
'{"status":"shipped","customer":{"name":"Mara"}}'::jsonb,
'$.customer.name'
) AS name;Walking into arrays
To reach array elements, use square brackets. Indexes are zero-based.
$.items[0]→ the first element$.items[*]→ the wildcard, every element$.items[*].sku→ theskuof every element
When a path matches many values, jsonb_path_query returns one row per match. Wrap the call in jsonb_path_query_array to collect them into a single JSON array instead.
SELECT jsonb_path_query_array(
'{"items":[{"sku":"A-1"},{"sku":"B-7"}]}'::jsonb,
'$.items[*].sku'
) AS skus;Filter expressions with ? ( )
The real power of JSONPath is the filter expression: ? ( predicate ). Inside a filter, @ refers to the current item being tested.
To get every item whose quantity is at least 2:
$.items[*] ? (@.qty >= 2)
The filter keeps only the array elements that satisfy the predicate. You can then keep navigating, e.g. $.items[*] ? (@.qty >= 2).sku to return just their SKUs.
SELECT jsonb_path_query(
'{"items":[{"sku":"A-1","qty":2},{"sku":"B-7","qty":1}]}'::jsonb,
'$.items[*] ? (@.qty >= 2).sku'
) AS heavy_skus;Combining predicates and operators
Filter predicates support the usual comparison operators (==, !=, <, <=, >, >=) and the boolean connectives && and ||.
Note the equality operator inside JSONPath is ==, not the SQL single =. Strings are written with double quotes.
$.items[*] ? (@.qty > 1 && @.price < 10)$ ? (@.customer.tier == "gold")
Parentheses let you group complex logic just like in SQL.
SELECT jsonb_path_query(
'{"items":[{"sku":"A-1","qty":2,"price":19.9},{"sku":"C-9","qty":3,"price":4.5}]}'::jsonb,
'$.items[*] ? (@.qty > 1 && @.price < 10)'
) AS cheap_bulk;Testing existence: @? and @@
For filtering rows in a WHERE clause you usually want a boolean, not the matched value. Two operators do this:
jsonb @? jsonpath→ true if the path returns any itemjsonb @@ jsonpath→ evaluates a path that itself yields a boolean predicate
Rule of thumb: with @? the filter lives inside the path ($.items[*] ? (@.qty > 5)); with @@ the path is the predicate ($.customer.tier == "gold"). Both are GIN-indexable.
SELECT
data @? '$.items[*] ? (@.qty > 5)' AS has_bulk_item,
data @@ '$.customer.tier == "gold"' AS is_gold
FROM (SELECT '{"customer":{"tier":"gold"},"items":[{"qty":2}]}'::jsonb AS data) t;Filtering rows in a real query
Here is the pattern you will write most often: select rows whose JSONB document satisfies a path predicate. Because @? is indexable, this can run without a sequential scan once the right index exists.
This query finds shipped orders that contain at least one item costing more than 100.
SELECT id, data->>'status' AS status
FROM orders
WHERE data @? '$.items[*] ? (@.price > 100)'
AND data @@ '$.status == "shipped"';Indexing with the default jsonb_ops GIN
A plain GIN index on the column uses the jsonb_ops operator class. It indexes every key and every value, supporting containment (@>), key-existence (?), and the JSONPath operators @? / @@.
It is flexible but larger, because each value gets its own index entry.
CREATE INDEX idx_orders_data ON orders USING gin (data);
-- Now this predicate can use the index:
EXPLAIN ANALYZE
SELECT id FROM orders
WHERE data @? '$.items[*] ? (@.price > 100)';Smaller and faster: jsonb_path_ops
If you only need containment and JSONPath search (not the standalone key-existence ? operator), the jsonb_path_ops operator class is the better choice.
It hashes whole key+value paths into single index entries, so the index is smaller and usually faster for @>, @?, and @@ lookups. The trade-off: it does not support the bare ?, ?|, ?& key-existence operators.
CREATE INDEX idx_orders_data_path
ON orders USING gin (data jsonb_path_ops);
-- Great for: data @? '$.items[*] ? (@.price > 100)'
-- Not for: data ? 'status'Expression indexes for hot scalar paths
GIN is ideal for flexible containment search. But if you constantly filter on one scalar value — say status — a targeted B-tree expression index on the extracted text is smaller and supports ordering and range scans.
- Extract once with
(data->>'status')and index that expression. - The query
WHEREclause must use the same expression for the planner to use it.
Use GIN for "does the document contain X?" and B-tree expression indexes for "equals / ordered-by this one field".
CREATE INDEX idx_orders_status
ON orders ((data->>'status'));
SELECT id FROM orders
WHERE data->>'status' = 'shipped'
ORDER BY (data->>'status');Quick Check
You need a GIN index that accelerates JSONPath predicates like data @? '$.items[*] ? (@.price > 100)' and you want the smallest, fastest index. You do not need the bare key-existence operator ?. Which index should you create?
Recap
You learned how to query JSONB with the SQL/JSON path language and how to make it fast:
- Navigate from
$using dots for keys and[*]for arrays. - Filter with
? (@ ... ), using==for equality and&&/||to combine predicates. - Extract matches with
jsonb_path_query/jsonb_path_query_array. - Test in WHERE clauses with
@?(filter inside the path) and@@(path is the predicate). - Index with GIN: default
jsonb_opsfor full flexibility, orjsonb_path_opsfor smaller, faster containment and path search; reach for a B-tree expression index when you repeatedly filter or sort by a single scalar field.
Pick the index that matches your access pattern, and always confirm with EXPLAIN ANALYZE.
Sıkça Sorulan Sorular
“JSONPath ile JSONB Sorgulama” dersi ücretsiz mi?
Evet — “JSONPath ile JSONB Sorgulama” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve PostgreSQL Performance & Query Optimization kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. PostgreSQL Performance & Query Optimization kursu toplamda 4 dersten oluşur.
“JSONPath ile JSONB Sorgulama” dersinde ne öğreneceğim?
Dizin desteğiyle iç içe değerleri filtrelemek ve çıkarmak için SQL/JSON yol ifadelerini uygulayın. PostgreSQL Performance & Query Optimization ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
PostgreSQL Performance & Query Optimization öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te PostgreSQL Performance & Query Optimization, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“JSONPath ile JSONB Sorgulama” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu PostgreSQL Performance & Query Optimization dersinde kod yazıp çalıştırabilir miyim?
Evet. Her PostgreSQL Performance & Query Optimization dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- JSONB İşleçleri ve İçerme Sorguları
- JSONB'de GIN ve İfade Dizinlerini Karşılaştırma
- JSONPath ile JSONB Sorgulama
- JSONB'den Ne Zaman Normalleştirme Yapılmalı