2009-07-14 30 views
24

Sto tentando di aggiungere il supporto alla ricerca per la mia app Web PHP utilizzando gli indici FULLTEXT di MySQL.MySQL FULLTEXT non funziona

Ho creato una tabella di test (utilizzando il tipo MyISAM, con un singolo campo di testo a) e inserito alcuni dati di esempio. Ora se ho ragione la seguente query dovrebbe restituire entrambe le righe:

SELECT * FROM test WHERE MATCH(a) AGAINST('databases') 

Tuttavia non restituisce nessuno. Ho fatto un po 'di ricerche e sto facendo tutto per quanto posso dire - la tabella è una tabella MyISAM, gli indici FULLTEXT sono impostati. Ho provato a eseguire la query dal prompt e da phpMyAdmin, senza fortuna. Mi sto perdendo qualcosa di cruciale?


UPDATE: Ok, mentre la soluzione di Cody ha lavorato nel mio banco di prova non sembra di lavorare sul mio tavolo reale:

CREATE TABLE IF NOT EXISTS `uploads` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` text NOT NULL, 
    `size` int(11) NOT NULL, 
    `type` text NOT NULL, 
    `alias` text NOT NULL, 
    `md5sum` text NOT NULL, 
    `uploaded` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; 

E i dati che sto usando:

INSERT INTO `uploads` (`id`, `name`, `size`, `type`, `alias`, `md5sum`, `uploaded`) VALUES 
(1, '04 Sickman.mp3', 5261182, 'audio/mp3', '1', 'df2eb6a360fbfa8e0c9893aadc2289de', '2009-07-14 16:08:02'), 
(2, '07 Dirt.mp3', 5056435, 'audio/mp3', '2', 'edcb873a75c94b5d0368681e4bd9ca41', '2009-07-14 16:08:08'), 
(3, 'header_bg2.png', 16765, 'image/png', '3', '5bc5cb5c45c7fa329dc881a8476a2af6', '2009-07-14 16:08:30'), 
(4, 'page_top_right2.png', 5299, 'image/png', '4', '53ea39f826b7c7aeba11060c0d8f4e81', '2009-07-14 16:08:37'), 
(5, 'todo.txt', 392, 'text/plain', '5', '7ee46db77d1b98b145c9a95444d8dc67', '2009-07-14 16:08:46'); 

La query ora sto correndo è:

SELECT * FROM `uploads` WHERE MATCH(name) AGAINST ('header' IN BOOLEAN MODE) 

Quale dovrebbe restituire la riga 3, header_bg2.png. Invece ottengo un altro set di risultati vuoto. Le mie opzioni per la ricerca booleana sono al di sotto:

mysql> show variables like 'ft_%'; 
+--------------------------+----------------+ 
| Variable_name   | Value   | 
+--------------------------+----------------+ 
| ft_boolean_syntax  | + -><()~*:""&| | 
| ft_max_word_len   | 84    | 
| ft_min_word_len   | 4    | 
| ft_query_expansion_limit | 20    | 
| ft_stopword_file   | (built-in)  | 
+--------------------------+----------------+ 
5 rows in set (0.02 sec) 

"header" si trova entro i limiti di lunghezza di parola e dubito che sia una parola di arresto (non sono sicuro di come ottenere l'elenco). Qualche idea?

+0

È possibile visualizzare l'elenco delle parole chiave qui https://dev.mysql.com/doc/refman/5.5/it/full-text-stopwords.html, per InnoDB http://dev.mysql.com/doc/refman/5.7/en/innodb-ft-default-stopword-table.html o eseguire SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD; –

risposta

46

aggiungere altri dati. Per impostazione predefinita, MySQL ignorerà qualsiasi parola presente nel 50% o più delle righe nella tabella poiché ritiene che sarebbe una parola 'disturbo'.

Con pochissime righe in una tabella, è frequente raggiungere questo limite del 50% spesso (cioè se si hanno due righe, ogni parola è in almeno il 50% delle righe!).

+0

+1 .. mi ha salvato un po 'di tempo alla ricerca di risposte –

+3

A meno che non utilizza la modalità booleana (MySQL4.1 +), che ignora la regola 50. – TheCarver

+0

+1 anche da qui, grazie per la spiegazione –

23

Esistono due modalità per la ricerca fulltext di MySQL: modalità linguaggio naturale e modalità booleana. Una restrizione della modalità di linguaggio naturale è "... le parole presenti nel 50% o più delle righe sono considerate comuni e non corrispondono. Le ricerche di testo completo sono ricerche in linguaggio naturale se non viene fornito alcun modificatore." E la lingua naturale è la modalità predefinita. Questo è documentato nella documentazione di Testo completo:

http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Se si passa la query al utilizzando la modalità booleana:

SELECT * FROM test WHERE MATCH(a) AGAINST('databases' IN BOOLEAN MODE) 

Poi i due file vengono restituiti.

La modalità booleana ha le proprie restrizioni, una comune è che non restituisce le righe in ordine di pertinenza. Nel complesso, offre più funzionalità e flessibilità rispetto alla modalità in linguaggio naturale, quindi probabilmente finirai per usarlo.

Se l'applicazione sta per affidarsi pesantemente al full-text ricerca si potrebbe prendere in considerazione più pacchetti full-optional come ad esempio Lucene/Solr o Sphinx

+0

Grazie, non mi rendevo conto circa la regola del 50% :) – Ross

+1

Questa è una risposta molto meglio se mi chiedete. – TheCarver

Problemi correlati