tutoriales.com

Descubriendo y Aprovechando la Característica `_source` en Elasticsearch

Este tutorial profundiza en la característica `_source` de Elasticsearch, explicando su propósito, cómo se almacena y sus implicaciones en el rendimiento. Aprenderás a controlarlo para mejorar la eficiencia del almacenamiento y la velocidad de tus consultas, optimizando así tu clúster de Elasticsearch.

Intermedio15 min de lectura6 views
Reportar error

🚀 Introducción a _source en Elasticsearch

Cuando indexas un documento en Elasticsearch, este se guarda en su forma original como un campo especial llamado _source. Este campo es fundamental porque contiene el documento JSON completo que enviaste, permitiendo que Elasticsearch lo devuelva tal cual cuando realizas una consulta de recuperación. Es la razón por la que puedes ver todos los campos de tu documento después de indexarlo, incluso si no los has mapeado explícitamente.

Sin embargo, aunque _source es increíblemente útil, también tiene implicaciones en el almacenamiento y el rendimiento que debes entender para optimizar tu clúster. En este tutorial, exploraremos a fondo qué es _source, cómo se utiliza, cómo podemos gestionarlo y cuándo es apropiado deshabilitarlo o controlarlo de forma más granular.

📌 **Nota:** Comprender `_source` es crucial para cualquier administrador o desarrollador que trabaje con Elasticsearch, ya que afecta directamente la eficiencia del almacenamiento y la latencia de las consultas.

📖 ¿Qué es Exactamente _source?

Imagina _source como la copia maestra de tu documento. Cuando indexas un documento en Elasticsearch, no solo se indexan los valores de sus campos individuales para hacerlos buscables (lo que ocurre en el índice invertido), sino que también se almacena una representación completa de ese documento en un único campo. Este campo se llama _source y por defecto está habilitado.

El contenido de _source es una cadena JSON que representa el documento original tal como fue enviado. Cuando realizas una consulta GET o una búsqueda que devuelve el documento completo, Elasticsearch recupera y devuelve el contenido de este campo _source.

✅ Beneficios de _source

  • Recuperación Completa: Permite recuperar el documento original exacto que se indexó, sin perder ningún campo, incluso aquellos que no se indexaron para búsqueda.
  • Reindexación Sencilla: Facilita la reindexación de datos en un nuevo índice con diferentes mappings o configuraciones, ya que el documento completo está disponible.
  • Depuración y Auditoría: Útil para la depuración y para entender la estructura original de los datos.
  • Actualizaciones Parciales: Esencial para realizar actualizaciones parciales de documentos, ya que Elasticsearch necesita el documento completo para modificarlo y reindexarlo internamente.

⚠️ Inconvenientes de _source

  • Uso de Almacenamiento: Almacenar una copia completa de cada documento puede consumir una cantidad significativa de espacio en disco, especialmente con documentos grandes o muchos documentos.
  • Impacto en el Rendimiento: La lectura y escritura de grandes campos _source puede ralentizar las operaciones de ingestión y recuperación de datos, ya que hay más datos que procesar y transferir.
Documento JSON Original Índice Invertido (Campos buscables) Campo _source (Documento Completo) Elasticsearch Consulta Recupera _source

🛠️ Cómo Controlar y Optimizar _source

Elasticsearch ofrece varias maneras de gestionar el campo _source para balancear la conveniencia con la eficiencia de almacenamiento y rendimiento.

1. 🛑 Deshabilitar _source Completamente

Puedes deshabilitar el almacenamiento de _source para un índice si estás seguro de que nunca necesitarás recuperar el documento completo en su forma original. Esto es común en escenarios donde Elasticsearch se usa puramente como un motor de búsqueda y los datos originales se almacenan en otro lugar (una base de datos relacional, un data lake, etc.).

Deshabilitar _source libera mucho espacio en disco y puede mejorar la velocidad de ingestión. Sin embargo, ten en cuenta que una vez deshabilitado, no podrás:

  • Recuperar el documento completo.
  • Realizar actualizaciones parciales (update o update_by_query).
  • Utilizar la función de resaltado (highlighting) si los campos no están también almacenados explícitamente (store: true).

Para deshabilitar _source, configura _source.enabled a false en el mapping de tu índice:

PUT /my_index
{
  "mappings": {
    "_source": {
      "enabled": false
    },
    "properties": {
      "title": {
        "type": "text"
      },
      "description": {
        "type": "text"
      }
    }
  }
}
⚠️ **Advertencia:** Deshabilitar `_source` es una decisión importante. Asegúrate de que tu aplicación no requiere la recuperación completa del documento o la funcionalidad de actualización parcial antes de hacerlo.

2. 📝 Filtrado de _source (_source.includes y _source.excludes)

Si necesitas _source pero no quieres almacenar todos los campos del documento original (por ejemplo, algunos campos son muy grandes o sensibles y no se necesitan para la recuperación), puedes usar _source.includes y _source.excludes en el mapping del índice. Esto permite definir qué campos se almacenarán dentro de _source.

_source.includes: Solo los campos listados se almacenarán en _source. _source.excludes: Todos los campos se almacenarán excepto los listados.

PUT /my_products
{
  "mappings": {
    "_source": {
      "includes": [
        "product_id",
        "name",
        "price"
      ]
    },
    "properties": {
      "product_id": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      },
      "description": {
        "type": "text"
      },
      "image_base64": {
        "type": "keyword",
        "index": false
      },
      "price": {
        "type": "float"
      }
    }
  }
}

En este ejemplo, image_base64 no se incluirá en _source, ahorrando espacio si es un campo muy grande. Sin embargo, seguirá siendo posible buscar por name o description si se han indexado, pero no se mostrarán al recuperar el documento completo.

💡 **Consejo:** Usa el filtrado de `_source` cuando tengas campos muy grandes o sensibles que no sean necesarios para la visualización o actualización posterior. Esto ofrece un buen equilibrio entre ahorro de espacio y funcionalidad.

3. ✨ Selección de Campos en Tiempo de Consulta (_source en la Request)

Aunque _source esté completamente habilitado, puedes solicitar solo un subconjunto de campos del _source almacenado en el momento de la consulta, utilizando el parámetro _source en tu petición de búsqueda.

Esto no reduce el espacio de almacenamiento, ya que el documento completo sigue en _source, pero puede reducir el tráfico de red y el tiempo de procesamiento en el lado del cliente si solo necesitas unos pocos campos.

GET /my_products/_search
{
  "_source": [
    "name",
    "price"
  ],
  "query": {
    "match": {
      "name": "laptop"
    }
  }
}

La respuesta contendrá solo los campos name y price dentro del _source devuelto.

4. 🗄️ Almacenar Campos Individualmente (store: true)

Además de _source, puedes optar por almacenar campos individuales utilizando la propiedad "store": true en el mapping del campo. Cuando un campo se almacena, su valor se guarda por separado del _source en una estructura dedicada. Esto permite recuperar ese campo específico sin tener que parsear el _source completo.

¿Cuándo usar store: true?

  • Cuando has deshabilitado _source y aún necesitas recuperar algunos campos específicos.
  • Cuando necesitas una recuperación muy rápida de ciertos campos que son accedidos frecuentemente, sin la sobrecarga de _source.
  • Para funcionalidades como el resaltado (highlighting) en campos específicos si _source está deshabilitado.
PUT /my_documents
{
  "mappings": {
    "_source": {
      "enabled": false
    },
    "properties": {
      "title": {
        "type": "text",
        "store": true
      },
      "content": {
        "type": "text"
      },
      "author": {
        "type": "keyword",
        "store": true
      }
    }
  }
}

En este escenario, si buscas un documento y pides los campos title y author, Elasticsearch los recuperará de sus almacenamientos individuales en lugar de intentar parsear _source (que está deshabilitado).

🔥 **Importante:** Almacenar campos individualmente consume más espacio en disco que si solo se indexan. Considera cuidadosamente qué campos realmente necesitan ser almacenados. No lo uses en exceso, ya que duplica los datos.

📊 Comparativa de Opciones de Recuperación

Para ayudarte a decidir, aquí tienes una tabla comparativa de las diferentes estrategias para gestionar la recuperación de datos en Elasticsearch:

Característica_source.enabled: true (por defecto)_source.enabled: false_source.includes/excludesstore: true en campoRec. con _source en query
------------------
Almacena documento completo✅ Sí❌ No✅ Parcialmente❌ No (solo campo)✅ Sí (almacenado completo)
Recupera documento completo✅ Sí❌ No✅ Parcialmente❌ No✅ Sí (si está completo)
------------------
Soporta actualizaciones✅ Sí❌ No✅ Sí❌ No✅ Sí (afecta solo request)
Impacto en almacenamientoAltoBajoMedioAdicional por campoNinguno (solo request)
------------------
Impacto en rendimientoPuede ser alto en docs grandesMuy buenoBuenoBuenoBueno
Resaltado (highlight)✅ Sí❌ No (a menos que store: true)✅ Sí✅ Sí (en el campo almacenado)✅ Sí (si está completo)

📈 Cuándo Deshabilitar o Filtrar _source

La decisión de deshabilitar o filtrar _source depende en gran medida de tu caso de uso específico. Aquí hay algunos escenarios típicos:

Escenarios para Deshabilitar _source

  • Registros (Logs): Si Elasticsearch se utiliza para indexar grandes volúmenes de logs y la fuente original de los logs se mantiene en otro sistema (ej. S3), y solo necesitas buscar y agregar, pero nunca recuperar el log completo.
  • Métricas de Tiempo: Datos de series temporales donde solo te interesan las agregaciones y los gráficos, y el documento original de cada punto de datos no es relevante después de la ingestión.
  • Catálogos de Búsqueda Externos: Si Elasticsearch es una capa de búsqueda para un sistema externo (una base de datos relacional) que ya contiene el documento original y es la fuente de la verdad para la recuperación completa.

Escenarios para Filtrar _source (includes/excludes)

  • Documentos con Campos Grandes: Tienes documentos que contienen campos muy grandes (ej. contenido HTML completo, grandes arrays de datos, imágenes en Base64) que no son necesarios para la mayoría de las operaciones de recuperación, pero otros campos sí lo son.
  • Datos Sensibles: Quieres evitar que ciertos campos sensibles sean almacenados en el _source recuperable, aunque sigan siendo indexados para búsqueda (por ejemplo, números de tarjetas de crédito o PII que solo se usan para un filtro específico y luego se descartan).

Ejemplos Prácticos

  1. Plataforma de E-commerce:

    • Puedes usar _source.includes para almacenar product_id, name, price, short_description y url_image.
    • Excluirías long_description_html, supplier_internal_notes o full_product_specs si no se muestran en las páginas de resultados de búsqueda principales y no se usan para actualizaciones parciales, guardándolos en una base de datos de productos separada.
  2. Sistema de Gestión de Documentos:

    • Si los documentos son PDF o Word convertidos a texto, el _source podría contener el texto completo (muy grande).
    • Podrías deshabilitar _source completamente si el PDF original está en un sistema de almacenamiento y solo usas Elasticsearch para buscar metadatos y un resumen.
    • Alternativamente, podrías usar _source.includes para guardar solo el title, author, creation_date y un abstract, excluyendo el full_text_content.
85% Cobertura de Casos de Uso

🔍 Verificando la Configuración de _source

Siempre puedes verificar cómo está configurado _source para un índice existente consultando su mapping:

GET /my_index/_mapping

La respuesta mostrará la configuración de _source bajo la clave _source en las mappings del índice. Si no ves una configuración explícita, significa que _source está habilitado por defecto.

{
  "my_products": {
    "mappings": {
      "_source": {
        "includes": [
          "product_id",
          "name",
          "price"
        ]
      },
      "properties": {
        "product_id": {
          "type": "keyword"
        },
        "name": {
          "type": "text"
        },
        "description": {
          "type": "text"
        },
        "image_base64": {
          "type": "keyword",
          "index": false
        },
        "price": {
          "type": "float"
        }
      }
    }
  }
}

En este ejemplo, vemos claramente que _source está habilitado con una inclusión de campos específica.


📝 Consideraciones Adicionales y Buenas Prácticas

  • Planifica desde el inicio: La configuración de _source es parte del mapping del índice y no se puede cambiar fácilmente en un índice existente. Si necesitas cambiarlo, generalmente deberás reindexar tus datos en un nuevo índice con el mapping deseado.
  • Documentación: Documenta tus decisiones sobre _source para cada índice. Esto es crucial para futuros administradores o desarrolladores que necesiten entender por qué un campo no está disponible o por qué el almacenamiento es mayor/menor de lo esperado.
  • Pruebas de Rendimiento: Antes de implementar cambios en producción, realiza pruebas de rendimiento y uso de disco en un entorno de prueba. Compara el rendimiento de ingestión y búsqueda con y sin _source habilitado o filtrado para ver el impacto real en tu carga de trabajo.
  • Combinar con stored_fields: Si deshabilitas _source pero necesitas recuperar un par de campos, usa "store": true para esos campos. Esto te permite recuperar solo lo esencial sin el _source completo.
¿Puede `_source` contener datos binarios?Sí, `_source` almacena el documento JSON original, por lo que si tu documento JSON contiene un campo con datos binarios codificados (como Base64), `_source` lo almacenará. Sin embargo, esto aumentará significativamente el tamaño del `_source` y, por lo tanto, el uso de almacenamiento y la latencia.
¿Cómo afecta `_source` a las actualizaciones parciales?Cuando realizas una actualización parcial (por ejemplo, con `POST /index/_update/id`), Elasticsearch primero recupera el `_source` completo del documento, aplica tus cambios sobre él, y luego reindexa el documento modificado. Si `_source` está deshabilitado, las actualizaciones parciales no funcionarán porque Elasticsearch no tiene el documento original para modificar.
Paso 1: Evaluar Necesidad: ¿Necesito recuperar el documento JSON completo tal cual? Si no, considera deshabilitar o filtrar `_source`.
Paso 2: Identificar Campos Críticos: Si deshabilitas `_source`, ¿hay campos específicos que *siempre* necesitaré recuperar? Considera `store: true` para ellos.
Paso 3: Definir Mappings: Configura `_source.enabled`, `_source.includes`, `_source.excludes` o `store: true` en tus *mappings*.
Paso 4: Probar y Monitorear: Realiza pruebas de rendimiento y monitorea el uso de disco y el rendimiento de tu clúster.

🎯 Conclusión

La característica _source es una parte integral y potente de Elasticsearch, ofreciendo la flexibilidad de recuperar tus documentos originales en su totalidad. Sin embargo, su configuración predeterminada puede no ser la más eficiente para todos los casos de uso, especialmente en entornos con grandes volúmenes de datos o documentos voluminosos.

Al comprender y utilizar de manera inteligente las opciones de control que ofrece Elasticsearch (_source.enabled, _source.includes, _source.excludes y store: true), puedes optimizar significativamente el uso del espacio en disco y mejorar el rendimiento de tu clúster, adaptando Elasticsearch a las necesidades específicas de tu aplicación. La clave está en tomar decisiones informadas sobre qué datos son realmente necesarios para la recuperación y cuándo el ahorro de recursos supera la conveniencia de tener el documento completo siempre disponible.

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!