En muchos sitios web que usan MySQL, sobre todo aquellos que manejan nombres en español o portugués, es común tener problemas con búsquedas. Por ejemplo, un usuario busca “camion"
y no encuentra “camión
“, o escribe “cafetera"
y no aparece “cafétera
“.
En este artículo aprenderás cómo configurar tu base de datos y tu código PHP para que las búsquedas:
- Sean insensibles a acentos y mayúsculas
- Usen
FULLTEXT
para mayor velocidad - Funcionen en bases de datos grandes
📦 Escenario: catálogo de productos
Supongamos que tenemos una tabla productos
así:
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(255) NOT NULL,
descripcion TEXT,
categoria VARCHAR(100),
precio DECIMAL(10,2),
FULLTEXT(nombre, descripcion)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
Problema: búsqueda con MATCH ... AGAINST
no encuentra “camión” si buscas “camion”
🚨 ¿Por qué sucede?
Aunque utf8mb3_unicode_ci
es insensible a acentos para comparaciones con LIKE
, no garantiza lo mismo para FULLTEXT
. Este índice crea un diccionario de términos tal como están escritos, por lo que “camión” y “camion” son palabras distintas.
✅ Solución 1: Migrar a utf8mb4_unicode_ci
El primer paso ideal es actualizar la tabla a utf8mb4
, que tiene mejor soporte para unicode y búsqueda:
ALTER TABLE productos CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Luego, recrea el índice FULLTEXT
para asegurarte de que se ajuste a la nueva codificación:
ALTER TABLE productos
DROP INDEX nombre,
ADD FULLTEXT(nombre, descripcion);
✅ Solución 2: Preprocesar el término de búsqueda en PHP
A pesar de tener la collation correcta, MySQL no siempre trata acentos como equivalentes en FULLTEXT
. Entonces, también debes normalizar el término de búsqueda desde el lado del servidor. En PHP:
function quitarAcentos($cadena) {
return iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $cadena);
}
$terminoBusqueda = 'camion'; // viene del usuario
$normalizado = quitarAcentos($terminoBusqueda);
🔍 Consulta optimizada con FULLTEXT
+ prioridad de categoría
Supongamos que quieres que los resultados de categoría "ofertas"
salgan primero:
SELECT id, nombre, descripcion, categoria, precio
FROM productos
WHERE MATCH(nombre, descripcion) AGAINST(:busqueda IN BOOLEAN MODE)
ORDER BY (categoria = 'ofertas') DESC, precio ASC
LIMIT 20;
Esto ordena los productos donde la categoría es 'ofertas'
primero, y luego por precio ascendente.
🧪 Alternativa sin FULLTEXT
(cuando hay pocos datos)
Si tu tabla es pequeña o temporalmente necesitas algo rápido, puedes usar LIKE
(aunque es más lento):
SELECT * FROM productos
WHERE nombre LIKE '%camion%' OR descripcion LIKE '%camion%';
Y puedes duplicar eso para considerar las versiones con y sin acento si no estás normalizando:
WHERE nombre LIKE '%camión%' OR nombre LIKE '%camion%'
📌 Conclusión
Para una búsqueda moderna y amigable:
- Usa
utf8mb4_unicode_ci
para buena compatibilidad internacional. - Usa
FULLTEXT
para rendimiento. - Normaliza los términos con PHP (
iconv
) para ignorar acentos. - Ajusta el
ORDER BY
según tus necesidades de negocio.
¡Así mejoras tanto la experiencia del usuario como el rendimiento de tu aplicación!
¿Qué opinas de esta solución? ¿La conocías?