Solr, ElasticSearch, Sphinx, ... alles überbewertet ;)
Das erledigt PostgreSQL quasi nebenbei. Inklusive einem riesen Vorteil: Der Such-Index ist nie out-of-sync mit dem primären Datenspeicher.
"A document is the unit of searching in a full text search system; for example, a magazine article or email message."
Ein Dokument kann aus mehreren Attributen (z.B. Titel, Einleitung, Haupttext) bestehen und auch auf mehrere Tabellen verteilt sein.
- Wörter, die interessant sind, extrahieren
- Mapping von Wort auf Dokumenten-IDs speichern
- Wörter schnell auffindbar machen
This is where the Magic happens:
SELECT to_tsvector('This is a very meaningful example');
SELECT to_tsvector('Dies ist ein toller Beispieltext');
SELECT to_tsvector('german', 'Dies ist ein toller Beispieltext');
Abbildung von normalisierten Wortstämmen auf die Position in der ursprünglichen Zeichenkette.
Aber wie wird nach normalisierten Wörtern gesucht?
SELECT to_tsvector('This is a very meaningful example') @@ to_tsquery('meaningful');
SELECT to_tsvector('This is a very meaningful example') @@ to_tsquery('meaningful & example');
SELECT to_tsvector('This is a very meaningful example') @@ to_tsquery('mea:*');
SELECT id FROM documents WHERE to_tsvector(title) @@ to_tsquery('foobar');
Funktioniert für andere Sprachen analog. Manchmal will man keine Normalisierung und keine Stop-Wörter: 'simple' als Sprache wählen.
Die to_tsquery Funktion unterstützt auch diverse Operatoren wie !, &, |, Klammerung und Präfix-Suche.
Postgres bringt verschiedene Indizes für die to_tsvector Daten mit, darunter auch den klassischen invertierten Index. Die Nutzung ist denkbar einfach:
CREATE INDEX ON foos USING gin(to_tsvector('german', title));
Noch einfacher:
# Gemfile
gem 'textacular'
# Code
FooModel.basic_search(title: 'Beispiel')