2011-08-19 8 views
6

Sono abbastanza nuovo per le ricerche full-text MySQL e mi sono imbattuto in questo problema oggi:mysql modalità booleana ricerca full-text con caratteri jolly e letterali

Il mio tavolo azienda ha un record con "e-magazine AG" nel colonna del nome. Ho un indice full-text sulla colonna del nome.

Quando eseguo questa query il record non è stato trovato:

SELECT id, name FROM company WHERE MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

ho bisogno di lavorare con le citazioni a causa del cruscotto e di utilizzare il jolly perché implementare una "ricerca durante la digitazione" funzionalità.

Quando cerco l'intero termine "e-magazine AG", viene trovato il record.

Qualche idea su cosa sto facendo male qui? Ho letto di aggiungere il trattino all'elenco di caratteri di parole (necessario aggiornamento di configurazione), ma sto cercando un modo per farlo a livello di programmazione.

+0

Interessante domanda. Posso replicarlo qui in un tavolo con un campo simile a uuid. 'SELECT id, bootid FROM socket WHERE MATCH (bootid) AGAINST ('+' 18bda775" 'IN BOOLEAN MODE); 'funzionerà e lo sarà anche se cerco" 18bda775-711c ", ma cerco" 18bda "o" 18bda775 -711 "non funzionerà. il campo 'bootid' in questione contiene: 18bda775-711c-4329-9de2-a3d81dc13d06 –

+0

Abbiamo anche provato a cambiare i caratteri di controllo booleani per usare # invece di - ma non ha avuto alcun effetto (sì, ho riparato l'indice della tabella dopo la modifica) : 'ft_boolean_syntax = + #><() ~ *:" "& |' – hajo

risposta

2

Questa clausola

MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

Cercherà di AND "e" AND NOT "magazi"; Ad esempio, lo - all'interno di "e-magazmi" verrà interpretato come not anche se è racchiuso tra virgolette.
Per questo motivo non funzionerà come previsto.
Una soluzione consiste nell'applicare una clausola aggiuntiva having con un LIKE.

So che questo having è lento, ma verrà applicato solo ai risultati della corrispondenza, quindi non devono essere coinvolte troppe righe.

suggerisco qualcosa di simile:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('magazine' IN BOOLEAN MODE) 
HAVING name LIKE '%e-magazi%'; 
+0

grazie per le informazioni ma non mi aiuta perché la stringa di ricerca viene inserita dall'utente che vuole cercare un'azienda.in altre parole, il backend che esegue la query non può sapere che "e-magazi" fa parte della stringa "e-magazine". il campo di ricerca dovrebbe accettare sia parti di parole che parole complete. – hajo

+0

Metodo davvero unico per il metodo di filtraggio! Grazie! – ProfileTwist

+0

Dove vedi gli spazi bianchi davanti o dopo la frase di ricerca ?! '+' È un normale operatore fulltext e non uno spazio bianco! – mgutt

0

MySQL documento considera la parola e-magazine in un testo come frase e non come una parola. Per questo motivo risulta lo due parole e e magazine. E mentre costruisce l'indice di ricerca non aggiunge il valore e all'indice a causa dello ft_min_word_len (il valore predefinito è 4 caratteri).

La stessa limitazione di lunghezza viene utilizzata per la query di ricerca. Questo è il motivo per cui la ricerca di e-magazine restituisce esattamente gli stessi risultati di a-magazine perché a e - viene completamente ignorata.

Ma ora si desidera trovare la frase esatta e-magazine.Con utilizzare le virgolette e questo è il modo corretto completo per trovare le frasi, ma MySql non supporta gli operatori per le frasi, solo la parola:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html

Con questo modificatore, alcuni caratteri hanno un significato speciale al all'inizio o alla fine di parole nella stringa di ricerca

Alcune persone suggerire di utilizzare la seguente query:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE) 
HAVING name LIKE 'e-magazi%'; 

Come ho detto, MySQL ignora lo e- e cerca la parola jolly magazi*. Dopo aver ottenuto questi risultati, utilizza HAVING per filtrare in modo adizionale i risultati per e-magazi* incluso lo e-. In questo modo troverai la frase e-magazine AG. Ovviamente HAVING è necessario solo se la frase di ricerca contiene l'operatore jolly e non si dovrebbero mai usare le virgolette. Questo operatore è usato dal tuo utente e non tu!

Nota: Finché non si circonda la frase di ricerca con %, troverà solo i campi che iniziano con quella parola. E tu non vuoi circondarlo, perché troverà anche bee-magazine. Quindi forse hai bisogno di un ulteriore OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%' per renderlo utilizzabile all'interno dei testi.

trucco

Ma alla fine io preferisco un trucco così HAVING non è necessario a tutti:

  1. Se si aggiungono testi per la tabella di database, aggiungerli in aggiunta a una colonna separata full-text indicizzata e sostituire parole come up-to-date con up-to-date uptodate.
  2. Se un utente cerca up-to-date sostituirlo nella query con uptodate.

Con questo si può ancora trovare specific in user-specific ma up-to-date così (e non solo date).

Bonus

Se un utente cerca -well-known huge ports MySQL per trattamento che, come not include *well*, could include *known* and *huge*. Ovviamente lo si può risolvere anche con un'altra variante di interrogazione, ma con il trucco sopra si rimuove il trattino in modo che la query di ricerca appaia semplicemente così:

Problemi correlati