Değerlerinizi normalleştirilmiş bir şemada saklamak çok daha verimli olacaktır. Bununla birlikte, mevcut kurulumunuzla çalışmasını sağlayabilirsiniz.
Varsayımlar
Bu tablo tanımı varsayıldığında:
CREATE TABLE tbl (tbl_id int, usr jsonb);
"kullanıcı" ayrılmış bir kelimedir ve sütun adı olarak çift tırnak kullanılmasını gerektirir. Bunu yapma. Bunun usr
yerine kullanıyorum.
Sorgu
Sorgu, (şimdi silinmiş) yorumların göründüğü kadar önemsiz değil:
SELECT t.tbl_id, obj.val->>'count' AS count
FROM tbl t
JOIN LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE t.usr @> '[{"_id":"1"}]';
Orada 3 temel adım :
1. Nitelikli satırları ucuza belirleyin
WHERE t.usr @> '[{"_id":"1"}]'
JSON dizisinde eşleşen nesneyle satırları tanımlar. İfade, jsonb
sütunda genel bir GIN dizini veya daha özel işleç sınıfına sahip bir GIN dizini kullanabilir jsonb_path_ops
:
CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);
Eklenen WHERE
yan tümce mantıksal olarak fazladır , ancak dizini kullanmak gerekir. Join yan tümcesindeki ifade aynı koşulu uygular, ancak şu ana kadar her satırda diziyi taksim etmeden sonra . Dizin desteğiyle, Postgres yalnızca başlangıç için niteleyici nesne içeren satırları işler. Pek önemi küçük tablolarla, bir yapar mı büyük büyük tablolar ve sadece birkaç eleme satırlarla farkı.
İlişkili:
2. Dizideki eşleşen nesneleri tanımlayın
İle dürüst olmayan jsonb_array_elements()
. ( unnest()
yalnızca Postgres dizi türleri için iyidir.) Yalnızca nesneleri gerçekten eşleştirmekle ilgilendiğimiz için birleştirme koşulunu hemen filtreleyin.
İlişkili:
3. İç içe anahtar için değeri ayıklayın 'count'
Eleme nesneleri sadece, ekstre edildikten sonra: obj.val->>'count'
.
obj(value)
geliyor? Üzerinde miLATERAL JOIN
,jsonb_array_elements
yoksa başka bir yerde mi?