2009-12-14 4 views
5

Ich habe eine Website, die über 20-30k Datensätze suchen, die meist Film und TV-Show-Namen sind. Die Seite führt php/mysql mit Memcache aus.Was ist die einfachste Site Search-Anwendung zu implementieren, die Fuzzy-Suche unterstützt?

Ich bin auf der Suche nach der FULLTEXT durch soundex() Suche, die ich derzeit habe, was funktioniert ... irgendwie, aber ist nicht sehr gut in vielen Situationen.

Gibt es irgendwelche anständigen Suchskripts, die einfach zu implementieren sind und eine anständige Suchfunktion (von 3 Spalten in einer Tabelle) bieten.

Antwort

6

ewemli Antwort in der richtigen Richtung ist, aber Sie sollten FULLTEXT und Soundex-Mapping kombinieren und nicht den Volltext ersetzen, da Ihre LIKE-Abfragen sonst sehr langsam sind.

create table with_soundex (
    id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, 
    original TEXT, 
    soundex TEXT, 
    FULLTEXT (soundex) 
); 

insert into with_soundex (original, soundex) values 

('add some test cases', CONCAT_WS(' ', soundex('add'), soundex('some'), soundex('test'), soundex('cases'))), 
('this is some text', CONCAT_WS(' ', soundex('this'), soundex('is'), soundex('some'), soundex('text'))), 
('one more test case', CONCAT_WS(' ', soundex('one'), soundex('more'), soundex('test'), soundex('case'))), 
('just filling the index', CONCAT_WS(' ', soundex('just'), soundex('filling'), soundex('the'), soundex('index'))), 
('need one more example', CONCAT_WS(' ', soundex('need'), soundex('one'), soundex('more'), soundex('example'))), 
('seems to need more', CONCAT_WS(' ', soundex('seems'), soundex('to'), soundex('need'), soundex('more'))) 
('some helpful cases to consider', CONCAT_WS(' ', soundex('some'), soundex('helpful'), soundex('cases'), soundex('to'), soundex('consider'))) 

select * from with_soundex where match(soundex) against (soundex('test')); 
+----+---------------------+---------------------+ 
| id | original   | soundex    | 
+----+---------------------+---------------------+ 
| 1 | add some test cases | A300 S500 T230 C000 | 
| 2 | this is some text | T200 I200 S500 T230 | 
| 3 | one more test case | O500 M600 T230 C000 | 
+----+---------------------+---------------------+ 

select * from with_soundex where match(soundex) against (CONCAT_WS(' ', soundex('test'), soundex('some'))); 
+----+--------------------------------+---------------------------+ 
| id | original      | soundex     | 
+----+--------------------------------+---------------------------+ 
| 1 | add some test cases   | A300 S500 T230 C000  | 
| 2 | this is some text    | T200 I200 S500 T230  | 
| 3 | one more test case    | O500 M600 T230 C000  | 
| 7 | some helpful cases to consider | S500 H414 C000 T000 C5236 | 
+----+--------------------------------+---------------------------+ 

Die recht gute Ergebnisse (innerhalb der Grenzen des soundex algo) bei maximalem Vorteile eines Index unter (jede Abfrage LIKE ‚% foo‘ hat jede Zeile in der Tabelle zu scannen).

Beachten Sie, dass es wichtig ist, soundex auf jedes Wort und nicht auf die gesamte Phrase anzuwenden. Sie könnten auch Ihre eigene Version von soundex auf jedem Wort ausführen, anstatt SQL zu machen, aber in diesem Fall stellen Sie sicher, dass Sie beides beim Speichern und Abrufen tun, falls es Unterschiede zwischen den Algorithmen gibt (z selbst zum Standard 4 chars)

0

Es gibt eine Funktion SOUNDEX in mysql. Wenn Sie einen Filmtitel gesucht werden sollen:

select * from movie where soundex(title) = soundex('the title'); 

Natürlich funktioniert es nicht im Text, wie Film oder Inhaltsangabe zu suchen.


Soundex ist eine relativ einfache algo. Sie können auch entscheiden, dass alle auf der applicative Ebene zu behandeln, kann es einfacher sein:

  • , wenn der Text gespeichert ist, tokenize und wenden soundex auf alle Wörter
  • speichern den ursprünglichen Text und die soundex Version in zwei Spalten
  • Wenn Sie suchen, berechnen Sie den Soundex in der App. Ebene und verwenden Sie dann einen regulären LIKE auf der Ebene db.
+0

Ich bin fasziniert. Wenn film.title "Apocalypse Now" ist, aber der Nutzer nach "Apocalypse Cow" sucht, findet der Soundex möglicherweise eine Übereinstimmung, die "... where film.title =" $ user_title "ODER soundex (film.title) = soundex ($ user_title) '; Aber das würde nicht funktionieren in sagen, Film.intro var (255), die "Martin Sheen" enthalten und Benutzer nach "Martin Shean" gesucht habe ich verstanden? Entschuldigung, wenn dieser Q/Kommentar an falscher Stelle ist, bitte leg mich richtig wenn ja. – Cups

+0

soundex ('Ein Film mit Martin Sheen') -> A513563525, Soundex ('A'), Soundex ('Film'), Soundex ('Mit'), Soundex ('Martin'), Soundex ('Sheen'); -> A000, M100, W300, M635, S500 Wenn Sie also die Soundex-Version des Textes 'A000 M100 W300 M635 S500' speichern und mit LIKE '% M635% S500%' suchen, ist das in Ordnung. Dies ist jedoch immer noch nicht optimal. Die Suche nach "Mart Insheen" (mögliches Missverständnis des Namens) ergibt LIKE "% M630% I525%" und würde nicht funktionieren. – ewernli

1

Wenn Sie nach einer einfachen bestehenden Lösung suchen, anstatt Ihre eigene Lösung zu schaffen, überprüft

0

Soundex hat Beschränkungen, um mit unscharfer Suche sich zu befassen. Eine bessere Funktion ist die Bearbeitungsentfernung, die mit UDF in MySQL integriert werden kann. Überprüfen Sie http://flamingo.ics.uci.edu/toolkit/ für eine C++ - Implementierung für MySQL unter Linux.

Verwandte Themen