sql >> Database >  >> RDS >> PostgreSQL

LIKE-query op elementen van platte jsonb-array

SELECT *
FROM   posts p
WHERE  EXISTS (
   SELECT FROM jsonb_array_elements_text(p.tags) tag
   WHERE  tag LIKE '%TAG%'
   );

Gerelateerd, met uitleg:

  • Zoek in een JSON-array naar een object dat een waarde bevat die overeenkomt met een patroon

Of eenvoudiger met de @? operator sinds Postgres 12 SQL/JSON heeft geïmplementeerd:

SELECT *
--     optional to show the matching item:
--   , jsonb_path_query_first(tags, '$[*] ? (@ like_regex "^ tag" flag "i")')
FROM   posts
WHERE  tags @? '$[*] ? (@ like_regex "TAG")';

De operator @? is slechts een wrapper rond de functie jsonb_path_exists() . Dit is dus equivalent:

...
WHERE  jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');

Geen van beide heeft indexondersteuning. (Mag worden toegevoegd voor de @? operator later, maar nog niet in pg 13). Dus die query's zijn traag voor grote tabellen. Een genormaliseerd ontwerp, zoals Laurenz al suggereerde, zou superieur zijn - met een trigram-index:

  • PostgreSQL LIKE prestatievariaties voor query's

Voor slechts voorvoegselovereenkomst (LIKE 'TAG%' , geen leidende wildcard), zou u het kunnen laten werken met een volledige tekstindex :

CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));

En een overeenkomende zoekopdracht:

SELECT *
FROM   posts p
WHERE  to_tsvector('simple', tags)  @@ 'TAG:*'::tsquery

Of gebruik de english woordenboek in plaats van simple (of wat dan ook bij je past) als je wilt stammen voor natuurlijke Engelse taal.

to_tsvector(json(b)) vereist Postgres 10 of later.

Gerelateerd:

  • Gedeeltelijke overeenkomst ophalen uit GIN-geïndexeerde TSVECTOR-kolom
  • Patroon komt overeen met LIKE, VERGELIJKBAAR MET of reguliere expressies in PostgreSQL



  1. Voeg een enkele kolom in een query samen met veel kolommen

  2. Altijd versleutelde prestaties:een vervolg

  3. Hoe de databasenauwkeurigheid te verbeteren

  4. Room - Gebruik van externe SQLites en interne DB