A
Hallo!
Im Manual steht einiges dazu: http://dev.mysql.com/doc/mysql/en/fulltext-search.html
Folgende Sachen sind bei der Volltextsuche in MySQL zu beachten:
.) Es gibt eine minimale Wortlänge, die in der Konfiguration standardmäßig leider auf 4 Zeichen eingestellt ist. Wörter, die in der Suchanfrage kleiner sind als dieses Limit, werden schlicht ignoriert. Außerdem gibt es eine Stopword-List wo Wörter aufgelistet werden, die in Texten sehr sehr häufig vorkommen w.z.B. 'the','a','in' etc. Meist also englische Wörter, die man gerne auf seine Sprache lokalisieren würde. Diese Wörter werden bei der Suchanfrage gefiltert oder vielleicht überhaupt nicht in den Index aufgenommen. Wenn man keinen Zugriff auf die Konfiguration von MySQL hat, oder wenn der Provider keine ordentlichen Werte für die Volltextsuche definiert hat, dann schaut es äußerst traurig aus was die Anwendung der Volltextsuche in MySQL betrifft.
.) Wenn man eine Volltext-Suche für mehr als eine Spalte definieren möchte, dann muss man dementsprechend einen FULLTEXT-Index für mehrere Spalten definieren (in phpMyAdmin könnten unerfahrene User Probleme damit haben). Dabei muss man beachten, dass man im MATCH-Operator alle Indices in der Reihenfolge auflistet, wie sie auch in der Erstellung des FULLTEXT-Index aufgezählt wurden.
Z.B.:
Zunächst einen Index erstellen:
ALTER TABLE 'articles' ADD FULLTEXT title_body ('Title' , 'Body' );
Eine einfache Suchanfrage:
SELECT A_ID, Title, Body
FROM articles
WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter');
Wenn wir Body aus der Liste auslassen würden, würde die Suche nicht mehr funktionieren. Normalerweise darf man bei Multiple-Column-Indices die rechts-äußersten Indices progressiv auslassen (also: "col1,col2,col3", "col1,col2", "col1"), aber anscheinend unterstützt MySQL dieses Konzept bei FULLTEXT-Indices nicht (was man im Englischen als "leftmost prefixing" bezeichnet). PhpMyAdmin spuckt bei dieser Query folgenden Fehler aus: "#1191 - Can't find FULLTEXT index matching the column list" :(.
SELECT A_ID, Title, Body
FROM articles
WHERE MATCH (Title) AGAINST ('liste der suchwörter');
.) Die "50% Rauschschwelle": Wenn ein Wort in mehr als 50 % der gefundenen Datensätze vorkommt, dann betrachtet MySQL es als "Rauschwort" und filtert alle Datensätze, die es beinhalten. Das heißt auf Deutsch, wenn ich z.B. 10 Artikel in meiner Datenbank habe, und das Wort "MySQL" in mindestens 5 von denen vorkommt, dann werden diese Artikel bei einer Suchanfrage nach "MySQL" nicht zurückgegeben. Sowas kann nicht immer erwünscht sein, aber man kann dieses Problem mit bool'schen Suchanfragen umgehen:
SELECT A_ID, Title, Body
FROM articles
WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE);
Wenn wir unsere Suchanfragen nach der Relevanz, die von MySQL gleichzeitig bei der Suche kalkuliert wird, sortieren wollten, dann würde die Query wie folgt aussehen:
SELECT A_ID, Title, Body, MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE) AS relevance
FROM articles
WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE)
ORDER BY relevance DESC;
Der Rückgabewert des Match-Operators ist im bool'schen Modus eine ganze Zahl (was der Anzahl der gefundenen Wörter entspricht) und im normalen Modus eine Fließkommazahl, also etwas genauer; nicht nur weil es eine Fließkommazahl ist, sondern weil mehrere Faktoren in die Berechnung dieses Wertes einfließen. Bei bool'schen Suchen in größeren Tabellen, wird es etliche Datensätze mit der selben Relevanz geben, was zur Wirkung haben kann, dass wirklich relevante Texte weit unten in der Ergebnisliste erscheinen würden. Die simpelste Methode das zu ändern, ist, indem wir die Suchanfrage im normalen und im bool'schen Modus durchführen, und die Rückgabewerte zu einem Wert zusammenaddieren:
SELECT A_ID, Title, Body,
MATCH (Title, Body) AGAINST ('liste der suchwörter') AS relevance +
MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE) AS relevance
FROM articles
WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE)
ORDER BY relevance DESC;
Die Nachteile sind offensichtlich, denn: es wird extra Overhead erzeugt, da jetzt in beiden Modi gesucht werden muss; und komplexe Queries die von bool'schen Operatoren Gebrauch machen, können im normalen Modus teilweise oder ganz ignoriert werden (was nicht unbedingt inakzeptabel sein muss).
MfG,
Aziz