MySQL match () contra () – ordena por relevancia y columna?

De acuerdo, entonces estoy tratando de hacer una búsqueda de texto completo en varias columnas, algo simple como esto:

SELECT * FROM pages WHERE MATCH(head, body) AGAINST('some words' IN BOOLEAN MODE) 

Ahora quiero ordenar por relevancia (¿cuántas de las palabras se encuentran?) Que he podido hacer con algo como esto:

 SELECT * , MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE) AS relevance FROM pages WHERE MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE) ORDER BY relevance 

Ahora aquí viene la parte en la que me pierdo, quiero priorizar la relevancia en la columna principal.

Creo que podría hacer dos columnas de relevancia, una para la head y otra para el body , pero en ese punto estaría haciendo la misma búsqueda en la tabla tres veces, y para lo que estoy haciendo esta función, el rendimiento es importante, ya que la consulta se unirá y comparará con otras tablas.

Entonces, mi pregunta principal es , ¿existe una forma más rápida de buscar relevancia y priorizar ciertas columnas? (¿Y como ventaja adicional, incluso haciendo que la relevancia cuente el número de veces que aparecen las palabras en las columnas?)

Cualquier sugerencia o consejo sería genial.

Nota: voy a ejecutar esto en un servidor LAMP. (WAMP en pruebas locales)

Esto podría darle una mayor relevancia a la parte principal que desee. No lo duplicará, pero posiblemente sea lo suficientemente bueno por su bien:

 SELECT pages.*, MATCH (head, body) AGAINST ('some words') AS relevance, MATCH (head) AGAINST ('some words') AS title_relevance FROM pages WHERE MATCH (head, body) AGAINST ('some words') ORDER BY title_relevance DESC, relevance DESC -- alternatively: ORDER BY title_relevance + relevance DESC 

Una alternativa que también desea investigar, si tiene la flexibilidad para cambiar el motor de DB, es Postgres . Permite establecer el peso de los operadores y jugar con el ranking.

Nunca lo he hecho, pero parece que

 MATCH (head, head, body) AGAINST ('some words' IN BOOLEAN MODE) 

Debería dar un doble peso a las coincidencias encontradas en la cabeza.


Solo lea este comentario en la página de documentos , ya que podría ser valioso para usted:

Publicado por Patrick O’Lone el 9 de diciembre de 2002 6:51 a.m.

Debe observarse en la documentación que IN BOOLEAN MODE casi siempre devolverá una relevancia de 1.0. Para obtener una relevancia que sea significativa, deberá:

 SELECT MATCH('Content') AGAINST ('keyword1 keyword2') as Relevance FROM table WHERE MATCH ('Content') AGAINST('+keyword1+keyword2' IN BOOLEAN MODE) HAVING Relevance > 0.2 ORDER BY Relevance DESC 

Observe que está haciendo una consulta de relevancia regular para obtener factores de relevancia combinados con una cláusula WHERE que usa el MODO BOOLEAN. El MODO BOOLEAN le proporciona el subconjunto que cumple los requisitos de la búsqueda BOOLEAN, la consulta de relevancia cumple el factor de relevancia y la cláusula HAVING (en este caso) garantiza que el documento sea relevante para la búsqueda (es decir, documentos con una puntuación inferior a 0,2 se consideran irrelevantes). Esto también le permite ordenar por relevancia.

Esto puede o no ser un error en la forma en que funciona IN BOOLEAN MODE, aunque los comentarios que he leído en la lista de correo sugieren que el ranking de relevancia de IN BOOLEAN MODE no es muy complicado, por lo que se presta mal para proporcionar documentos relevantes. Por cierto, no noté una pérdida de rendimiento por hacer esto, ya que parece que MySQL solo realiza la búsqueda FULLTEXT una vez, aunque las dos cláusulas de MATCH son diferentes. Use EXPLAIN para probar esto.

Por lo tanto, parece que no necesita preocuparse por llamar dos veces al texto completo de búsqueda, aunque debería “usar EXPLAIN para probarlo”.

Solo agregue para quien pueda necesitar … ¡No olvide alterar la mesa!

 ALTER TABLE table_name ADD FULLTEXT(column_name); 

Yo solo estaba jugando con esto, también. Una forma de agregar peso extra es en el área ORDER BY del código.

Por ejemplo, si combinara 3 columnas diferentes y quisiera ponderar más determinadas columnas:

 SELECT search.*, MATCH (name) AGAINST ('black' IN BOOLEAN MODE) AS name_match, MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE) AS keyword_match, MATCH (description) AGAINST ('black' IN BOOLEAN MODE) AS description_match FROM search WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE) ORDER BY (name_match * 3 + keyword_match * 2 + description_match) DESC LIMIT 0,100;