2012-01-26 12 views
11

Sono stato incaricato di creare una funzione di ricerca su tutto il sito. La ricerca ha bisogno di guardare articoli, eventi e pagina di contenutoRilevanza ricerca full text Mysql su più tabelle

Ho usato MATCH()/CONTRO() in MySQL prima e sa come ottenere la rilevanza di un risultato, ma per quanto ne so la rilevanza è unico alla ricerca (contenuto, numero di righe ecc.) la pertinenza dei risultati dalla tabella degli articoli non corrisponde alla pertinenza dei risultati della tabella degli eventi.

È comunque necessario unificare la pertinenza in modo che i risultati di tutte e tre le tabelle abbiano una rilevanza comparabile?

+0

Logicamente questo sembra essere un buon posto per usare un sindacato e sub-select con match contro; ma non l'ho mai usato per cercare in questo modo; quindi dubito che questo sia il modo migliore. – xQbert

+0

ci sarebbe un modo per voi di ponderare le rilevanze? solo un semplice multiplo – bowlerae

+0

Mi chiedevo di normalizzare la massima rilevanza a 1 ma che ancora genera i risultati su più tabelle – michael

risposta

20

Sì, è possibile unificarle molto bene utilizzando un motore di ricerca come Apache Lucene e Solr.

http://lucene.apache.org/solr/

Se avete bisogno di farlo solo in MySQL, si può fare questo con un UNION. Probabilmente vorrai eliminare qualsiasi risultato rilevante per lo zero.

È necessario decidere come si desidera influire sulla pertinenza in base alla tabella corrispondente.

Ad esempio, si supponga di volere che gli articoli siano più importanti, che gli eventi siano di importanza media e che le pagine siano meno importanti. È possibile utilizzare i moltiplicatori come questo:

set @articles_multiplier=3; 
set @events_multiplier=2; 
set @pages_multiplier=1; 

Ecco un esempio di lavoro si può provare che dimostra alcune di queste tecniche:

Crea dati di esempio:

create database d; 
use d; 

create table articles (id int primary key, content text) ENGINE = MYISAM; 
create table events (id int primary key, content text) ENGINE = MYISAM; 
create table pages (id int primary key, content text) ENGINE = MYISAM; 

insert into articles values 
(1, "Lorem ipsum dolor sit amet"), 
(2, "consectetur adipisicing elit"), 
(3, "sed do eiusmod tempor incididunt"); 

insert into events values 
(1, "Ut enim ad minim veniam"), 
(2, "quis nostrud exercitation ullamco"), 
(3, "laboris nisi ut aliquip"); 

insert into pages values 
(1, "Duis aute irure dolor in reprehenderit"), 
(2, "in voluptate velit esse cillum"), 
(3, "dolore eu fugiat nulla pariatur."); 

Make it ricercabile:

ALTER TABLE articles ADD FULLTEXT(content); 
ALTER TABLE events ADD FULLTEXT(content); 
ALTER TABLE pages ADD FULLTEXT(content); 

Utilizzare UNION per cercare tutte queste tabelle:

set @target='dolor'; 

SELECT * from (
    SELECT 
    'articles' as 'table_name', id, 
    @articles_multiplier * (MATCH(content) AGAINST (@target)) as relevance 
    from articles 
    UNION 
    SELECT 
    'events' as 'table_name', 
    id, 
    @events_multiplier * (MATCH(content) AGAINST (@target)) as relevance 
    from events 
    UNION 
    SELECT 
    'pages' as 'table_name', 
    id, 
    @pages_multiplier * (MATCH(content) AGAINST (@target)) as relevance 
    from pages 
) 
as sitewide WHERE relevance > 0; 

Il risultato:

+------------+----+------------------+ 
| table_name | id | relevance  | 
+------------+----+------------------+ 
| articles | 1 | 1.98799377679825 | 
| pages  | 3 | 0.65545331108093 | 
+------------+----+------------------+ 
+0

È fantastico! Ho una domanda molto simile, ma ho bisogno di corrispondenze correlate. potresti dare un'occhiata anche a questo? http://stackoverflow.com/q/9953922/633513 – LordZardeck

+0

Sei FANTASTICO !! – Cogicero

+0

Grazie mille per questa risposta !!!! – Marcky

2

(Siamo spiacenti, voglio lasciare questo come commento alla risposta di cui sopra, ma non ho abbastanza fama di commentare)

essere consapevoli del fatto che UNION nelle sottoquery sono molto male ottimizzati. Un caso frequente è quando si desidera impaginare i risultati utilizzando "LIMIT @page * 10, 10" nella query padre, quindi MySQL deve ottenere tutti i i risultati delle sottoquery per valutare la query padre.

Problemi correlati