Postgres Żąda/filtruje JSONB z zagnieżdżonych tablic

0

Pytanie

Oto moje wymagania do wzoru

Potrzebne mi są klienci, którzy spełniają wszystkie następujące warunki

  1. W kraju "xyz", zarejestrowanym w okresie od 2019 na 2021 rok.
  2. Musi być przynajmniej jeden rachunek z saldem od 10 000 do 13000, a oddział - "abc" i datę transakcji między 20200110 i 20210625. On sformatowany i jest przechowywany w postaci pokoje
  3. Musi mieć co najmniej jeden adres w stanie "state1" i kody PIN między 625001 i 625015

Poniżej znajduje się struktura tabeli

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

W tabeli mogą być miliony wierszy. Założyłem indeks GIN typu jsonb_ops w kolumnie customer_details, tak jak będziemy również sprawdzać warunki istnienia i porównywanie zakresów

Poniżej przedstawiono przykład danych w kolumnie JSONB customer_data

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
                }
            ]
        }
    }

Teraz pytanie, który napisałem powyżej, to

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)

Aby poradzić sobie z opisanym powyżej scenariuszem, to najlepszy sposób napisać. Czy można połączyć wszystkie 3 kryteria (klient/konto/adres) w jedno wyrażenie? W tabeli będą miliony wierszy. Jestem zdania, że to jedno wyrażenie, i dostanie się do bazy danych daje najlepszą wydajność. Czy można połączyć te 3 warunki w jedno wyrażenie

1

Najlepsza odpowiedź

0

Zapytanie nie wyświetla mi się błąd, o którym zgłaszasz. Raczej to działa, ale daje "złe" wyniki w porównaniu z tym, co chcesz. Jest w nim kilka błędów, które nie są синтаксическими błędami, a po prostu dają błędne wyniki.

Twój pierwszy jsonpath wygląda ok. To wyrażenie logiczne, i @@ sprawdzić, czy daje to wyrażenie true.

U twojego drugiego jsonpath są dwa problemy. To daje listę obiektów, które spełniają twoje kryteria. Ale obiekty nie są logiczne, więc @@ będzie niezadowolony i zwróci SQL NULL, który jest tutaj traktowana tak samo, jak false. Zamiast tego należy sprawdzić, pusty czy ta lista. Oto, co @? robi, więc wykorzystaj to zamiast @@. Ponadto, daty są zapisane w postaci 8-cyfrowych liczb całkowitych, ale ty porównujesz ich z 8-ciągami znaków. W jsonpath takie porównania między typami prowadzą do zera JSON, że jest tu traktowana tak samo, jak i fałsz. Dlatego trzeba albo zmienić magazyn na polecenia, albo zmienić literały, które są porównywane, na całe numery.

Trzeci jsonpath ma również @@ problem. I to ma odwrotny problem z typem, masz pin-kod, zapisany w postaci wierszy, ale sprawdzasz ich na całych liczbach. W końcu masz "kod pin", napisany z błędem w jednym przypadku.

2021-11-24 20:58:29

Dziękuję, Джейнс. Poprawiłem kod i dane w oryginalnej wiadomości. Ze względu na poufny charakter musiałem opublikować przygotowane dane i popełnił błąd w tym. Nie mogę odtworzyć scenariusz błędy. Czy któreś najlepszy podejście dla zapytania powyższego, z 3 warunków w klauzuli where. Myślę, że jeśli uda mi się zrobić to jak jeden warunek zamiast 3, to będzie lepiej. Wszelkie wskazówki będą mi bardzo pomocne. Dziękuję
Balaji Govindan

W innych językach

Ta strona jest w innych językach

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