Instalación y Configuración de Typesense
Typesense es un motor de búsqueda de código abierto, rápido y tolerante a errores tipográficos, diseñado para ofrecer experiencias de búsqueda instantánea en aplicaciones web y móviles. Con tiempos de respuesta por debajo de los 50ms, soporte para búsqueda facetada, geolocalización y una API sencilla compatible con múltiples lenguajes, Typesense es una alternativa ligera y fácil de gestionar a Elasticsearch o Algolia. Esta guía cubre la instalación en Linux, creación de colecciones, indexación de documentos y configuración avanzada de búsqueda.
Requisitos Previos
- Ubuntu 20.04/22.04, Debian 11+ o CentOS 8+/Rocky Linux 8+
- 1 GB de RAM mínimo (depende del tamaño del índice)
- 2 GB de espacio en disco
- Puerto 8108 disponible
Instalación de Typesense
Instalación con el script oficial
# Instalar usando el script de instalación oficial
curl -O https://dl.typesense.org/releases/0.25.2/typesense-server-0.25.2-linux-amd64.tar.gz
tar -xzf typesense-server-0.25.2-linux-amd64.tar.gz
# O instalar como paquete del sistema en Ubuntu/Debian
curl -sL https://dl.typesense.org/deb/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/typesense.gpg
echo "deb [signed-by=/usr/share/keyrings/typesense.gpg] https://dl.typesense.org/deb stable main" \
| sudo tee /etc/apt/sources.list.d/typesense.list
sudo apt update && sudo apt install -y typesense-server
Instalación en CentOS/Rocky
# Descargar el binario directamente
TYPESENSE_VERSION=0.25.2
wget https://dl.typesense.org/releases/${TYPESENSE_VERSION}/typesense-server-${TYPESENSE_VERSION}-linux-amd64.tar.gz
tar -xzf typesense-server-${TYPESENSE_VERSION}-linux-amd64.tar.gz
# Mover el binario al PATH del sistema
sudo mv typesense-server /usr/local/bin/
sudo chmod +x /usr/local/bin/typesense-server
Configuración Inicial
Crea el archivo de configuración en /etc/typesense/typesense-server.ini:
sudo mkdir -p /etc/typesense /var/lib/typesense /var/log/typesense
sudo useradd -r -s /bin/false typesense
sudo chown -R typesense:typesense /var/lib/typesense /var/log/typesense
; /etc/typesense/typesense-server.ini
[server]
; Directorio donde se almacenan los datos del índice
data-dir = /var/lib/typesense
; Clave API de administrador - cambiar por una clave aleatoria segura
api-key = TU_CLAVE_API_SECRETA_AQUI
; Dirección y puerto donde escucha el servidor
listen-address = 0.0.0.0
listen-port = 8108
; Habilitar CORS para peticiones desde el navegador
enable-cors = true
; Archivo de log
log-dir = /var/log/typesense
; Nivel de log: debug, info, warn, error
log-level = info
Crear el servicio systemd
sudo tee /etc/systemd/system/typesense.service > /dev/null <<EOF
[Unit]
Description=Typesense Search Engine
After=network.target
[Service]
Type=simple
User=typesense
Group=typesense
ExecStart=/usr/local/bin/typesense-server --config=/etc/typesense/typesense-server.ini
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable typesense --now
# Verificar que está corriendo
sudo systemctl status typesense
# Probar la API
curl http://localhost:8108/health
Crear Colecciones
Las colecciones en Typesense son equivalentes a las tablas en SQL o los índices en Elasticsearch. Cada colección tiene un schema definido:
# Variable con la clave API para no repetirla
export TYPESENSE_API_KEY="TU_CLAVE_API_SECRETA_AQUI"
# Crear una colección de productos
curl -X POST http://localhost:8108/collections \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{
"name": "productos",
"fields": [
{"name": "id", "type": "string"},
{"name": "nombre", "type": "string"},
{"name": "descripcion", "type": "string"},
{"name": "categoria", "type": "string", "facet": true},
{"name": "marca", "type": "string", "facet": true},
{"name": "precio", "type": "float"},
{"name": "stock", "type": "int32"},
{"name": "activo", "type": "bool", "index": true},
{"name": "etiquetas", "type": "string[]", "facet": true},
{"name": "ubicacion", "type": "geopoint", "optional": true}
],
"default_sorting_field": "precio"
}'
# Listar todas las colecciones
curl http://localhost:8108/collections \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
# Ver detalles de una colección
curl http://localhost:8108/collections/productos \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
# Eliminar una colección
curl -X DELETE http://localhost:8108/collections/productos \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
Indexar Documentos
# Indexar un documento individual
curl -X POST http://localhost:8108/collections/productos/documents \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{
"id": "prod-001",
"nombre": "Camiseta básica algodón",
"descripcion": "Camiseta de algodón 100% en varios colores",
"categoria": "Ropa",
"marca": "BasicWear",
"precio": 19.99,
"stock": 150,
"activo": true,
"etiquetas": ["ropa", "camiseta", "algodón", "basico"]
}'
# Importación masiva con JSONL (más eficiente)
cat > /tmp/productos.jsonl <<EOF
{"id": "prod-002", "nombre": "Zapatillas deportivas", "descripcion": "Zapatillas ligeras para correr", "categoria": "Calzado", "marca": "SpeedRun", "precio": 89.99, "stock": 45, "activo": true, "etiquetas": ["calzado", "deporte", "running"]}
{"id": "prod-003", "nombre": "Pantalón vaquero slim", "descripcion": "Vaquero ajustado de corte moderno", "categoria": "Ropa", "marca": "DenimPro", "precio": 49.99, "stock": 80, "activo": true, "etiquetas": ["ropa", "pantalon", "vaquero"]}
EOF
# Importar el archivo JSONL
curl -X POST "http://localhost:8108/collections/productos/documents/import?action=create" \
-H "Content-Type: text/plain" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
--data-binary @/tmp/productos.jsonl
# Actualizar un documento (upsert)
curl -X PUT "http://localhost:8108/collections/productos/documents/prod-001" \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{"precio": 17.99, "stock": 200}'
# Eliminar un documento
curl -X DELETE http://localhost:8108/collections/productos/documents/prod-001 \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
Búsqueda y Parámetros
# Búsqueda básica
curl "http://localhost:8108/collections/productos/documents/search?q=zapatillas&query_by=nombre,descripcion" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
# Búsqueda con parámetros avanzados
curl "http://localhost:8108/collections/productos/documents/search" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-G \
--data-urlencode "q=zapatillas deporte" \
--data-urlencode "query_by=nombre,descripcion,etiquetas" \
--data-urlencode "query_by_weights=3,1,2" \
--data-urlencode "filter_by=activo:=true && precio:<100" \
--data-urlencode "sort_by=precio:asc" \
--data-urlencode "per_page=20" \
--data-urlencode "page=1" \
--data-urlencode "num_typos=2" \
--data-urlencode "prefix=true"
Búsqueda Facetada
# Búsqueda con facetas para filtros de navegación
curl "http://localhost:8108/collections/productos/documents/search" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-G \
--data-urlencode "q=*" \
--data-urlencode "query_by=nombre" \
--data-urlencode "facet_by=categoria,marca,etiquetas" \
--data-urlencode "max_facet_values=10" \
--data-urlencode "filter_by=categoria:=Ropa" \
--data-urlencode "sort_by=precio:asc"
La respuesta incluirá el campo facet_counts con los valores posibles y sus conteos para construir filtros dinámicos en la interfaz.
Despliegue con Docker
# docker-compose.yml para Typesense
version: "3.8"
services:
typesense:
image: typesense/typesense:0.25.2
container_name: typesense
ports:
- "8108:8108"
volumes:
- typesense-data:/data
command: >
--data-dir /data
--api-key=TU_CLAVE_API_SECRETA_AQUI
--enable-cors=true
--listen-port=8108
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8108/health"]
interval: 30s
timeout: 10s
retries: 3
volumes:
typesense-data:
docker compose up -d
docker compose logs typesense
Integración con Aplicaciones
Generar claves API de solo lectura para el frontend
# Crear una clave de búsqueda con permisos limitados
curl -X POST http://localhost:8108/keys \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{
"description": "Clave de búsqueda pública para el frontend",
"actions": ["documents:search"],
"collections": ["productos"]
}'
Integración con JavaScript (InstantSearch)
# Instalar las librerías necesarias
npm install typesense typesense-instantsearch-adapter react-instantsearch-dom
// Configuración básica del cliente Typesense
import Typesense from 'typesense';
const client = new Typesense.Client({
nodes: [{
host: 'tu-servidor.com',
port: 8108,
protocol: 'https',
}],
apiKey: 'CLAVE_PUBLICA_SOLO_BUSQUEDA',
connectionTimeoutSeconds: 2,
});
// Búsqueda simple
const resultados = await client.collections('productos').documents().search({
q: 'zapatillas',
query_by: 'nombre,descripcion',
filter_by: 'activo:=true',
sort_by: 'precio:asc',
});
Solución de Problemas
Typesense no arranca:
# Revisar logs del servicio
sudo journalctl -u typesense -n 50 --no-pager
# Verificar permisos del directorio de datos
ls -la /var/lib/typesense/
sudo chown -R typesense:typesense /var/lib/typesense/
Error 401 en las peticiones API:
# Verificar que la clave API en la cabecera es correcta
curl -v http://localhost:8108/health -H "X-TYPESENSE-API-KEY: TU_CLAVE"
# La clave debe coincidir exactamente con la del archivo de configuración
grep "api-key" /etc/typesense/typesense-server.ini
La búsqueda no devuelve resultados esperados:
# Ver los documentos indexados
curl "http://localhost:8108/collections/productos/documents/search?q=*&query_by=nombre&per_page=10" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
# Verificar el número de documentos en la colección
curl http://localhost:8108/collections/productos \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" | python3 -m json.tool | grep num_documents
Rendimiento lento:
# Typesense mantiene todo el índice en memoria
# Verificar RAM disponible
free -m
# El índice debe caber en RAM; si no, considerar:
# 1. Aumentar la RAM del servidor
# 2. Reducir el número de campos indexados
# 3. Usar clustering de Typesense para distribuir la carga
Conclusión
Typesense es una excelente opción para implementar búsqueda de alta calidad en aplicaciones que requieren velocidad, tolerancia a errores tipográficos y facilidad de gestión. Su instalación es notablemente más sencilla que Elasticsearch y su consumo de recursos es considerablemente menor, lo que lo hace ideal para proyectos con presupuesto ajustado o equipos pequeños. Las claves de API con permisos limitados permiten exponer la búsqueda directamente al navegador del usuario de forma segura, eliminando la necesidad de un servidor proxy intermedio.


