2009-12-14 17 views
5

Ho un sito che deve cercare tra circa 20-30k record, che sono per lo più nomi di film e programmi TV. Il sito esegue php/mysql con memcache.Qual è l'applicazione di ricerca di siti più semplice da implementare, che supporta la ricerca fuzzy?

Sto cercando di sostituire il FULLTEXT con la ricerca soundex() che attualmente ho, che funziona ... il tipo di, ma non è molto buono in molte situazioni.

Ci sono degli script di ricerca decenti là fuori che sono semplici da implementare e forniranno una capacità di ricerca decente (di 3 colonne in una tabella).

risposta

6

di ewemli è nella giusta direzione, ma dovresti combinare FULLTEXT e soundex mapping, non sostituendo il testo completo, altrimenti le tue query LIKE saranno molto lente.

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 | 
+----+--------------------------------+---------------------------+ 

Questo dà buoni risultati (entro i limiti della algo soundex) mentre sfruttando al massimo un indice (qualsiasi richiesta COME '% foo' deve scansione di ogni riga della tabella).

Nota l'importanza di eseguire soundex su ogni parola, non sull'intera frase. Puoi anche eseguire la tua versione di soundex su ogni parola invece di fare SQL, ma in tal caso assicurati di farlo sia quando archivi e recuperi nel caso ci siano differenze tra gli algoritmi (ad esempio, l'algoritmo di MySQL non limita stesso allo standard 4 chars)

0

Esiste una funzione SOUNDEX in mysql. Se si vuole cercare un titolo di un film:

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

Naturalmente non funziona per la ricerca nel testo, come ad esempio film o riassunto della trama.


Soundex è un relativamente semplice algo. Si può anche decidere di gestire tutto ciò che a livello applicativo, può essere più facile:

  • quando il testo viene memorizzato, tokenize ed applicare soundex su tutte le parole
  • memorizzare il testo originale e la versione soundex in due colonne
  • durante la ricerca, calcola l'audio dall'app. livello e quindi utilizzare un regolare LIKE a livello di database.
+0

Sono incuriosito. Se film.title è "Apocalypse Now" ma l'utente cerca "Apocalypse Cow", il soundex potrebbe trovare una corrispondenza per "... dove film.title =" $ user_title "OR soundex (film.title) = soundex ($ user_title) '; Ma questo non funzionerebbe, ad esempio, film.intro var (255) che conteneva "Martin Sheen" e l'utente ha cercato "Martin Shean" ho capito? Scusate se questo Q/commento è nel posto sbagliato, per favore mi metta a posto se così. – Cups

+0

soundex ('Un film con Martin Sheen') -> A513563525, selezionare soundex ('A'), soundex ('film'), soundex ('with'), soundex ('Martin'), soundex ('Sheen'); -> A000, M100, W300, M635, S500 Quindi, se si memorizza la versione soundex del testo "A000 M100 W300 M635 S500" e si ricerca con LIKE '% M635% S500%' potrebbe essere ok. Questo tuttavia non è ancora ottimale. La ricerca di "Mart Insheen" (possibile fraintendimento del nome) rende LIKE "% M630% I525%" e non funzionerebbe. – ewernli

1

Se siete alla ricerca di una soluzione semplice esistente invece di creare la propria soluzione check out

0

Soundex ha limitazioni per la ricerca fuzzy. Una funzione migliore è la modifica della distanza, che può essere integrata in MySQL usando UDF. Controllare http://flamingo.ics.uci.edu/toolkit/ per un'implementazione C++ per MySQL su Linux.

Problemi correlati