Guía rápida de Elasticsearch: Comandos esenciales y consejos

Comandos de Elasticsearch para búsqueda, indexación y análisis

Índice

Elasticsearch es un potente motor de búsqueda y análisis distribuido construido sobre Apache Lucene. Este completo resumen de comandos cubre comandos esenciales, mejores prácticas y referencias rápidas para trabajar con clústeres de Elasticsearch.

elasticsearch

Nota: La mayoría de los ejemplos en esta guía utilizan cURL para solicitudes HTTP. Si eres nuevo en cURL o necesitas una referencia rápida para opciones avanzadas, consulta nuestro cURL Cheatsheet para técnicas detalladas de solicitudes HTTP desde la línea de comandos.

Gestión de Clústeres

Verificar Salud del Clúster

Todos los comandos en esta sección utilizan cURL para interactuar con la API REST de Elasticsearch. Puedes personalizar estas solicitudes con encabezados adicionales, autenticación y otras opciones según sea necesario.

# Verificación básica
curl -X GET "localhost:9200/_cluster/health?pretty"

# Salud del clúster detallada con información de particiones
curl -X GET "localhost:9200/_cluster/health?level=shards&pretty"

# Verificar información del nodo
curl -X GET "localhost:9200/_cat/nodes?v"

# Verificar configuraciones del clúster
curl -X GET "localhost:9200/_cluster/settings?pretty"

Operaciones en Nodos

# Listar todos los nodos
curl -X GET "localhost:9200/_cat/nodes?v&h=name,node.role,heap.percent,ram.percent,cpu,load_1m"

# Estadísticas del nodo
curl -X GET "localhost:9200/_nodes/stats?pretty"

# Hilos calientes (para solucionar problemas)
curl -X GET "localhost:9200/_nodes/hot_threads"

Gestión de Índices

Crear y Eliminar Índices

# Crear índice
curl -X PUT "localhost:9200/my_index?pretty"

# Crear índice con configuraciones
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}
'

# Eliminar índice
curl -X DELETE "localhost:9200/my_index?pretty"

# Listar todos los índices
curl -X GET "localhost:9200/_cat/indices?v"

# Estadísticas del índice
curl -X GET "localhost:9200/my_index/_stats?pretty"

Mapeos del Índice

# Definir mapeo
curl -X PUT "localhost:9200/products" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "price": { "type": "float" },
      "created_at": { "type": "date" },
      "tags": { "type": "keyword" },
      "description": { 
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}
'

# Obtener mapeo
curl -X GET "localhost:9200/products/_mapping?pretty"

# Actualizar mapeo (añadir campo)
curl -X PUT "localhost:9200/products/_mapping" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "category": { "type": "keyword" }
  }
}
'

Plantillas de Índice

# Crear plantilla de índice
curl -X PUT "localhost:9200/_index_template/logs_template" -H 'Content-Type: application/json' -d'
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 1
    },
    "mappings": {
      "properties": {
        "timestamp": { "type": "date" },
        "message": { "type": "text" },
        "level": { "type": "keyword" }
      }
    }
  }
}
'

# Listar plantillas
curl -X GET "localhost:9200/_index_template?pretty"

Operaciones de Documentos (CRUD)

Crear Documentos

# Índice de documento con ID generado automáticamente
curl -X POST "localhost:9200/products/_doc?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99,
  "tags": ["electronics", "computers"]
}
'

# Índice de documento con ID específico
curl -X PUT "localhost:9200/products/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99
}
'

# Indexado en masa
curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index": { "_index": "products", "_id": "1" }}
{ "name": "Laptop", "price": 999.99 }
{ "index": { "_index": "products", "_id": "2" }}
{ "name": "Mouse", "price": 29.99 }
'

Leer Documentos

# Obtener documento por ID
curl -X GET "localhost:9200/products/_doc/1?pretty"

# Obtener múltiples documentos
curl -X GET "localhost:9200/_mget?pretty" -H 'Content-Type: application/json' -d'
{
  "docs": [
    { "_index": "products", "_id": "1" },
    { "_index": "products", "_id": "2" }
  ]
}
'

# Verificar si el documento existe
curl -I "localhost:9200/products/_doc/1"

Actualizar Documentos

# Actualizar documento
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  }
}
'

# Actualizar con script
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "script": {
    "source": "ctx._source.price *= params.discount",
    "params": {
      "discount": 0.9
    }
  }
}
'

# Actualizar o insertar
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  },
  "doc_as_upsert": true
}
'

Eliminar Documentos

# Eliminar por ID
curl -X DELETE "localhost:9200/products/_doc/1?pretty"

# Eliminar por consulta
curl -X POST "localhost:9200/products/_delete_by_query?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "old"
    }
  }
}
'

Consultas de Búsqueda

Búsqueda Básica

# Coincidir todo
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'

# Consulta de coincidencia
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "laptop"
    }
  }
}
'

# Consulta de coincidencia múltiple
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "laptop gaming",
      "fields": ["name", "description"]
    }
  }
}
'

Consultas de Nivel de Término

# Consulta de término (coincidencia exacta)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "tags": "electronics"
    }
  }
}
'

# Consulta de términos (múltiples valores)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "terms": {
      "tags": ["electronics", "computers"]
    }
  }
}
'

# Consulta de rango
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 1000
      }
    }
  }
}
'

# Consulta de existencia
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "exists": {
      "field": "description"
    }
  }
}
'

Consultas Booleanas

# Consulta booleana (debe, debe no, filtro)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "laptop" }}
      ],
      "filter": [
        { "range": { "price": { "gte": 500 }}}
      ],
      "should": [
        { "term": { "tags": "gaming" }}
      ],
      "must_not": [
        { "term": { "tags": "refurbished" }}
      ]
    }
  }
}
'

Búsqueda Avanzada

# Consulta de comodín
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "wildcard": {
      "name": "lap*"
    }
  }
}
'

# Consulta difusa (tolerancia a errores tipográficos)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "laptpo",
        "fuzziness": "AUTO"
      }
    }
  }
}
'

# Consulta de prefijo
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "prefix": {
      "name": "lap"
    }
  }
}
'

Agregaciones

Agregaciones de Métrica

# Promedio, suma, mínimo, máximo
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "avg_price": { "avg": { "field": "price" }},
    "max_price": { "max": { "field": "price" }},
    "min_price": { "min": { "field": "price" }},
    "total_sales": { "sum": { "field": "price" }}
  }
}
'

# Agregación de estadísticas
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_stats": {
      "stats": { "field": "price" }
    }
  }
}
'

Agregaciones de Bucket

# Agregación de términos (agrupar por)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "popular_tags": {
      "terms": {
        "field": "tags",
        "size": 10
      }
    }
  }
}
'

# Agregación de rango
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 50 },
          { "from": 50, "to": 100 },
          { "from": 100 }
        ]
      }
    }
  }
}
'

# Histograma de fechas
curl -X GET "localhost:9200/logs/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "logs_over_time": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      }
    }
  }
}
'

Agregaciones Anidadas

# Agregaciones anidadas
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "categories": {
      "terms": { "field": "category" },
      "aggs": {
        "avg_price": {
          "avg": { "field": "price" }
        }
      }
    }
  }
}
'

Ordenamiento y Paginación

# Ordenar por campo
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "price": { "order": "desc" }},
    { "_score": { "order": "desc" }}
  ]
}
'

# Paginación con from/size
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "from": 0,
  "size": 10,
  "query": { "match_all": {} }
}
'

# Búsqueda después (para paginación profunda)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 10,
  "query": { "match_all": {} },
  "sort": [{ "price": "asc" }, { "_id": "asc" }],
  "search_after": [100, "product_123"]
}
'

Selección de Campos y Resaltado

# Seleccionar campos específicos
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}
'

# Resaltado
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": { "description": "gaming laptop" }
  },
  "highlight": {
    "fields": {
      "description": {}
    }
  }
}
'

Índices de Alias

# Crear alias
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "add": { "index": "products_v1", "alias": "products" }}
  ]
}
'

# Cambiar alias a un nuevo índice (sin tiempo de inactividad)
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "remove": { "index": "products_v1", "alias": "products" }},
    { "add": { "index": "products_v2", "alias": "products" }}
  ]
}
'

# Listar alias
curl -X GET "localhost:9200/_cat/aliases?v"

Reindexación

# Reindexar de un índice a otro
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "old_products"
  },
  "dest": {
    "index": "new_products"
  }
}
'

# Reindexar con consulta
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "products",
    "query": {
      "range": {
        "price": { "gte": 100 }
      }
    }
  },
  "dest": {
    "index": "expensive_products"
  }
}
'

Snapshots y Copias de Seguridad

# Registrar repositorio de snapshot
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/mount/backups/my_backup"
  }
}
'

# Crear snapshot
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true&pretty"

# Restaurar snapshot
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore?pretty"

# Listar snapshots
curl -X GET "localhost:9200/_snapshot/my_backup/_all?pretty"

# Eliminar snapshot
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_1?pretty"

Optimización del Rendimiento

Configuraciones del Índice

# Deshabilitar actualización durante indexado en masa
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "-1"
  }
}
'

# Rehabilitar después del indexado en masa
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "1s"
  }
}
'

# Forzar fusión (optimizar)
curl -X POST "localhost:9200/products/_forcemerge?max_num_segments=1&pretty"

Limpieza de Caché

# Limpiar todos los cachés
curl -X POST "localhost:9200/_cache/clear?pretty"

# Limpiar caché específico
curl -X POST "localhost:9200/products/_cache/clear?query=true&pretty"

Monitoreo y Solución de Problemas

# Tareas pendientes
curl -X GET "localhost:9200/_cat/pending_tasks?v"

# Estadísticas del pool de hilos
curl -X GET "localhost:9200/_cat/thread_pool?v"

# Información de segmentos
curl -X GET "localhost:9200/_cat/segments?v"

# Información de recuperación
curl -X GET "localhost:9200/_cat/recovery?v&h=index,stage,time"

# API de tareas
curl -X GET "localhost:9200/_tasks?detailed=true&pretty"

Ejemplos del Cliente de Python

from elasticsearch import Elasticsearch

# Conectar a Elasticsearch
es = Elasticsearch(['http://localhost:9200'])

# Índice de documento
doc = {
    'name': 'Laptop',
    'price': 999.99,
    'tags': ['electronics']
}
es.index(index='products', id=1, document=doc)

# Búsqueda
resp = es.search(index='products', query={'match': {'name': 'laptop'}})
for hit in resp['hits']['hits']:
    print(hit['_source'])

# Indexado en masa
from elasticsearch.helpers import bulk

actions = [
    {
        '_index': 'products',
        '_id': i,
        '_source': {'name': f'Product {i}', 'price': i * 10}
    }
    for i in range(1000)
]
bulk(es, actions)

Ejemplos del Cliente de JavaScript/Node.js

El cliente de JavaScript de Elasticsearch proporciona una forma segura de tipo para interactuar con su clúster. Para aplicaciones de producción, considere usar TypeScript para una mayor seguridad de tipo y autocompletado. Consulte nuestro TypeScript Cheatsheet para mejores prácticas sobre definiciones de tipo e interfaces.

const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });

// Índice de documento
async function indexDoc() {
  await client.index({
    index: 'products',
    id: 1,
    document: {
      name: 'Laptop',
      price: 999.99
    }
  });
}

// Búsqueda
async function search() {
  const result = await client.search({
    index: 'products',
    query: {
      match: { name: 'laptop' }
    }
  });
  console.log(result.hits.hits);
}

// Indexado en masa
async function bulkIndex() {
  const operations = [];
  for (let i = 0; i < 1000; i++) {
    operations.push({ index: { _index: 'products', _id: i } });
    operations.push({ name: `Product ${i}`, price: i * 10 });
  }
  await client.bulk({ operations });
}

Ejemplo de TypeScript con Tipado Fuerte

import { Client } from '@elastic/elasticsearch';

interface Product {
  name: string;
  price: number;
  tags?: string[];
  created_at?: Date;
}

const client = new Client({ node: 'http://localhost:9200' });

async function indexProduct(product: Product, id: number): Promise<void> {
  await client.index<Product>({
    index: 'products',
    id: id.toString(),
    document: product
  });
}

async function searchProducts(query: string): Promise<Product[]> {
  const result = await client.search<Product>({
    index: 'products',
    query: {
      match: { name: query }
    }
  });
  
  return result.hits.hits.map(hit => hit._source as Product);
}

Mejores Prácticas

Diseño de Índices

  • Mantén el tamaño de partición entre 20-50 GB para un rendimiento óptimo
  • Usa la gestión del ciclo de vida de índices (ILM) para datos de series temporales
  • Diseña cuidadosamente los mapeos antes de indexar datos
  • Usa tipos de campo adecuados (keyword vs text, formatos de fecha)
  • Deshabilita _source para documentos grandes si no es necesario

Optimización de Consultas

  • Usa filtros en lugar de consultas cuando no se necesite puntuación
  • Prefiere consultas de nivel de término para datos estructurados
  • Usa la consulta bool para combinar múltiples condiciones de manera eficiente
  • Implementa paginación con search_after para paginación profunda
  • Caché filtros frecuentes

Rendimiento de Indexado

  • Usa la API de indexado en masa para indexado por lotes (1000-5000 documentos por solicitud)
  • Deshabilita la actualización durante operaciones de indexado en masa
  • Aumenta index.refresh_interval durante indexado pesado
  • Usa múltiples hilos/trabajadores para indexado paralelo
  • Considera usar enrutamiento para una mejor distribución de particiones

Gestión de Clústeres

  • Monitorea regularmente la salud del clúster
  • Configura correctamente la configuración de réplicas
  • Usa nodos maestros dedicados para clústeres grandes
  • Implementa una estrategia adecuada de copia de seguridad con snapshots
  • Monitorea el uso de la memoria del JVM (mantén por debajo del 75%)

Seguridad

  • Habilita autenticación y autorización (X-Pack Security)
  • Usa HTTPS para despliegues en producción (configura cURL con --cacert, --cert y --key para SSL/TLS)
  • Implementa control de acceso basado en roles
  • Actualizaciones y parches de seguridad regulares
  • Encripta datos en reposo y en tránsito

Casos de Uso Comunes

Búsqueda de Texto Completo

Elasticsearch destaca en búsqueda de texto completo con características como:

  • Puntuación de relevancia
  • Coincidencia difusa
  • Coincidencia de frases
  • Manejo de sinónimos
  • Soporte multilingüe

Análisis de Registros (Pila ELK)

  • Recopila registros con Logstash/Filebeat
  • Índice y búsqueda de registros en Elasticsearch
  • Visualiza con dashboards de Kibana
  • Configura alertas para anomalías

Búsqueda de E-commerce

  • Búsqueda en catálogo de productos
  • Navegación facetada con agregaciones
  • Autocompletado y sugerencias
  • Resultados de búsqueda personalizados

Monitoreo del Rendimiento de Aplicaciones

  • Índice métricas de aplicaciones
  • Dashboards de monitoreo en tiempo real
  • Detección de anomalías
  • Análisis de tendencias de rendimiento

Enlaces Útiles

Recursos Oficiales de Elasticsearch

Cheatsheets y Guías Relacionadas