MySQL Volltextsuche mit FULLTEXT Index
Suche über LIKE '%suchbegriff%' ist langsam und unflexibel. Kein Index wird genutzt, keine Relevanz-Sortierung, kein Stemming. MySQL's eingebaute Volltextsuche ist für viele Anwendungsfälle eine bessere Wahl ohne externen Dienst.
Index anlegen
ALTER TABLE articles ADD FULLTEXT INDEX ft_content (title, body);
-- oder beim CREATE TABLE:
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
body TEXT NOT NULL,
FULLTEXT INDEX ft_content (title, body)
);
Suche ausführen
-- Natural Language Mode (Standard)
SELECT id, title, MATCH(title, body) AGAINST ('php sicherheit' IN NATURAL LANGUAGE MODE) AS score
FROM articles
WHERE MATCH(title, body) AGAINST ('php sicherheit' IN NATURAL LANGUAGE MODE)
ORDER BY score DESC;
Der score gibt die Relevanz an — höherer Wert bedeutet bessere Übereinstimmung.
Boolean Mode
-- Muss "php" enthalten, "java" darf nicht enthalten sein, "sicherheit" ist optional
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST ('+php -java sicherheit' IN BOOLEAN MODE);
- Operatoren:
+wort— muss enthalten sein-wort— darf nicht enthalten sein*— Prefix-Suche:php*findet php, phpunit, phpmyadmin"phrase"— exakte Phrase
In PHP
function search(PDO $pdo, string $query, int $limit = 20): array
{
// Sonderzeichen in Boolean Mode escapen
$clean = preg_replace('/[+\-><\(\)~*\"@]+/', ' ', $query);
$terms = implode(' ', array_map(
fn($t) => '+' . $t . '*',
array_filter(explode(' ', trim($clean)))
));
if (empty($terms)) return [];
$stmt = $pdo->prepare('
SELECT id, title,
MATCH(title, body) AGAINST (? IN BOOLEAN MODE) AS score
FROM articles
WHERE MATCH(title, body) AGAINST (? IN BOOLEAN MODE)
ORDER BY score DESC
LIMIT ?
');
$stmt->execute([$terms, $terms, $limit]);
return $stmt->fetchAll();
}
Einschränkungen
- Wörter unter 3 Zeichen (konfigurierbar mit
ft_min_word_len) werden ignoriert - Sehr häufige Wörter (in mehr als 50% der Zeilen) werden als Stopwords behandelt
- Kein Fuzzy-Matching, kein Typo-Toleranz
Für diese Fälle oder für sehr große Datenmengen ist Elasticsearch oder Meilisearch besser geeignet. Für die meisten eigenen Projekte reicht MySQL FULLTEXT aber vollkommen aus.