So implementieren Sie die Volltextsuche für komplexe geschachtelte JSONB in ​​PostgreSQL

8

Ich habe ziemlich komplexe JSONB in ​​einer jsonb Spalte gespeichert.

DB-Tabelle sieht wie folgt aus:

%Vor%

Daten, die wir in der Spalte doc speichern, sind komplexe verschachtelte JSONB data:

%Vor%

So sieht meine JSONB Struktur wie folgt aus:

%Vor%

Wir müssen die Volltextsuche durch einige Werte in jedem Typ von Eintrag implementieren:

%Vor%

Die SQL-Abfrage sollte nur in diesen Feldwerten eine Volltextsuche ausführen.

Ich denke, wir müssen GIN indexes und so etwas wie tsvector verwenden, haben aber nicht genug Postgresql Hintergrund.

Also, meine Frage ist es möglich solche verschachtelten JSONB Strukturen zu indizieren und dann abzufragen?

    
rusllonrails 14.08.2017, 18:39
quelle

1 Antwort

4

Fügen wir eine neue Spalte von tsvector type hinzu:

%Vor%

Lasst uns jetzt einen Trigger erstellen, der Lexems sammelt, organisiert und in unseren Tsvector legt. Wir werden 4 Gruppen verwenden (A, B, C, D) - dies ist eine spezielle Tsvector-Funktion, die es Ihnen erlaubt, Lexems später bei der Suche zu unterscheiden (siehe Beispiele im Handbuch Ссылка ; leider unterstützt diese Funktion nur bis zu 4 Gruppen, da Entwickler nur 2 Bits dafür reserviert haben, aber wir haben Glück, wir brauchen nur 4 Gruppen):

%Vor%

^^ - Scroll es, dieses Snippet ist größer als es aussieht (vor allem von dir haben MacOS ohne Scrollbalken ...)

Lassen Sie uns nun den GIN-Index erstellen, um die Suchabfragen zu beschleunigen (macht Sinn, wenn Sie viele Zeilen haben - sagen wir, mehr als Hunderte oder Tausende):

%Vor%

Und jetzt fügen wir etwas ein, um es zu überprüfen:

%Vor%

Überprüfen Sie mit select * from sites; - Sie müssen sehen, dass tsvector Spalte mit einigen Daten gefüllt ist.

Nun wollen wir es abfragen:

%Vor%

- es muss unseren Rekord zurückgeben. In diesem Fall suchen wir nach 'sample' word und es ist uns egal, in welcher Gruppe es gefunden wird.

Ändern wir es und versuchen, nur in Gruppe A ("SITE (Identifikation, Titel, Adresse)" wie Sie es beschrieben haben) zu suchen:

%Vor%

- Dies muss nichts zurückgeben, weil das Wort 'sample' nur in Gruppe D sitzt ("AUDIT (sample_id)"). Tatsächlich:

%Vor%

- wird uns wieder unseren Rekord zurückgeben.

Beachten Sie, dass Sie to_tsquery(..) , nicht plainto_tsquery(..) verwenden müssen, um 4 Gruppen zu adressieren. Sie müssen also Ihre Eingabe selbst bereinigen (vermeiden Sie das Verwenden oder Entfernen von Sonderzeichen wie & und | , da sie in tsquery -Werten eine besondere Bedeutung haben).

Und die gute Nachricht ist, dass Sie verschiedene Gruppen in einer einzigen Abfrage kombinieren können:

%Vor%

Der andere Weg (zB wenn Sie mit mehr als 4 Gruppen arbeiten müssen) besteht aus mehreren tsvectors, die jeweils in einer separaten Spalte sitzen, sie mit einer einzelnen Abfrage erstellen, einen Index erstellen (Sie können einen einzelnen Index für mehrere erstellen) tsvector columns) und Query Adressierung separater Spalten. Es ist ähnlich dem, was ich oben erklärt habe, aber vielleicht weniger effizient.

Hoffe, das hilft.

    
Nick 22.08.2017 03:09
quelle