Manticore Search es un motor de búsqueda de texto completo de código abierto, heredero de Sphinx, que se consulta con SQL a través del protocolo de MySQL o con JSON a través de HTTP. Eso permite conectarte con el cliente mysql de siempre o con cualquier librería MySQL para crear tablas, insertar documentos y buscar. En este tutorial instalarás Manticore Search desde su repositorio oficial en Ubuntu 24.04, crearás una tabla en tiempo real con análisis de texto en español y harás búsquedas con filtros, facetas y resaltado de términos.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Al menos 1 GB de RAM (2 GB o más para índices grandes) y espacio en disco acorde a tus datos.
Manticore escucha por defecto solo en 127.0.0.1, así que no hace falta abrir puertos para seguir esta guía. Usa tres puertos:
| Puerto | Protocolo | Uso |
|---|---|---|
| 9306 | MySQL | Consultas SQL con cualquier cliente MySQL |
| 9308 | HTTP | API JSON y endpoint /sql |
| 9312 | Binario | Protocolo nativo, usado entre nodos y por clientes antiguos de Sphinx |
Paso 1: Añadir el repositorio de Manticore
Manticore distribuye un pequeño paquete que configura su repositorio APT e instala la clave de firma en /usr/share/keyrings. Descárgalo e instálalo:
cd /tmp
wget https://repo.manticoresearch.com/manticore-repo.noarch.deb
sudo dpkg -i manticore-repo.noarch.deb
sudo apt update
Comprueba que APT ya ve los paquetes de Manticore:
apt-cache policy manticore
La salida debe mostrar una versión candidata procedente de repo.manticoresearch.com.
Paso 2: Instalar e iniciar Manticore Search
Instala el servidor junto con la librería columnar, que añade el almacenamiento columnar y los índices secundarios que aceleran los filtros:
sudo apt install manticore manticore-columnar-lib
El servicio no arranca automáticamente tras la instalación. Habilítalo e inícialo:
sudo systemctl enable --now manticore
Comprueba que está activo y escuchando en los tres puertos:
sudo systemctl status manticore
sudo ss -tlnp | grep searchd
LISTEN 0 4096 127.0.0.1:9306 0.0.0.0:* users:(("searchd",pid=5312,fd=12))
LISTEN 0 4096 127.0.0.1:9308 0.0.0.0:* users:(("searchd",pid=5312,fd=13))
LISTEN 0 4096 127.0.0.1:9312 0.0.0.0:* users:(("searchd",pid=5312,fd=11))
Paso 3: Revisar la configuración
La configuración está en /etc/manticoresearch/manticore.conf. Muéstrala:
cat /etc/manticoresearch/manticore.conf
Verás un bloque searchd parecido a este:
searchd {
listen = 127.0.0.1:9312
listen = 127.0.0.1:9306:mysql
listen = 127.0.0.1:9308:http
log = /var/log/manticore/searchd.log
query_log = /var/log/manticore/query.log
pid_file = /run/manticore/searchd.pid
data_dir = /var/lib/manticore
}
La directiva data_dir activa el modo RT (en tiempo real): las tablas se crean y modifican con sentencias SQL como CREATE TABLE y Manticore guarda su definición en ese directorio, sin tocar el archivo de configuración. Es el modo recomendado para aplicaciones nuevas y el que usarás en esta guía.
Si más adelante otra máquina necesita conectarse, cambia 127.0.0.1 por la IP privada del servidor en las líneas listen y permite el acceso solo desde esa máquina con UFW, por ejemplo sudo ufw allow from 10.0.0.5 to any port 9306 proto tcp. Manticore no tiene autenticación propia, así que nunca expongas estos puertos a Internet.
Paso 4: Conectarte con el cliente MySQL
Instala el cliente de MySQL:
sudo apt install mysql-client
Conéctate al puerto SQL de Manticore. No necesita usuario ni contraseña:
mysql -h 127.0.0.1 -P 9306
Comprueba que todo responde listando las tablas, que de momento no existen:
SHOW TABLES;
Empty set (0.00 sec)
Todas las sentencias SQL de los siguientes pasos se ejecutan dentro de esta sesión.
Paso 5: Crear una tabla en tiempo real
Crea una tabla de productos. Los campos text son los que se indexan para búsqueda de texto completo; el resto son atributos que sirven para filtrar, ordenar y agrupar. morphology = 'libstemmer_es' aplica el stemmer de español, de modo que "zapatilla" y "zapatillas" se consideran la misma palabra, y min_prefix_len = '3' permite buscar por prefijo con un asterisco (zapat*):
CREATE TABLE productos (
nombre text,
descripcion text,
categoria string,
marca string,
precio float,
stock integer,
activo bool
) morphology = 'libstemmer_es' min_prefix_len = '3';
Comprueba la estructura:
DESCRIBE productos;
+-------------+--------+----------------+
| Field | Type | Properties |
+-------------+--------+----------------+
| id | bigint | |
| nombre | text | indexed stored |
| descripcion | text | indexed stored |
| categoria | string | |
| marca | string | |
| precio | float | |
| stock | uint | |
| activo | bool | |
+-------------+--------+----------------+
El campo id se añade automáticamente. Los campos de texto son stored, lo que significa que Manticore guarda también el texto original y puede devolverlo en los resultados.
Paso 6: Insertar y modificar documentos
Inserta varios productos. Si no indicas un id, Manticore genera uno único:
INSERT INTO productos (id, nombre, descripcion, categoria, marca, precio, stock, activo) VALUES
(1, 'Camiseta básica de algodón', 'Camiseta unisex de algodón 100% en varios colores', 'Ropa', 'BasicWear', 19.99, 150, 1),
(2, 'Zapatillas de running', 'Zapatillas ligeras para correr con amortiguación', 'Calzado', 'SpeedRun', 89.99, 45, 1),
(3, 'Zapatillas de montaña', 'Calzado resistente para senderismo y trail', 'Calzado', 'TrailPro', 119.00, 12, 1),
(4, 'Sudadera deportiva', 'Sudadera de algodón con capucha para entrenar', 'Ropa', 'SpeedRun', 39.90, 0, 0);
Query OK, 4 rows affected (0.00 sec)
Los documentos se pueden buscar en cuanto termina el INSERT. Para cambiar atributos (precio, stock, estado) usa UPDATE, que es inmediato:
UPDATE productos SET precio = 17.99, stock = 200 WHERE id = 1;
Los campos de texto no se pueden modificar con UPDATE. Para cambiarlos, sustituye el documento completo con REPLACE, que tiene la misma sintaxis que INSERT. Para borrar, usa DELETE FROM productos WHERE id = 4;.
Paso 7: Buscar con texto completo y filtros
La búsqueda de texto completo se hace con MATCH() dentro del WHERE, y se puede combinar con filtros sobre atributos. WEIGHT() devuelve la puntuación de relevancia:
SELECT id, nombre, precio, WEIGHT() AS relevancia
FROM productos
WHERE MATCH('zapatilla') AND activo = 1 AND precio < 100
ORDER BY relevancia DESC;
+------+-----------------------+-----------+------------+
| id | nombre | precio | relevancia |
+------+-----------------------+-----------+------------+
| 2 | Zapatillas de running | 89.989998 | 2552 |
+------+-----------------------+-----------+------------+
Aunque buscaste "zapatilla" en singular, el stemmer encuentra "Zapatillas". El producto 3 también coincide, pero el filtro de precio lo excluye.
El lenguaje de consulta de MATCH() admite operadores para búsquedas más precisas:
| Consulta | Significado |
|---|---|
MATCH('@nombre camiseta') | Busca solo en el campo nombre |
MATCH('algodón -sudadera') | Contiene "algodón" pero no "sudadera" |
MATCH('running | trail') | Contiene cualquiera de las dos palabras |
MATCH('"zapatillas running"~3') | Las dos palabras a menos de 3 posiciones |
MATCH('zapat*') | Palabras que empiezan por "zapat" |
Paso 8: Facetas y resaltado de resultados
Las facetas devuelven, junto con los resultados, cuántos documentos hay por cada valor de un atributo. Es lo que alimenta los filtros laterales de una tienda. Cada FACET genera un conjunto de resultados adicional:
SELECT id, nombre, precio FROM productos WHERE MATCH('algodón | zapatillas')
FACET categoria ORDER BY COUNT(*) DESC
FACET marca;
+------+-----------------------------+-----------+
| id | nombre | precio |
+------+-----------------------------+-----------+
...
+-----------+----------+
| categoria | count(*) |
+-----------+----------+
| Calzado | 2 |
| Ropa | 2 |
+-----------+----------+
...
HIGHLIGHT() devuelve fragmentos del texto original con los términos buscados marcados, listos para mostrar en una página de resultados:
SELECT id, HIGHLIGHT({before_match='<b>', after_match='</b>'}, 'descripcion') AS fragmento
FROM productos
WHERE MATCH('algodón');
+------+------------------------------------------------------------+
| id | fragmento |
+------+------------------------------------------------------------+
| 1 | Camiseta unisex de <b>algodón</b> 100% en varios colores |
| 4 | Sudadera de <b>algodón</b> con capucha para entrenar |
+------+------------------------------------------------------------+
Sal del cliente con exit.
Paso 9: Consultar desde la API HTTP
Si tu aplicación no usa una librería MySQL, puedes usar la API JSON del puerto 9308. Esta petición equivale a una búsqueda de "zapatillas" con un filtro de precio:
curl -s http://127.0.0.1:9308/search -d '{
"table": "productos",
"query": {
"bool": {
"must": [{"match": {"*": "zapatillas"}}],
"filter": [{"range": {"precio": {"lte": 150}}}]
}
},
"limit": 10
}'
La respuesta sigue un formato parecido al de Elasticsearch, con los documentos en hits.hits y el total en hits.total. También puedes enviar SQL directamente por HTTP con el endpoint /sql:
curl -s "http://127.0.0.1:9308/sql?mode=raw" -d "SELECT COUNT(*) FROM productos"
Solución de problemas
El servicio no arranca. Revisa el log de Manticore y el de systemd:
sudo tail -n 50 /var/log/manticore/searchd.log
sudo journalctl -u manticore -n 50 --no-pager
Un error de sintaxis en manticore.conf aparece al principio del log con el número de línea. Si has cambiado las líneas listen, comprueba que no hay otro proceso usando esos puertos con sudo ss -tlnp.
ERROR 2003 (HY000): Can't connect to MySQL server. Comprueba que indicas el puerto 9306 con -P 9306 y la IP 127.0.0.1. Si escribes localhost, el cliente intenta usar un socket Unix en lugar de TCP.
Una búsqueda por prefijo no devuelve resultados. MATCH('zap*') solo funciona si la tabla tiene min_prefix_len o min_infix_len y el prefijo es al menos igual de largo que ese valor. Estos ajustes se aplican al indexar, así que cambiarlos en una tabla existente requiere volver a insertar los datos.
La tabla crece mucho tras muchas escrituras. Las tablas RT se compactan solas en segundo plano. Puedes consultar su estado con SHOW TABLE productos STATUS; y forzar una compactación con OPTIMIZE TABLE productos;.
Conclusión
Tienes Manticore Search funcionando en Ubuntu 24.04 con una tabla en tiempo real, análisis de texto en español y consultas con filtros, facetas y resaltado, tanto por SQL como por HTTP. Como siguientes pasos, puedes conectar tu aplicación mediante su librería MySQL habitual, importar datos existentes de MySQL o PostgreSQL con la herramienta indexer, o crear un clúster con replicación entre varios nodos para alta disponibilidad.
