2009-06-19 26 views
22

Sono relativamente nuovo a MYSQL e ho riscontrato un problema che mi ha infastidito per un po '. Ho provato a cercare su google tutto il posto per la risposta, ma non ho ancora trovato una soluzione accettabile.Come ordinare i risultati della ricerca fulltext MYSQL per pertinenza

Ecco la domanda Sono in esecuzione al momento di trovare la migliore corrispondenza possibile per un determinato termine di ricerca:

$query="SELECT * from `vocabulary` WHERE translation = 'word' OR translation LIKE '%word%'"; 

i risultati che i rendimenti sono completi, nel senso che includono tutte le righe rilevanti. Tuttavia, non sono ordinati in un ordine particolare e mi piacerebbe che quelli con una corrispondenza esatta vengano visualizzati per primi quando stampo i risultati in PHP. Come questo:


1 | parola < corrispondenza esatta
2 | cruciverba < - corrispondenze parziali in ordine alfabetico/
3 | parole
4 | wordsmith


Grazie mille in anticipo per il vostro aiuto.

-macspacejunkie

+0

AGGIORNAMENTO: Grazie a tutti per l'assistenza! Proprio quello che stavo cercando. Saluti, -macspacejunkie – user125591

+0

se qualcuno ti ha aiutato, si prega di controllare la loro risposta – Jason

risposta

14
SELECT * from vocabulary 
WHERE translation like 'word' 
union all 
SELECT * from vocabulary 
WHERE translation LIKE '%word%' and translation not like 'word' 

elencherà corrispondenze esatte prima

+1

Questo è un modo molto terribile di fare cose in grandi tavoli. Prendi in considerazione l'utilizzo della ricerca FULLTEXT per query molto più veloci – OverCoder

28

LIKE non è fulltext search. Nella ricerca testo completo, MATCH(...) AGAINST(...) restituisce un punteggio corrispondente che può essere approssimativamente approssimato come pertinenza.

21

È possibile ottenere una buona ricerca di pertinenza creando un indice di testo completo e quindi confrontandolo con il termine di ricerca.

Quindi qualcosa del genere dovrebbe funzionare.

ALTER TABLE `vocabulary` ADD FULLTEXT INDEX `SEARCH`(`translation`); 

SELECT *, MATCH(translation) AGAINST ('+word' IN BOOLEAN MODE) AS relevance 
FROM `vocabulary` 
WHERE MATCH(translation) AGAINST ('+word' IN BOOLEAN MODE) 
ORDER BY relevance DESC 

Ulteriori informazioni sono reperibili nello MySQL Reference Manual.

+13

Quando il comando MATCH viene utilizzato nella clausola WHERE, MySQL ordina automaticamente le righe dalla rilevanza più alta a quella più bassa. – ejunker

+0

Grazie, Rich Adams ed ejunker per questo. Entrambi i punti molto buoni. Ho avuto un cliente che mi ha messo le mani sulla rilevanza della ricerca e questo è di grande aiuto. – Volomike

+0

@ejunker sarebbe fantastico. Potresti per favore indicare un riferimento a questo? Questo vale anche per BOOLEAN MODE? Grazie. – Havok

5

Ho cercato lo stesso problema e non ho ancora trovato la risposta perfetta per la mia situazione, ma questo potrebbe essere utile per voi. Sono abbastanza nuovo nella ricerca a testo integrale, quindi anche gli esperti mi aiutano.

Faccio due istruzioni MATCH() CONTRO() nella selezione e unisco il punteggio da ciascuno per formare la pertinenza totale. Assegnare diversi moltiplicatori mi permette di configurare l'importazione di ogni insieme di risultati.

Il mio primo MATCH() avrebbe controllato il termine di ricerca letterale (o esatto) usando le virgolette doppie Il mio secondo MATCH avrebbe controllato normalmente. Applico un moltiplicatore più alto alla prima partita, quindi dovrebbe avere un valore di pertinenza più elevato se trovato.

Qualcosa di simile.

SELECT *, ((MATCH(indexes) AGAINST ('"search_terms"' IN BOOLEAN MODE) * 10) 
      + (MATCH(indexes) AGAINST ('search_terms' IN BOOLEAN MODE) * 1.5)) AS relevance 
FROM ... 
WHERE ... 
     AND (MATCH (indexes) AGAINST ('"search_terms"' IN BOOLEAN MODE) > 0 
      OR MATCH (indexes) AGAINST ('search_terms' IN BOOLEAN MODE) > 0) 
     ... 
ORDER BY relevance DESC 

Se si esegue utilizzare la funzione EXPLAIN per mostrare come la query funziona si dovrebbe trovare che la partita in più() CONTRO clausole() dont effettivamente aggiungere alcun overhead alla query a causa del modo in cui funziona MySQL.

2

La query richiede solo una piccola modifica per ottenere l'ordine che stai cercando.

SELECT * 
FROM vocabulary 
WHERE translation LIKE '%word%' 
ORDER BY translation <> 'word', translation; 

Se translation è esattamente 'word', sarà in cima ai risultati. Questo perché translation <> 'word' sarà quando c'è un corrispondenza esatta che precede lo che verrà restituito per tutti gli altri risultati. I risultati rimanenti verranno ordinati alfabeticamente in seguito, a causa dello , translation.

Questa query evita di eseguire due query come la risposta selezionata con il suo UNION. Inoltre, la query non ha bisogno di translation = 'word' OR translation LIKE '%word%' poiché la seconda metà verrà sempre eseguita ed è un superset della prima parte.

Per coloro che sono alla ricerca di una risposta che utilizza una ricerca di testo completo effettiva, vedere le altre risposte a più alto incremento.

Problemi correlati