2016-07-13 8 views
0

Ich versuche, Zeilen in meiner Postgresql-Datenbank zu finden, wo eine JSON-Spalte einen bestimmten Text enthält.Postgresql: Suche Zeile über Text in JSON Array von Objekten

Reihe Schema:

id | name   | subitems 
----------------------------------------------------------------- 
1 | "item 1"  | [{name: 'Subitem A'}, {name: 'Subitem B'}] 
2 | "item 2"  | [{name: 'Subitem C'}, {name: 'Subitem D'}] 

Mein wollte Abfrage führen 'Unterpunkt B'

id | name   | subitems 
----------------------------------------------------------------- 
1 | "item 1"  | [{name: 'Subitem A'}, {name: 'Subitem B'}] 

ich zum ersten subitem wie folgt suchen: I

WHERE lower(subitems->0->>\'name\') LIKE '%subitem a%' 

Aber offensichtlich finde keinen anderen Unterpunkt als den ersten.

kann ich alle Namen meiner Subitems erhalten:

SELECT lower(json_array_elements(subitems)->>'name') FROM ... 

Aber es gibt mir zwei Reihen mit den Namen:

lower 
---------------------------------------------------------------- 
"subitem a" 
"subitem b" 

Was ich brauche eigentlich 1 Zeile das Element enthält, ist.

Kann mir jemand sagen, wie man das macht?

+0

Was Sie suchen ist ein wenig unklar - können Sie uns einige Beispieldaten und auch ein Beispiel für die gewünschte Ausgabe geben? – jmelesky

+0

Danke für deine Antwort, ich habe meine Frage aktualisiert – Jesse

Antwort

1

Sie sind fast da. Ihre Frage:

SELECT lower(json_array_elements(subitems)->>'name') FROM foo; 

Das bekommt Sie, was Sie filtern möchten. Wenn Sie, dass in einer Unterabfrage plop, erhalten Sie die Ergebnisse, die Sie suchen:

# SELECT * 
    FROM foo f1 
    WHERE 'subitem a' IN 
     (SELECT lower(json_array_elements(subitems)->>'name') 
     FROM foo f2 WHERE f1.id = f2.id 
    ); 
id | name |     subitems      
----+--------+------------------------------------------------ 
    1 | item 1 | [{"name": "Subitem A"}, {"name": "Subitem B"}] 
(1 row) 

Edited

Gut schreiben, Stil Anpassung zu unterstützen, werden Sie eine gehen müssen etwas tiefer, indem Sie eine Unterabfrage in Ihre Unterabfrage einfügen. Da das ein bisschen schwer zu lesen ist, wechsle ich auf common table expressions.

WITH all_subitems AS (
    SELECT id, json_array_elements(subitems)->>'name' AS subitem 
    FROM foo), 
matching_items AS (
    SELECT id 
    FROM all_subitems 
    WHERE 
     lower(subitem) LIKE '%subitem a%') 
SELECT * 
    FROM foo 
    WHERE 
    id IN (SELECT id from matching_items); 

Das sollte Sie bekommen, was Sie brauchen. Beachten Sie, dass ich den Anruf an lower herauf ein Niveau verschoben habe, also ist es neben dem LIKE. Das bedeutet, dass die Filterbedingung an einer Stelle ist, sodass Sie einfacher zu einer Übereinstimmung mit einem regulären Ausdruck oder was auch immer wechseln können.

+0

Vielen Dank, funktioniert wie ein Charme, solange die Saiten genau übereinstimmen! Weißt du auch, wie man die LIKE '% query%' Syntax damit arbeiten lässt? – Jesse

+0

Bearbeitete Antwort, um das hinzuzufügen. – jmelesky

+0

Perfekt, das funktioniert. Nochmals vielen Dank, dass du dir die Zeit genommen hast und mir geholfen hast! Ich habe ein wenig Angst vor der Leistung, da die Datenbank, für die ich das benutze, ziemlich groß wird. Weißt du etwas darüber? – Jesse