Ich habe herausgefunden, dass der Levenshtein-Abstand gut sein kann, wenn Sie eine vollständige Zeichenfolge gegen eine andere vollständige Zeichenfolge suchen. Wenn Sie jedoch nach Schlüsselwörtern innerhalb einer Zeichenfolge suchen, gibt diese Methode (manchmal) nicht die gewünschten Ergebnisse zurück. Darüber hinaus ist die SOUNDEX-Funktion nicht für andere Sprachen als Englisch geeignet, sodass sie recht eingeschränkt ist. Sie könnten mit LIKE davonkommen, aber es ist wirklich für einfache Suchen. Möglicherweise möchten Sie andere Suchmethoden untersuchen, um herauszufinden, was Sie erreichen möchten. Zum Beispiel:
Sie können Lucene als Suchbasis für Ihre Projekte verwenden. Es ist in den meisten gängigen Programmiersprachen implementiert und sehr schnell und vielseitig einsetzbar. Diese Methode ist wahrscheinlich die beste, da nicht nur nach Teilzeichenfolgen gesucht wird, sondern auch nach Buchstabenumsetzung, Präfixen und Suffixen (alle kombiniert). Sie müssen jedoch einen separaten Index führen (die Verwendung von CRON zum gelegentlichen Aktualisieren von einem unabhängigen Skript funktioniert jedoch).
Wenn Sie eine MySQL-Lösung wünschen, ist die Volltextfunktionalität ziemlich gut und sicherlich schneller als eine gespeicherte Prozedur. Wenn Ihre Tabellen nicht MyISAM sind, können Sie eine temporäre Tabelle erstellen und dann Ihre Volltextsuche durchführen:
CREATE TABLE IF NOT EXISTS `tests`.`data_table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(2000) CHARACTER SET latin1 NOT NULL,
`description` text CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
Verwenden Sie einen Datengenerator , um zufällige Daten zu generieren, wenn Sie sich nicht die Mühe machen möchten, diese selbst zu erstellen ...
** HINWEIS **: Der Spaltentyp sollte latin1_bin
darin bestehen, eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung durchzuführen latin1
. Für Unicode-Zeichenfolgen würde ich für Suchvorgänge ohne Berücksichtigung der utf8_bin
Groß- und utf8_general_ci
Kleinschreibung empfehlen .
DROP TABLE IF EXISTS `tests`.`data_table_temp`;
CREATE TEMPORARY TABLE `tests`.`data_table_temp`
SELECT * FROM `tests`.`data_table`;
ALTER TABLE `tests`.`data_table_temp` ENGINE = MYISAM;
ALTER TABLE `tests`.`data_table_temp` ADD FULLTEXT `FTK_title_description` (
`title` ,
`description`
);
SELECT *,
MATCH (`title`,`description`)
AGAINST ('+so* +nullam lorem' IN BOOLEAN MODE) as `score`
FROM `tests`.`data_table_temp`
WHERE MATCH (`title`,`description`)
AGAINST ('+so* +nullam lorem' IN BOOLEAN MODE)
ORDER BY `score` DESC;
DROP TABLE `tests`.`data_table_temp`;
Weitere Informationen finden Sie auf der MySQL API-Referenzseite
Der Nachteil dabei ist, dass es nicht nach Buchstabenumsetzung oder "ähnlichen, klingt wie" Wörtern sucht.
** UPDATE **
Wenn Sie Lucene für Ihre Suche verwenden, müssen Sie lediglich einen Cron-Job erstellen (alle Webhosts verfügen über diese "Funktion"), bei dem dieser Job einfach ein PHP-Skript ausführt (z. B. "cd / path / to / script; php searchindexer.php"). ), die die Indizes aktualisiert. Der Grund dafür ist, dass das Indizieren von Tausenden von "Dokumenten" (Zeilen, Daten usw.) einige Sekunden oder sogar Minuten dauern kann. Dies soll jedoch sicherstellen, dass alle Suchvorgänge so schnell wie möglich ausgeführt werden. Daher möchten Sie möglicherweise einen Verzögerungsjob erstellen, der vom Server ausgeführt wird. Es kann über Nacht sein oder in der nächsten Stunde liegt es an Ihnen. Das PHP-Skript sollte ungefähr so aussehen:
$indexer = Zend_Search_Lucene::create('/path/to/lucene/data');
Zend_Search_Lucene_Analysis_Analyzer::setDefault(
// change this option for your need
new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
);
$rowSet = getDataRowSet(); // perform your SQL query to fetch whatever you need to index
foreach ($rowSet as $row) {
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::text('field1', $row->field1, 'utf-8'))
->addField(Zend_Search_Lucene_Field::text('field2', $row->field2, 'utf-8'))
->addField(Zend_Search_Lucene_Field::unIndexed('someValue', $someVariable))
->addField(Zend_Search_Lucene_Field::unIndexed('someObj', serialize($obj), 'utf-8'))
;
$indexer->addDocument($doc);
}
// ... you can get as many $rowSet as you want and create as many documents
// as you wish... each document doesn't necessarily need the same fields...
// Lucene is pretty flexible on this
$indexer->optimize(); // do this every time you add more data to you indexer...
$indexer->commit(); // finalize the process
Dann suchen Sie im Grunde so (einfache Suche):
$index = Zend_Search_Lucene::open('/path/to/lucene/data');
// same search options
Zend_Search_Lucene_Analysis_Analyzer::setDefault(
new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
);
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
$query = 'php +field1:foo'; // search for the word 'php' in any field,
// +search for 'foo' in field 'field1'
$hits = $index->find($query);
$numHits = count($hits);
foreach ($hits as $hit) {
$score = $hit->score; // the hit weight
$field1 = $hit->field1;
// etc.
}
Hier finden Sie großartige Websites zu Lucene in Java , PHP und .Net .
Zusammenfassend hat jede Suchmethode ihre eigenen Vor- und Nachteile:
- Sie haben die Sphinx-Suche erwähnt und sie sieht sehr gut aus, solange Sie den Deamon auf Ihrem Webhost ausführen können.
- Zend Lucene benötigt einen Cron-Job, um die Datenbank neu zu indizieren. Dies ist zwar für den Benutzer recht transparent, bedeutet jedoch, dass neue Daten (oder gelöschte Daten!) Nicht immer mit den Daten in Ihrer Datenbank synchronisiert sind und daher nicht sofort bei der Benutzersuche angezeigt werden.
- Die MySQL FULLTEXT-Suche ist gut und schnell, bietet Ihnen jedoch nicht die Leistung und Flexibilität der ersten beiden.
Bitte zögern Sie nicht zu kommentieren, wenn ich etwas vergessen / verpasst habe.