Postgres Interrogation/filtrage JSONB avec des tableaux imbriqués

0

La question

Ci-dessous mon échantillon

Je souhaite que les clients qui répondent à toutes les conditions ci-dessous

  1. Dans un pays "xyz", constituée entre 2019 et 2021.
  2. Doit avoir au moins un compte avec de l'équilibre entre 10000 et 13000 et de la direction générale est "abc" et la date de la transaction entre 20200110 et 20210625. Il est formaté et stocké sous forme de nombre
  3. Devrait avoir au moins une adresse dans l'état "état1" et des codes pin entre 625001 et 625015

Ci-dessous est la structure de la table

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

Il peut y avoir des millions de lignes dans la table. J'ai créé GIN index de type jsonb_ops sur le customer_details colonne comme nous, également, de vérifier l'existence des conditions et de la gamme de comparaison

Ci-dessous est un échantillon de données dans le customer_data JSONB colonne

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

Maintenant la requête que j'ai écrit ci-dessus est

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)

Pour gérer le scénario ci-dessus est la meilleure façon de l'écrire. Est-il possible de combiner tous les 3 critères (client/compte/adresse) dans une expression? La table aura des millions de lignes. Je suis de l'avis de l'avoir comme une expression et de frapper la DB offrira les meilleures performances. Est-il possible de combiner ces 3 conditions comme une expression

1

La meilleure réponse

0

Votre requête ne me donne pas l'erreur de vous rapport. Plutôt, il s'exécute, mais ne donnera le "mauvais" résultats par rapport à ce que vous voulez. Il y a plusieurs erreurs qui ne sont pas des erreurs de syntaxe, mais juste de donner de mauvais résultats.

Votre première jsonpath a l'air bien. C'est une expression Booléenne, et @@ vérifie si l'expression des rendements true.

Votre deuxième jsonpath a deux problèmes. Il donne une liste d'objets qui correspondent à vos conditions. Mais les objets ne sont pas des booléens, de sorte @@ seront malheureux et retour SQL NULL, qui est traité de la même que les faux ici. Au lieu de cela, vous avez besoin de tester si la liste est vide. C'est ce que @? n', afin de l'utiliser à la place de @@. Aussi, vos dates sont stockées en tant que 8 chiffres entiers, mais vous êtes en les comparant à 8 chaînes de caractères. Dans jsonpath, par exemple de type croisé des comparaisons de rendement JSON nulle, ce qui est le même traitement que les faux ici. Il faut donc modifier le stockage de chaînes, ou de modifier les littéraux ils sont comparés à en nombres entiers.

Votre troisième jsonpath a aussi le @@ problème. Et il a l'inverse du type de problème, vous avez la pin_code stockés sous forme de chaînes, mais vous êtes les tester contre des entiers. Enfin, vous avez de 'pin_code' mal orthographié dans un accident.

2021-11-24 20:58:29

Grâce Janes. J'ai corrigé le code et les données dans le post original. En raison de la nature confidentielle de nature, j'ai eu de post cuit données et a fait erreur en que. Je ne suis pas en mesure de reproduire l'erreur de scénario. Est-il meilleure approche pour la requête donnée ci-dessus avec 3 conditions de la clause where. Ma pensée est que si je suis capable d'en faire une seule condition au lieu de 3, il sera mieux. Toute orientation sera d'une grande aide pour moi. Merci
Balaji Govindan

Dans d'autres langues

Cette page est dans d'autres langues

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