Utilizando MATCH … AGAINST en MySQL | Buscador PHP simple, utilizando funcionalidades de MySQL
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
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
Me alegra mucho. Esto no es un foro es mi blog personal donde comparto parte de mi trabajo.
Hola queria hacer una pregunta ¿aprox cuanto debe valer la prioridad para que un resultado se considere relevante?
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
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?
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
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….
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
nada, fijate, con el select tradicional funciona bien todo el paginador, en el momoento que cambio ese select tradicional al match vienen los problemas…..
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.
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’)
bueno de lo que tengo ahi se supone que me tiene k retornar «matematicas 2» y «matematicas para computadoras»
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»
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!!
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!
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
Cuidado de no usar GROUP BY en el query.
Tiene que retornar un SET de registros como cualquier query Select. Funciona de maravilla.
Buen dato, muchas gracias te pago con un click en tu banner….
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.