MATCH AGAINST
MATCH() AGAINST() es la sintaxis para realizar búsquedas full-text en MySQL. MATCH() especifica las columnas donde buscar y AGAINST() especifica el texto a buscar y el modo de búsqueda. Devuelve una puntuación de relevancia que indica qué tan bien coincide cada fila con la búsqueda.
Sintaxis
SELECT columnas
FROM tabla
WHERE MATCH(columna1, columna2) AGAINST('texto de búsqueda' modo);Los modos disponibles son:
| Modo | Descripción |
|---|---|
| Sin especificar | Lenguaje natural |
| IN NATURAL LANGUAGE MODE | Lenguaje natural |
| IN BOOLEAN MODE | Modo booleano con operadores |
| WITH QUERY EXPANSION | Expansión de consulta |
Preparación
Para los ejemplos de esta sección, creamos los índices full-text:
CREATE FULLTEXT INDEX ft_productos ON productos (nombre, descripcion);
CREATE FULLTEXT INDEX ft_resenas ON resenas (comentario);Búsqueda básica
SELECT nombre, precio
FROM productos
WHERE MATCH(nombre, descripcion) AGAINST('smartphone cámara');| nombre | precio |
|---|---|
| iPhone 15 Pro | 1299.99 |
| Samsung Galaxy S24 | 899.99 |
| Google Pixel 8 | 699.00 |
| Xiaomi 14 | 599.99 |
MySQL busca las palabras "smartphone" y "cámara" en las columnas nombre y descripcion, y devuelve las filas que contienen al menos una de ellas, ordenadas por relevancia.
Puntuación de relevancia
MATCH() AGAINST() en el SELECT devuelve un número decimal que indica la relevancia:
SELECT
nombre,
MATCH(nombre, descripcion) AGAINST('smartphone cámara') AS relevancia
FROM productos
WHERE MATCH(nombre, descripcion) AGAINST('smartphone cámara')
ORDER BY relevancia DESC;| nombre | relevancia |
|---|---|
| iPhone 15 Pro | 0.6842 |
| Samsung Galaxy S24 | 0.4521 |
| Google Pixel 8 | 0.3218 |
| Xiaomi 14 | 0.2987 |
Un valor mayor indica mayor relevancia. El cálculo considera la frecuencia de las palabras, su rareza en el conjunto de datos y la longitud del documento.
MATCH en WHERE y SELECT
Puedes usar MATCH() AGAINST() tanto en WHERE como en SELECT. MySQL optimiza esto para evaluar la expresión solo una vez:
SELECT
nombre,
precio,
MATCH(nombre, descripcion) AGAINST('gaming') AS relevancia
FROM productos
WHERE MATCH(nombre, descripcion) AGAINST('gaming')
ORDER BY relevancia DESC;| nombre | relevancia |
|---|---|
| ASUS ROG Zephyrus | 0.7234 |
Combinar con otras condiciones
-- Full-text con filtro de precio
SELECT nombre, precio
FROM productos
WHERE MATCH(nombre, descripcion) AGAINST('portátil')
AND precio < 1500;| nombre | precio |
|---|---|
| MacBook Air M3 | 1399.00 |
-- Full-text con JOIN
SELECT
p.nombre AS producto,
r.comentario,
r.puntuacion,
MATCH(r.comentario) AGAINST('bueno') AS relevancia
FROM resenas r
JOIN productos p ON r.producto_id = p.id
WHERE MATCH(r.comentario) AGAINST('bueno')
ORDER BY relevancia DESC;MATCH con ORDER BY
Si usas MATCH() AGAINST() solo en el SELECT sin WHERE, MySQL no filtra pero puedes ordenar por relevancia:
SELECT
nombre,
MATCH(nombre, descripcion) AGAINST('cocina') AS relevancia
FROM productos
ORDER BY relevancia DESC
LIMIT 5;| nombre | relevancia |
|---|---|
| Robot de cocina | 0.8456 |
| Sartén antiadherente 28cm | 0.3124 |
| iPhone 15 Pro | 0.0000 |
| Samsung Galaxy S24 | 0.0000 |
| Google Pixel 8 | 0.0000 |
Sin WHERE, todas las filas se devuelven, pero las que contienen el término tienen relevancia mayor que cero.
Limitaciones de MATCH AGAINST
- Las columnas en
MATCH()deben coincidir exactamente con las de un índiceFULLTEXT - No puedes mezclar columnas de diferentes tablas en un solo
MATCH() - La puntuación de relevancia no es comparable entre diferentes consultas
- Las palabras más cortas que
innodb_ft_min_token_sizese ignoran
Limpieza
DROP INDEX ft_productos ON productos;
DROP INDEX ft_resenas ON resenas;En el siguiente artículo profundizaremos en la búsqueda en lenguaje natural, el modo por defecto de las búsquedas full-text.
Escrito por Eduardo Lázaro
