Volltextsuche mit FTS - Index erstellen und darin suchen

Die Volltextsuche ist derweil nicht mehr nur den großen Suchdiensten vorbehalten. Sich selbst eine kleine Suchmaschine zu basteln ist heute nicht mehr schwer. Wie das geht, sieht man hier.

Grundlage ist eine SQLite-Installation, die das Modul “FTS” an Board hat. Mittels dieser Erweiterung ist die Volltestsuche ein Kinderspiel

Zuerst muss die SQLite-Konsole geöffnet und damit gleich eine Datenbank erstellt werden. Existiert eine Datenbank, wird diese natürlich nicht nicht angelegt.

sqlite3 fts.db

Erstellen einer virtuellen Tabelle:

--SQL
CREATE VIRTUAL TABLE article_fts USING fts4();

Die Tabelle ist nun nicht nur leer, sondern hat nicht mal eine Spalte. Hat sie wohl! Denn, wird kein Name angegeben, wird automatisch eine Spalte “content” angegeben.

Wenn man es nun gern etwas strukturierter hätte, kann man auch einfach eine neue Tabelle anlegen. Es wäre doch ganz charmant, einfach nach einem Title und nicht gleich quer über “alles” suchen zu müssen.

--SQL
DROP TABLE article_fts;
CREATE VIRTUAL TABLE article_fts USING fts4(title, text, tag);

Bevor es weiter geht, muss erwähnt werden, dass nicht nur “content” im Hintergrund angelegt wird. Der Eintrag “docid”, die ID des jeweiligen Dokuments also, ist für die Idee der Volltextsuche so wichtig, dass es diesen Eintrag immer gibt. Schließlich will man ja auch wissen, wohin der gefundene Text gehört; “docid” ist also eine Referenz auf das Originaldokument.

Nun lässt sich die neue, virtuelle Tabelle mit Inhalt füllen.

--SQL
INSERT INTO article_fts (docid, title, text, tag) VALUES(1, 'Test', '...aber so ein richtiger', 'test richtig fts');
INSERT INTO article_fts (docid, title, text, tag) VALUES(2, 'Testament', '...findet sich nicht so leicht wieder', 'testament weg');
INSERT INTO article_fts (docid, title, text, tag) VALUES(3, 'T E S T', '...wird so niemals gefunden', 'fts aber mehr nicht');

Daten anzeigen:

--SQL
SELECT * FROM article_fts;

Test|…aber so ein richtiger|test richtig fts Testament|…findet sich nicht so leicht wieder|testament weg T E S T|…wird so niemals gefunden|fts aber mehr nicht

Die Daten sind da; nun wird gesucht!

--SQL
SELECT * FROM article_fts WHERE title MATCH 'test';

Test|…aber so ein richtiger|test richtig fts

Soweit wäre man nun auch noch mit einem einfachen LIKE gekommen; nun wird es jedoch interessanter.

--SQL
SELECT * FROM article_fts WHERE title MATCH 'test*';

Test|…aber so ein richtiger|test richtig fts Testament|…findet sich nicht so leicht wieder|testament weg

Okay, ganz nett, aber wie kann über “alles” gesucht werden?

--SQL
SELECT * FROM article_fts WHERE article_fts MATCH 'fts';

Test|…aber so ein richtiger|test richtig fts T E S T|…wird so niemals gefunden|fts aber mehr nicht

Nun wird nach “fts” gesucht und dass auch gleich über alle Spalten. Das wird erreicht, indem man, statt des Spaltennamens, den Bezeichner der Tabelle angibt.

Wer schon mal eine Suchmaschine benutzt hat, weiß, dass man nicht nur nach einem Begriff sucht; für gewöhnlich. ;-) Kein Problem:

--SQL
SELECT * FROM article_fts WHERE article_fts MATCH 'test fts';

Test|…aber so ein richtiger|test richtig fts

Zwischen den beiden Begriffen “test” und “fts” steht (unsichtbar) ein AND, was bedeutet, dass einzig der Eintrag, der eben diese beiden Begriffe enthält, angezeigt wird.

Es geht natürlich auch so:

--SQL
SELECT * FROM article_fts WHERE article_fts MATCH 'test* OR fts';

Test|…aber so ein richtiger|test richtig fts T E S T|…wird so niemals gefunden|fts aber mehr nicht

Das Spiel lässt sich nun natürlich beliebig erweitern:

--SQL
SELECT * FROM article_fts WHERE article_fts MATCH 'test* -fts';

Testament|…findet sich nicht so leicht wieder|testament weg

Die einfache Volltextsuche ist somit in Windeseile umgesetzt!