Diego Di Camillo

Base de tips para problemas comunes de los desarrolladores.



Utilizando MATCH … AGAINST en MySQL | Buscador PHP simple, utilizando funcionalidades de MySQL

22Feb10

Mysql incorpora una función de búsqueda natural a partir de las versiones 4 en adelante y para motores MyISAM unicamente, utliza una instrucción en conjunto con la definición de indices de tipo fulltext.

Nos permitirá realizar busquedas sobre el indice definido al igual que lo haríamos en google. Es muy útil ya que nos evita tener que programarlo o adaptar frames en nuestro sitio.

Para crearlo:

1.- Debemos crear un indice de tipo FULLTEXT en los campos de la tabla (estos campos deben ser de tipo char, Text o Varchar, llamemoslos campo1, campo2, campo3….) donde realizaremos la búsqueda. Para ello con acceder a un phpMyAdmin vas a la parte de inserción de indices (seleccionando primero la tabla donde se insertará).
2.- En el php donde recibimos la query de la consulta realizada (llamemosla $qstring ) agregamos en el WHERE de la consulta esta instrucción:

…. WHERE MATCH ( campo1, campo2, campo3….) AGAINST (‘$qstring’) ….

Con ello obtenemos un listado de registros en los cuales el $qstring aparezca en alguno de los campos definidos en MATCH.

Además podemos obtener cual es el score, o la relevancia en cada uno de los registros obtenidos de la tabla, simplemente volvemos a poner en el SELECT de columnas MATCH ( campo1, campo2, campo3….) AGAINST (‘$qstring’) as relevancia y en relevancia obtenemos dicho valor, asique podriamos ordenar la consulta por esta columna: ORDER BY relevancia. Ejemplo:

SELECT *, MATCH ( campo1, campo2, campo3….) AGAINST (‘$qstring’) as relevancia
FROM tabla
WHERE
MATCH ( campo1, campo2, campo3….) AGAINST (‘$qstring’)
ORDER BY relevancia;

Tenemos ademas dos modificadores para indicarle a Mysql como se analizará el string dado,

IN BOOLEAN MODE:

Especifica que deberá realizarse una búsqueda booleana, el texto puede contener operadores que indiquen que una palabra no este presente o por el contrario que si deba estar una palabra en todos los resultados que se obtengan. Además se puede indicar una ponderación especial para una palabra, al igual que lo hacemos en Google.

Ejemplos:

+hola indica que la palabra hola debe estar en los resultados siempre.
-por indica que la palabra por es una palabra sin importancia (stopword)
~noquiero indica que la palabra noquiero no debe estar en los resultados obtenidos.

WITH QUERY EXPANSION:

Se realizan dos búsquedas, en la primera se determinan las palabras mas relevantes de las filas encontradas, y en la segunda se agregan dichas palabras a la cadena a buscar. Se retorna el resultado de la segunda búsqueda.

Ejemplo:

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

Archivado en: General, Mysql, PHP   |  21 Comentarios

21 comentarios a “Utilizando MATCH … AGAINST en MySQL | Buscador PHP simple, utilizando funcionalidades de MySQL”  

Feed de este artículo URI para Trackbacks
  1. 1 fernanDj en Jul 13th, 2011 dijo:

    Este tema me sirvió de mucho para resolver una tarea de curso.

    Garcias por lo expuensto en este foro.

    Soy estudiante de Ciencias de la Computación 4to Año

  2. 2 ddicami en Jul 13th, 2011 dijo:

    Me alegra mucho. Esto no es un foro es mi blog personal donde comparto parte de mi trabajo.

  3. 3 Manu en Ago 11th, 2011 dijo:

    Hola queria hacer una pregunta ¿aprox cuanto debe valer la prioridad para que un resultado se considere relevante?

  4. 4 ddicami en Ago 11th, 2011 dijo:

    En este ejemplo :

    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

    estoy tomando relevancias > a 0.2

  5. 5 Mianovag en Oct 27th, 2011 dijo:

    me gustaria sabes como aplicar este script para hacer una busqueda simple ejemplo:

    cien años de soledad ( busqueda referencial)

    dato ingresado para la busqueda : años soledad

    sera muy dificil?

  6. 6 ddicami en Oct 27th, 2011 dijo:

    Hola, debes realizar los pasos del post en tu base de datos en la/s tabla/s donde realizaras busquedas. Supongamos la tabla libros

    el $qstring = «años soledad»

    Luego haces la consulta como figura en el post y por ultimo solo recorres el resultado de mysql que contendra los resultados de la busqueda.

    Como dice el post , te evita programacion PHP porque la funcion viene built-in en el motor de mysql.

    Un saludo

  7. 7 alcas en Nov 26th, 2011 dijo:

    saludos…..me he dado cuenta que usando el WHERE MATCH ( campo1, campo2, campo3….) AGAINST (‘$qstring’) …. al momento de paginar la primera pagina la muestra bien, pero cuando paso a la segunda esta vacia, tomando en cuenta que no deberia dar el enlace de una segunda pagina puesto que no hay mas registros que mostrar….

  8. 8 ddicami en Nov 26th, 2011 dijo:

    Si el query a la base de datos es el mismo, MAS QUE SEGURO tienes un error en tu paginador y el error esta entre La cantidad total de resultados obtenidos y el resultado de filas para una pagina

  9. 9 alcas en Nov 29th, 2011 dijo:

    nada, fijate, con el select tradicional funciona bien todo el paginador, en el momoento que cambio ese select tradicional al match vienen los problemas…..

  10. 10 ddicami en Nov 30th, 2011 dijo:

    Debes verificar que en la base de datos hayas creado los indices tipo TEXT
    Lo tengo en uso en varios sitios y funciona a la perfeccion.

  11. 11 jorge ramiro en Feb 20th, 2012 dijo:

    bueno espero me puedan ayudar
    tengo una tabla pero cuando se repiten los resultados me reotorna un valor vacio, no se que sea

    CREATE TABLE IF NOT EXISTS `libro` (
    `id_libro` int(255) NOT NULL AUTO_INCREMENT,
    `num_tarjeta` varchar(255) NOT NULL,
    `autores` text NOT NULL,
    `titulos` text NOT NULL,
    `temas` varchar(255) NOT NULL,
    `ejem_vol` varchar(255) NOT NULL,
    `clasificacion` varchar(255) NOT NULL,
    `clasificacion_nombre` text NOT NULL,
    `tipo` varchar(255) NOT NULL,
    `tipo_letra` varchar(30) NOT NULL,
    `ubicacion` varchar(255) NOT NULL,
    `adquisicion` int(255) NOT NULL DEFAULT ‘-1’,
    `estado_prestamo` varchar(100) NOT NULL,
    PRIMARY KEY (`id_libro`),
    FULLTEXT KEY `titulos` (`titulos`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

    —
    — Volcar la base de datos para la tabla `libro`
    —

    INSERT INTO `libro` (`id_libro`, `num_tarjeta`, `autores`, `titulos`, `temas`, `ejem_vol`, `clasificacion`, `clasificacion_nombre`, `tipo`, `tipo_letra`, `ubicacion`, `adquisicion`, `estado_prestamo`) VALUES
    (1, ‘2323’, ‘reynonso’, ‘ok matematicas 2’, ‘l,l, l,l,l,, ‘, ‘l,22’, ‘99.23 b34’, ‘GEOGRAFIA E HISTORIA’, ‘biblioteca’, ‘b’, ‘consulta GENERAL parte ALTA’, 1212121, ‘disponible’),
    (2, ‘okoko’, ‘jorge’, ‘kmkm’, ‘kmkm’, ‘kmkm’, ‘km’, », ‘biblioteca’, ‘b’, ‘sala 1’, 1212, ‘disponible’),
    (3, ‘sin’, ‘jorge ‘, ‘matematicas para computadoras’, ‘okas’, ‘121’, ‘34.24’, ‘CIENCIAS SOCIALES’, ‘biblioteca’, ‘b’, ‘consulta GENERAL parte ALTA’, 121212, ‘disponible’),
    (4, ‘ok’, ‘o’, ‘kook’, ‘ok’, ‘o’, ‘22.989 mcs 1’, », ‘biblioteca’, ‘b’, ‘consulta GENERAL parte ALTA’, 1221, ‘disponible’);

    mi consulta es
    select id_libro, num_tarjeta, autores, titulos, temas, ejem_vol, clasificacion, clasificacion_nombre, ubicacion,adquisicion, estado_prestamo from libro where MATCH(titulos) AGAINST(‘matematicas’)

  12. 12 jorge ramiro en Feb 20th, 2012 dijo:

    bueno de lo que tengo ahi se supone que me tiene k retornar «matematicas 2» y «matematicas para computadoras»

  13. 13 ddicami en Feb 20th, 2012 dijo:

    Hola, en la tabla libro has creado el indice FULLTEXT antes de anadir los datos de INSERT ?

    1.- Debemos crear un indice de tipo FULLTEXT en los campos de la tabla (estos campos deben ser de tipo char, Text o Varchar, llamemoslos campo1, campo2, campo3….) donde realizaremos la búsqueda. Para ello con acceder a un phpMyAdmin vas a la parte de inserción de indices (seleccionando primero la tabla donde se insertará).

    En tu caso deberia ser sobre la col «titulos»

  14. 14 Diego L en Ago 9th, 2012 dijo:

    Hola, estoy realizando un sitio, y estoy con un inconveniente en los resultados.

    Aquí le pongo la parte del buscador.

    $querycosa = mysql_query(«SELECT * FROM markers WHERE MATCH(direccion) AGAINST (‘$search’) ORDER BY RAND() DESC LIMIT 0 , 5»);

    Tengo una serie de direcciones de clientes y deseo que me entregue el buscador la dirección correcta. Por ejemplo, tengo un cliente en san martín 652, pero si coloco san martin 650, directamente me trae otras direcciones de la calle san martín, ejemplo san martín 250, san martín 800, etc.

    Ese es un problema, el otro es si coloco una intersección, ejemplo san martín y pellegrini, directamente me entrega por ejemplo: san martín 420, san martín 800, pellegrini 800 y no la que deseo que sea san martín y pellegrini que por cierto está en la base de datos.

    Realmente mucha idea no tengo de mysql, por eso les escribo para que me puedan explicar que estoy haciendo mal.

    Muchas gracias!!

  15. 15 ferbal en Oct 6th, 2012 dijo:

    JaJa! Se desvio mal esto. Se pensaron que era un foro y empezaron a mandar codigo.
    Muy bueno el post, y el blog en general.. muy completo.
    Me sirvio para entender mejor las busquedas.
    Muchas gracias!

  16. 16 PeriLoco en Sep 16th, 2013 dijo:

    Hola
    todo me lo hace bien, pero cuando hago la búsqueda el ID que me muestras siempre es uno, de manera que no puedo linkar con una ficha de cada registro

  17. 17 ddicami en Sep 16th, 2013 dijo:

    Cuidado de no usar GROUP BY en el query.
    Tiene que retornar un SET de registros como cualquier query Select. Funciona de maravilla.

  18. 18 Ricardo en May 7th, 2014 dijo:

    Buen dato, muchas gracias te pago con un click en tu banner….

  19. 19 Gustavo en Oct 18th, 2016 dijo:

    Hola gente, gracias por del MATCH AGAINST!
    Lo estoy probando y tengo problemas con los tildes. He agregado «COLLATE utf8_general_ci» que funciona bien cuando la búsqueda es con LIKE, pero cuando uso MATCH AGAINST no devuelve nada, tanto si la palabra buscada es con o sin tilde 🙁
    Les agradezco si me pueden dar una mano.
    Saludos.

  1. 1 MySQL, MATCH AGAINST LIKE o Texto parcial | Diego Di Camillo
  2. 2 MATCH AGAINST MYSQL | NOT MATCH PHRASES SHORTS USING “*” IN BOOLEAN MODE | Diego Di Camillo
Enviando tu Comentario
Por favor espera

Deja una respuesta

Hubo un error con tu comentario, por favor intenta de nuevo.



Comparte este artículo

  • Menéame  Menéalo
  • del.icio.us  Enviar a Del.icio.us
  • Mi Yahoo!  Agregar a Mi Web 2.0
  • Furl  Guardar en Furl
 


wordpressk2openswitchyukei.netfeedwordpress