Crear un índice de Elasticsearch

Dos conceptos muy importantes en Elasticsearch son los documentos y los índices.

Un documento es una colección de campos con sus valores asociados. Para trabajar con Elasticsearch tienes que organizar tus datos en documentos y luego agregar todos tus documentos a un índice. Puedes pensar en un índice como una colección de documentos almacenada en un formato altamente optimizado diseñado para realizar búsquedas eficientes.

Si trabajaste con otras bases de datos, puede que sepas que muchas requieren una definición de esquema, que es esencialmente una descripción de todos los campos que quieres almacenar y sus tipos. Un índice Elasticsearch puede configurar con un esquema si se desea, pero también puede derivar automáticamente el esquema a partir de los propios datos. En esta sección vas a dejar que Elasticsearch resuelva el esquema por sí solo, lo cual funciona bastante bien para tipos de datos simples como texto, números y fechas. Más adelante, cuando te introduzcan tipos de datos más complejos, aprenderás a proporcionar definiciones explícitas de esquemas.

Crear el índice

Así es como se crea un índice de Elasticsearch usando la biblioteca cliente de Python:

En este ejemplo, self.es es una instancia de la clase Elasticsearch , que en este tutorial se almacena en la clase Search en search.py. Un despliegue de Elasticsearch puede usar para almacenar múltiples índices, cada uno identificado por un nombre como my_documents en el ejemplo anterior.

Los índices también pueden ser eliminados:

Si intentas crear un índice con un nombre que ya está asignado a un índice existente, obtendrás un error. A veces es útil crear un índice que elimine automáticamente una instancia anterior del índice si existe. Esto es especialmente útil al desarrollar una aplicación, porque probablemente tendrás que regenerar un índice varias veces.

Vamos a agregar un método de ayuda create_index() en search.py. Abre este archivo en tu editor de código y agrega el siguiente código al final, dejando el contenido existente tal cual:

El método create_index() primero elimina un índice con el nombre my_documents. La opción ignore_unavailable=True evita que esta llamada falle cuando no se encuentra el nombre del índice. La siguiente línea del método crea un índice completamente nuevo con ese mismo nombre.

La aplicación de ejemplo que aparece en este tutorial necesita un único índice de Elasticsearch, y por eso codifica el nombre del índice como my_documents. Para aplicaciones más complejas que usan múltiples índices, puedes considerar aceptar el nombre del índice como argumento.

Agregar documentos al índice

En la biblioteca cliente Elasticsearch para Python, un documento se representa como un diccionario de campos clave/valor. Los campos que tienen un valor de cadena se indexan automáticamente para la búsqueda de texto completo y palabras clave, pero además de las cadenas puedes usar otros tipos de campos como números, fechas y booleanos, que también se indexan para operaciones eficientes como el filtrado. También puedes construir estructuras de datos complejas en las que un campo se asigna a una lista o a un diccionario con subelementos.

Para insertar un documento en un índice, se emplea el método index() del cliente Elasticsearch. Por ejemplo:

El valor de retorno del método index() es la respuesta devolvida por el servicio Elasticsearch. La información más importante que se devuelve en esta respuesta es un elemento con el nombre clave _id, que representa el identificador único asignado al documento cuando se insertó en el índice. El identificador puede usar para recuperar, eliminar o actualizar el documento.

Ahora que sabes cómo insertar un documento, sigamos construyendo una biblioteca de ayudas útiles en search.py, con un nuevo método insert_document() para la clase Search . Agrega este método al final de search.py:

El método acepta el cliente Elasticsearch y un documento del llamante, e inserta el documento en el índice de my_documents , devolviendo la respuesta del servicio.

NOTA: Estas operaciones no se cubren en este tutorial, pero el cliente Elasticsearch también puede modificar y eliminar documentos. Consulta la referencia de la clase Elasticsearch en la documentación de la biblioteca de Python para conocer todas las operaciones disponibles.

Ingirencia de documentos de un archivo JSON

Al configurar un nuevo índice de Elasticsearch, probablemente necesitarás importar un gran número de documentos. Para este tutorial, el proyecto inicial incluye un archivo data.json con algunos datos en formato JSON. En esta sección aprenderás cómo importar todos los documentos contenidos en este archivo al índice.

La estructura de los documentos incluidos en el data.json es la siguiente:

  • name: el título del documento
  • url: una URL al documento alojado en un sitio externo
  • summary: un breve resumen del contenido del documento
  • content: el cuerpo del documento
  • created_on: fecha de creación
  • updated_at: fecha de actualización (podría faltar si el documento nunca se actualizó)
  • category: la categoría del documento, que puede ser github, sharepoint o teams
  • rolePermissions: una lista de licencias de rol

En este punto se recomienda abrir data.json en tu editor para familiarizarte con los datos con los que vas a trabajar.

En esencia, importar un gran número de documentos no es diferente a importar un solo documento dentro de un bucle for. Para importar todo el contenido del archivo data.json , podrías hacer algo así:

Aunque este enfoque funciona, no escala bien. Si tuvieras que insertar un número muy grande de documentos, tendrías que hacer tantas llamadas como sea posible al servicio Elasticsearch. Desafortunadamente, cada llamada a la API conlleva un costo de rendimiento, y además el servicio tiene límites de velocidad que impiden que se realicen un gran número de llamadas muy rápidamente. Por estas razones, es mejor emplear la función de inserción masiva del servicio Elasticsearch, que permite comunicar varias operaciones al servicio en una sola llamada a la API.

El método insert_documents() que se muestra abajo, que deberías agregar al final de search.py, Emplea el método bulk() para insertar todos los documentos en una sola llamada:

El método acepta una lista de documentos. En lugar de agregar cada documento por separado, ensambla una única lista llamada operations, y luego pasa la lista al método bulk() . Para cada documento, se agregan dos entradas a la lista de operations :

  • Una descripción de qué operación realizar, establecida en index, con el nombre del índice dado como argumento.
  • Los datos reales del documento

Al procesar una solicitud masiva, el servicio Elasticsearch recorre la lista de operaciones desde el inicio y realiza las operaciones aplicar.

Regeneración del índice

Mientras trabajas en este tutorial, tendrás que regenerar el índice varias veces. Para agilizar esta operación, agrega un método reindex() a search.py:

Este método combina los métodos create_index() y insert_documents() creados anteriormente, de modo que con una sola llamada el índice antiguo puede ser destruido (si existe) y construir y repoblar un nuevo índice.

NOTA: Al indexar un número muy grande de documentos, lo mejor sería dividir la lista de documentos en conjuntos más pequeños e importar cada conjunto por separado.

Para que este método sea más fácil de invocar, vamos a exponerlo a través del comando flask . Abre app.py en tu editor de código y agrega la siguiente función al final:

El decorador de @app.cli.command() indica al framework Flask que registre esta función como un comando personalizado, que estará disponible como flask reindex. El nombre del comando se toma del nombre de la función, y la docstring se incluye aquí porque Flask la emplea en la documentación --help .

La respuesta de la función reindex() , que a su vez es la respuesta del método bulk() del cliente Elasticsearch, contiene algunos elementos útiles que pueden usar para construir un buen mensaje de estado. En individuo, response['took'] es la duración de la llamada en milisegundos, y response['items'] es una lista de los resultados individuales de cada operación, que en realidad no es útil directamente, pero la longitud de la lista proporciona un recuento de documentos insertados.

Mira cómo queda ejecutando flask --help desde una sesión de terminal, cerciorándote de que el entorno virtual de Python esté activado (si tu sesión de terminal sigue ejecutando la aplicación Flask, puedes abrir una segunda ventana de terminal). Hacia el final de la pantalla de ayuda deberías ver la opción reindex incluida como comando disponible junto con otras opciones que ofrece el framework Flask:

Ahora, cuando quieres generar un índice limpio, solo tienes que ejecutar flask reindex.

¿Estás listo para crear experiencias de búsqueda de última generación?

No se logra una búsqueda suficientemente avanzada con los esfuerzos de uno. Elasticsearch está impulsado por científicos de datos, operaciones de ML, ingenieros y muchos más que son tan apasionados por la búsqueda como tú. Conectemos y trabajemos juntos para crear la experiencia mágica de búsqueda que te dará los resultados que deseas.

Pruébalo tú mismo