Instalación y Configuración de Meilisearch
Meilisearch es un motor de búsqueda de código abierto ultrarrápido que ofrece búsqueda instantánea con tolerancia a errores tipográficos, búsqueda en tiempo real mientras se escribe y una API REST sencilla. Diseñado para ser fácil de integrar, ofrece resultados en menos de 50ms incluso con millones de documentos, soporta búsqueda multilingüe y permite personalizar la relevancia sin conocimientos avanzados de motores de búsqueda. Esta guía cubre la instalación en Linux, gestión de índices, configuración de búsqueda y despliegue en producción.
Requisitos Previos
- Ubuntu 20.04/22.04, Debian 11+ o CentOS 8+/Rocky Linux 8+
- 512 MB de RAM mínimo (Meilisearch mantiene los índices en memoria)
- Espacio en disco suficiente para los datos (los índices pueden ser 2-3x el tamaño de los datos originales)
- Puerto 7700 disponible
Instalación de Meilisearch
Instalación con el script oficial
# Descargar e instalar el binario directamente
curl -L https://install.meilisearch.com | sh
# Verificar la instalación
./meilisearch --version
# Mover el binario al PATH del sistema
sudo mv meilisearch /usr/local/bin/
Instalación manual del binario
# Descargar la versión más reciente
MEILISEARCH_VERSION=1.7.3
wget "https://github.com/meilisearch/meilisearch/releases/download/v${MEILISEARCH_VERSION}/meilisearch-linux-amd64" \
-O meilisearch
# Hacer el binario ejecutable
chmod +x meilisearch
sudo mv meilisearch /usr/local/bin/
# Verificar
meilisearch --version
Instalación con Docker
docker run -d \
--name meilisearch \
-p 7700:7700 \
-e MEILI_MASTER_KEY="tu_clave_maestra_segura" \
-v meilisearch-data:/meili_data \
getmeili/meilisearch:v1.7.3
Configuración del Servidor
# Crear usuario y directorios para Meilisearch
sudo useradd -r -s /bin/false meilisearch
sudo mkdir -p /var/lib/meilisearch /etc/meilisearch /var/log/meilisearch
sudo chown -R meilisearch:meilisearch /var/lib/meilisearch /var/log/meilisearch
Crea el archivo de configuración /etc/meilisearch/config.toml:
# /etc/meilisearch/config.toml
# Directorio donde se almacenan los datos del índice
db_path = "/var/lib/meilisearch/data"
# Entorno: "development" (sin clave maestra) o "production" (clave maestra obligatoria)
env = "production"
# Clave maestra para autenticación (mínimo 16 caracteres)
master_key = "tu_clave_maestra_super_secreta_aqui"
# Puerto y dirección de escucha
http_addr = "127.0.0.1:7700"
# Directorio para dumps (exportaciones)
dump_dir = "/var/lib/meilisearch/dumps"
# Directorio para snapshots
snapshot_dir = "/var/lib/meilisearch/snapshots"
# Intervalo de snapshots automáticos (en segundos)
schedule_snapshot = 86400 # Cada 24 horas
# Nivel de log: off, error, warn, info, debug, trace
log_level = "info"
# Límite de tamaño para la base de datos LMDB (en bytes)
max_index_size = 107374182400 # 100 GB
# Tamaño máximo del payload de importación (en bytes)
http_payload_size_limit = 104857600 # 100 MB
# Crear el servicio systemd
sudo tee /etc/systemd/system/meilisearch.service > /dev/null <<EOF
[Unit]
Description=Meilisearch Search Engine
After=network.target
[Service]
Type=simple
User=meilisearch
Group=meilisearch
ExecStart=/usr/local/bin/meilisearch --config-file-path=/etc/meilisearch/config.toml
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/meilisearch/meilisearch.log
StandardError=append:/var/log/meilisearch/meilisearch.log
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable meilisearch --now
# Verificar el estado
sudo systemctl status meilisearch
# Probar la API
curl http://localhost:7700/health
Gestión de Índices
# Variable con la clave maestra
export MEILI_KEY="tu_clave_maestra_super_secreta_aqui"
export MEILI_URL="http://localhost:7700"
# Crear un índice
curl -X POST "${MEILI_URL}/indexes" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
-d '{
"uid": "productos",
"primaryKey": "id"
}'
# Listar índices
curl "${MEILI_URL}/indexes" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Ver información de un índice
curl "${MEILI_URL}/indexes/productos" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Eliminar un índice
curl -X DELETE "${MEILI_URL}/indexes/productos" \
-H "Authorization: Bearer ${MEILI_KEY}"
Indexación de Documentos
# Añadir documentos individuales o en lote
curl -X POST "${MEILI_URL}/indexes/productos/documents" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
-d '[
{
"id": 1,
"nombre": "Camiseta básica algodón",
"descripcion": "Camiseta unisex de algodón 100% en varios colores",
"categoria": "Ropa",
"precio": 19.99,
"stock": 150,
"etiquetas": ["ropa", "casual", "algodón"]
},
{
"id": 2,
"nombre": "Zapatillas deportivas running",
"descripcion": "Zapatillas ligeras para correr con amortiguación extra",
"categoria": "Calzado",
"precio": 89.99,
"stock": 45,
"etiquetas": ["deporte", "running", "calzado"]
}
]'
# Las operaciones de indexación son asíncronas - verificar el estado de la tarea
curl "${MEILI_URL}/tasks" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Ver el estado de una tarea específica
curl "${MEILI_URL}/tasks/1" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Importación masiva desde un archivo JSON
curl -X POST "${MEILI_URL}/indexes/productos/documents" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
--data-binary @/tmp/productos.json
# Actualizar documentos (los campos no mencionados se mantienen)
curl -X PATCH "${MEILI_URL}/indexes/productos/documents" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
-d '[{"id": 1, "precio": 15.99, "stock": 200}]'
# Eliminar documentos por ID
curl -X DELETE "${MEILI_URL}/indexes/productos/documents/1" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Eliminar todos los documentos de un índice (sin borrar el índice)
curl -X DELETE "${MEILI_URL}/indexes/productos/documents" \
-H "Authorization: Bearer ${MEILI_KEY}"
Búsqueda y Personalización
# Búsqueda básica
curl "${MEILI_URL}/indexes/productos/search?q=zapatillas" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Búsqueda avanzada con parámetros
curl -X POST "${MEILI_URL}/indexes/productos/search" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
-d '{
"q": "zapatillas deporte",
"limit": 20,
"offset": 0,
"filter": "categoria = Calzado AND precio < 100",
"sort": ["precio:asc"],
"facets": ["categoria", "etiquetas"],
"attributesToHighlight": ["nombre", "descripcion"],
"highlightPreTag": "<strong>",
"highlightPostTag": "</strong>",
"attributesToCrop": ["descripcion"],
"cropLength": 100
}'
Configurar atributos de búsqueda
# Definir qué campos son buscables y cuáles son filtrables
curl -X PATCH "${MEILI_URL}/indexes/productos/settings" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
-d '{
"searchableAttributes": [
"nombre",
"descripcion",
"etiquetas",
"categoria"
],
"filterableAttributes": [
"categoria",
"precio",
"stock",
"etiquetas"
],
"sortableAttributes": [
"precio",
"stock"
],
"rankingRules": [
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness",
"precio:asc"
],
"stopWords": ["el", "la", "los", "las", "un", "una", "y", "o", "de", "del", "en"],
"synonyms": {
"zapatillas": ["tenis", "sneakers", "deportivas"],
"camiseta": ["remera", "playera", "polo"]
},
"typoTolerance": {
"enabled": true,
"minWordSizeForTypos": {
"oneTypo": 5,
"twoTypos": 9
}
}
}'
Claves de API y Seguridad
# Crear una clave de solo lectura para el frontend
curl -X POST "${MEILI_URL}/keys" \
-H "Authorization: Bearer ${MEILI_KEY}" \
-H "Content-Type: application/json" \
-d '{
"description": "Clave de búsqueda pública para el sitio web",
"actions": ["search"],
"indexes": ["productos"],
"expiresAt": "2025-12-31T00:00:00Z"
}'
# Listar todas las claves
curl "${MEILI_URL}/keys" \
-H "Authorization: Bearer ${MEILI_KEY}"
Despliegue en Producción
Configurar Nginx como proxy inverso
# /etc/nginx/sites-available/meilisearch
server {
listen 443 ssl;
server_name busqueda.tudominio.com;
ssl_certificate /etc/letsencrypt/live/busqueda.tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/busqueda.tudominio.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:7700;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
# Solo permitir operaciones de búsqueda desde el exterior
# Bloquear endpoints de administración
location ~* ^/(indexes|tasks|keys|dumps|snapshots|settings) {
if ($request_method != GET) {
return 403;
}
}
}
}
Crear un dump (exportación de datos)
# Crear un dump para backup o migración
curl -X POST "${MEILI_URL}/dumps" \
-H "Authorization: Bearer ${MEILI_KEY}"
# Los dumps se guardan en dump_dir configurado
ls -la /var/lib/meilisearch/dumps/
# Importar un dump al iniciar Meilisearch
meilisearch --import-dump /var/lib/meilisearch/dumps/20240115-backup.dump
Solución de Problemas
Meilisearch no arranca:
# Verificar logs
sudo journalctl -u meilisearch -n 50 --no-pager
cat /var/log/meilisearch/meilisearch.log | tail -50
# Verificar permisos del directorio de datos
ls -la /var/lib/meilisearch/
sudo chown -R meilisearch:meilisearch /var/lib/meilisearch/
Error "Invalid API key":
# En modo producción (env=production), la clave maestra es obligatoria
# Verificar que se está usando la clave correcta
curl "${MEILI_URL}/health" -H "Authorization: Bearer ${MEILI_KEY}"
# Si cambias la clave maestra, los índices existentes permanecen pero las claves anteriores dejan de funcionar
La indexación es lenta:
# Aumentar el límite de payload para importaciones masivas
# En config.toml:
http_payload_size_limit = 209715200 # 200 MB
# Importar en lotes de 50.000-100.000 documentos máximo
# Dividir archivos grandes con split o similar
split -l 50000 datos_grandes.json partes/datos_
Los resultados de búsqueda no son los esperados:
# Verificar la configuración de atributos buscables
curl "${MEILI_URL}/indexes/productos/settings" \
-H "Authorization: Bearer ${MEILI_KEY}" | python3 -m json.tool
# Revisar las ranking rules configuradas
# Añadir sinónimos para términos del dominio
# Ajustar los pesos de los campos en searchableAttributes (el orden importa)
Conclusión
Meilisearch destaca por su facilidad de despliegue, su velocidad de búsqueda y una API intuitiva que permite a cualquier desarrollador integrar búsqueda avanzada en minutos. La configuración de atributos filtrables, ordenables y la personalización de la relevancia permiten construir experiencias de búsqueda sofisticadas sin necesidad de conocimientos especializados. Para producción, recuerda configurar siempre una clave maestra, usar un proxy inverso con HTTPS y programar dumps periódicos para la recuperación ante desastres.


