Postgres jsonb'yi iç içe dizilerle sorgulama / filtreleme

0

Soru

Aşağıda benim örnek gereksinimi

Aşağıdaki koşulların tümünü karşılayan müşteriler istiyorum

  1. 2019 ile 2021 yılları arasında kurulan "xyz" ülkesinde.
  2. 10000 ile 13000 arasında bakiyesi olan en az bir hesaba sahip olmalı ve şube "abc" ve işlem tarihleri 20200110 ile 20210625 arasında olmalıdır. Numara olarak biçimlendirilir ve saklanır
  3. "State1" durumunda en az bir adrese ve 625001 ile 625015 arasındaki pın kodlarına sahip olmalıdır

Aşağıda tablo yapısı verilmiştir

        CREATE TABLE IF NOT EXISTS customer_search_ms.customer
        (
            customer_id integer,
            customer_details jsonb
        )
    

Tabloda milyonlarca satır olabilir. Varoluş koşullarını ve aralık karşılaştırmasını da kontrol edeceğimiz için customer_details sütununda jsonb_ops türünde CİN dizini oluşturdum

Aşağıda customer_data JSONB sütunundaki örnek veriler verilmiştir

customer_id : 1

    {
        "customer_data": {
            "name": "abc",
            "incorporated_year": 2020,
            "country":"xyz",
            "account_details": [
                {
                    "transaction_dates": [
                        20180125, 20190125, 20200125,20200525
                    ],
                    "account_id": 1016084,
                    "account_balance": 2000,
                    "account_branch": "xyz"
                },
                {
                    "transaction_dates": [
                        20180125, 20190125, 20200125
                    ],
                    "account_id": 1016087,
                    "account_balance": 12010,
                    "account_branch": "abc"
                }
            ],
            "address": [
                {
                    "address_id": 24739,
                    "door_no": 4686467,
                    "street_name":"street1",
                    "city": "city1",
                    "state": "state1",
                    "pin_code": 625001
                },
                {
                    "address_id": 24730,
                    "door_no": 4686442,
                    "street_name":"street2",
                    "city": "city1",
                    "state": "state1",
                    "pin_code": 625014
                }
            ]
        }
    }

Şimdi yukarıda yazdığım sorgu şu şekildedir

SELECT  c.customer_id,
        c.customer_details
FROM customer_search_ms.customer c
WHERE c.customer_details @@ CAST('$.customer_data.country ==  "xyz" && $.customer_data.incorporated_year >= 2019 && $.customer_data.incorporated_year <= 2021 ' AS JSONPATH)
AND c.customer_details @? CAST('$.customer_data.account_details[*] ? (@.account_balance >=  10000) ? (@.account_balance <=  13000) ?(@.account_branch ==  "abc") ? (@.transaction_dates >=  20200110) ? (@.transaction_dates <=  20210625)' AS JSONPATH)
AND c.customer_details @? CAST('$.customer_data.address[*] ? (@.state ==  "state1") ? (@.pin_code >=  625001) ? (@.pin_code <= 625015)  ' AS JSONPATH)

Yukarıdaki senaryoyu ele almak, yazmanın en iyi yoludur. Tüm 3 kriteri (müşteri/hesap/adres) tek bir ifadede birleştirmek mümkün mü? Tabloda milyonlarca satır olacaktır. Tek bir ifade olarak sahip olmanın ve dB'ye vurmanın en iyi performansı vereceğini düşünüyorum. Bu 3 koşulu tek bir ifade olarak birleştirmek mümkün mü

1

En iyi cevabı

0

Sorgunuz bana bildirdiğiniz hatayı vermiyor. Aksine, çalışır, ancak istediğinize kıyasla "yanlış" sonuçlar verir. Sözdizimi hataları olmayan, ancak yanlış sonuçlar veren birkaç hata vardır.

İlk jsonpath'iniz iyi görünüyor. Bu bir Boole ifadesidir ve @@ denetleyen bir ifade verir eğer true.

İkinci jsonpath'inizin iki sorunu var. Koşullarınıza uyan nesnelerin bir listesini verir. Ancak nesneler boolean değildir, bu yüzden @@ mutsuz olacak ve burada false ile aynı şekilde ele alınan SQL NULL değerini döndürecektir. Bunun yerine, bu listenin boş olup olmadığını test etmeniz gerekir. Bu nedir @? yapar, bu yüzden bunun yerine kullanın @@. Ayrıca, tarihleriniz 8 basamaklı tamsayılar olarak depolanır, ancak bunları 8 karakterli dizelerle karşılaştırırsınız. Jsonpath'de, bu tür çapraz tür karşılaştırmaları, burada false ile aynı şekilde ele alınan JSON null değerini verir. Yani ya dizeleri depolama değiştirmek için, ya da tamsayı göre onlar bu rakamları değiştirmek gerekir.

Üçüncü jsonpath'iniz de @@ sorun. Ve tür sorununun tersi var, dizeler olarak saklanan pin_code var, ancak bunları tamsayılara karşı test ediyorsunuz. Son olarak, bir olayda' pin_code ' yanlış yazılmıştır.

2021-11-24 20:58:29

Teşekkürler Janes. Orijinal gönderideki kodu ve verileri düzelttim. Gizli doğası gereği pişmiş verileri göndermek zorunda kaldım ve bu konuda hata yaptım. Hata senaryosunu yeniden oluşturamıyorum. Where yan tümcesinde 3 koşulla yukarıda verilen sorgu için daha iyi bir yaklaşım var mı? Benim düşüncem, bunu 3 yerine tek bir koşul olarak yapabiliyorsam daha iyi olacağıdır. Herhangi bir hidayet bana çok yardımcı olacaktır. Teşekkürler
Balaji Govindan

Diğer dillerde

Bu sayfa diğer dillerde

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................