PostgreSQL jsonb dizisinden belirli bir nesneyi nasıl alabilirim?


16

Kabaca şöyle görünüyor bir json dizisi tutan 'kullanıcı' adlı bir alan var:

"user":

[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]

Şimdi şöyle bir sorgu istiyorum:

select count from tablename where id = "1"

countPostgreSQL 9.4 json nesneleri bir dizi belirli bir alan elde edemiyorum .

Yanıtlar:


17

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 usryerine 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, jsonbsü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 WHEREyan 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'.


2
Nereden obj(value)geliyor? Üzerinde mi LATERAL JOIN, jsonb_array_elementsyoksa başka bir yerde mi?
Tyler DeWitt

Biçimlendirmenin sıkışmış olduğu anlaşılıyor. Bunu doğru mu okuyorum JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)ve bu obj(value)bir tablo ve sütun takma adı mı? Bu örnekte, objtablo takma adı varsa , takma ad nedir? Set geri döndü jsonb_array_elementsmü?
Tyler DeWitt

1
Evet ve evet. şifreli yorum kaldırdım.
Erwin Brandstetter

Sütun takma adını kullanmaya gerek var mı? Benim testlerde, JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'(kullanma seçme deyimi güncelleştirmek zamanlar aynı etkiye sahip valueyerine val). jsonb_array_elements(t.usr)Yalnızca bir sütunu olan bir tablo döndüren görünür . Postgres akıllı olmak ve fark edilir obj ->>aynıdır obj.val ->>?
Tyler DeWitt

Postgres yalnızca tek bir sütunda tablo ve sütun adı olarak belirli bir takma ad kullanır . Birden fazla sütun döndüren birçok set dönen işlevleri olduğu gibi ben sadece açıklık duyuyorum.
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.