2012-01-26 13 views
11

Se me ha encomendado la tarea de crear una función de búsqueda en todo el sitio. La búsqueda necesita mirar artículos, eventos y contenido de la páginaRelevancia de búsqueda de texto completo de Mysql en varias tablas

He usado MATCH()/AGAINST() en MySQL antes y sé cómo obtener la relevancia de un resultado pero hasta donde sé la relevancia es única a la búsqueda (contenido, número de filas, etc.) la relevancia de los resultados de la tabla de artículos no coincidirá con la relevancia de los resultados de la tabla de eventos.

¿Hay alguna forma de unificar la relevancia para que los resultados de las tres tablas tengan una relevancia comparable?

+0

Lógicamente, este parece ser un buen lugar para usar una unión y seleccionar con coincidencia; pero nunca lo he usado para buscar de esta manera; así que dudo que esta sea la MEJOR manera. – xQbert

+0

¿habría alguna forma de ponderar las novedades? simplemente un simple multiplicar – bowlerae

+0

Me pregunté sobre la normalización de la mayor relevancia para 1, pero que aún arroja los resultados en múltiples tablas – michael

Respuesta

20

Sí, puede unificarlos muy bien utilizando un motor de búsqueda como Apache Lucene y Solr.

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

Si tiene que hacerlo sólo en MySQL, se puede hacer esto con un sindicato. Probablemente quiera suprimir cualquier resultado relevante cero.

Deberá decidir cómo desea afectar la relevancia según qué tabla coincida.

Por ejemplo, supongamos que desea que los artículos sean más importantes, que los eventos sean medianamente importantes y que las páginas sean menos importantes. Puede utilizar multiplicadores de esta manera:

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

Aquí está un ejemplo de trabajo puede probar que demuestra algunas de estas técnicas:

Crear datos de ejemplo:

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."); 

que admita búsquedas:

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

Utilice un UNION para buscar en todas estas tablas:

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; 

El resultado:

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

¡Esto es asombroso! Tengo una pregunta muy similar, pero necesito coincidencias relacionadas. ¿podrías echarle un vistazo también? http://stackoverflow.com/q/9953922/633513 – LordZardeck

+0

¡Eres INCREÍBLE! – Cogicero

+0

¡Muchas gracias por esta respuesta! – Marcky

2

(Lo siento, quiero dejar esto como comentario a la respuesta anterior, pero no tengo la reputación suficiente para comentar)

Tenga en cuenta que la unión en subconsultas están muy mal optimizados. Un caso frecuente es cuando desea paginar los resultados usando "LIMIT @page * 10, 10" en la consulta principal, entonces MySQL debe obtener todos los resultados de las subconsultas para evaluar la consulta principal.

Cuestiones relacionadas