Muchas veces, cuando empezamos a trabajar con una nueva tecnología, nos centramos en conseguir que funcione de manera rápida sin entender los conceptos en los que se basa.

El tiempo apremia, así que buscamos un tutorial o un paso a paso que nos diga exactamente qué hacer para tener algo funcionando cuanto antes. Si todo va bien, conseguimos salir del paso con la funcionalidad necesaria, pero en el momento en el que algo falla es cuando tener clara la base de esa tecnología nos puede evitar muchos quebraderos de cabeza.

Este post tiene como objetivo dar algunas claves que pueden ayudarnos a entender cómo funciona Elasticsearch (u otros motores de búsqueda basados en Lucene) y comprender cuál puede ser la causa de algunos de los errores más comunes.

Índices invertidos

Elasticsearch está basado en Apache Lucene y una de las principales características de esta librería para búsquedas de texto es el uso de índices invertidos.

Al contrario que las aproximaciones clásicas de bases de datos, donde cada uno de los documentos se almacena asociado a una clave, en un índice invertido se guardan partes del documento por las que buscar (normalmente palabras) y referencias a los documentos en los que aparecen.

En un índice podríamos guardar los siguientes documentos, cada uno de ellos asociado a su clave:

Clave Documento
1 ¿Qué es esto?
2 Esto es un texto
3 Este texto es otro texto

Si se quiere hacer una búsqueda de documentos en los que aparece la palabra “texto”, el proceso consistiría en ir documento a documento comprobando si contiene dicha palabra, lo cuál, especialmente para gran número de documentos, puede suponer tiempos de búsqueda elevados.

En el caso de índices invertidos se realiza un proceso previo en el que, cada uno de los documentos se dividen en cadenas de texto buscable y se almacenan asociadas a los documentos en los que aparecen. Por ejemplo, para el caso anterior, dividiendo por palabras (y eliminando signos de puntuación) tendríamos:

Palabra ID de documento
qué 1
es 1, 2, 3
esto 1, 2
un 2
texto 2, 3
este 3
otro 3

En este caso, saber en qué documentos se encuentra la palabra “texto” es directo, ya que, asociados a la palabra, se pueden recuperar los identificadores de los documentos en los que aparece (en este caso 2 y 3).

Estos índices invertidos se pueden generar además con información adicional, como las posiciones que ocupan las palabras en el documento o las veces que aparecen, de tal forma que se pueda usar esa información para funcionalidades adicionales como resaltado de coincidencias u ordenación por relevancia:

Palabra (Documento, Posición)
qué (1,1)
es (1,2) (2,2) (3,3)
esto (1,3) (2,1)
un (2,3)
texto (2,4) (3,2) (3,5)
este (3,1)
otro (3,4)

Así, por ejemplo, podríamos ver que la palabra “texto” aparece en la posición 4 del documento 2 y en las posiciones 2 y 5 del documento 3.

A tener en cuenta

Shards y réplicas

Normalmente, cuando hacemos pruebas con un solo nodo no es necesario que nos preocupemos por las réplicas o los shards, pero una vez que pasamos a un entorno productivo en el que queremos protección contra fallos y optimizar el rendimiento, son dos conceptos que juegan un papel fundamental.

Shards

Son fragmentos de un índice que contienen parte de los documentos (o todos los documentos si se tiene un único shard).

La principal ventaja de dividir los índices en shards es que se pueden hacer búsquedas en paralelo sobre un menor número de documentos y, por lo tanto, cada una de esas búsquedas será más rápida que hacerla sobre el índice completo.

Sin embargo, tiene como contrapartida que los resultados de dichas búsquedas deben combinarse, lo cual supone un tiempo adicional de procesado.

Es por ello que, en caso de querer optimizar el rendimiento de las búsquedas, deben hacerse pruebas de rendimiento con diferentes valores para ver cuáles son los que hacen que, ese equilibrio entre búsquedas más rápidas y mayor tiempo de procesado, nos de mejores resultados.

Réplicas

Una réplica es una copia de un shard en un nodo diferente del cluster. Tener múltiples copias de un mismo shard nos permite por una parte aumentar el número de usuarios concurrentes que pueden estar haciendo búsquedas y, por otra, proteger al servicio de búsqueda ante fallos, ya que, al estar replicada la información, podría seguir funcionando en caso de eventuales caídas de nodos.

Podemos ver cómo se comporta un cluster de elasticsearch con un índice dividido en 3 shards en caso de caída de algún nodo, dependiendo de si tiene o no configuradas réplicas:

A tener en cuenta

Analizadores de texto

Los analizadores de texto son una herramienta muy potente a la hora de proporcionar a nuestro sistema una suerte de búsqueda semántica, en la que importa más el significado de las palabras que los caracteres que las forman.

Esto es especialmente importante si tenemos en cuenta que, por norma general, un usuario que haga una búsqueda de texto no tiene por qué utilizar las palabras exactas que se han almacenado en los documentos.

El uso de analizadores de texto permite transformar tanto las palabras que introduce el usuario como las que se almacenan en los documentos, de tal forma que ciertas variaciones como diferente capitalización, signos de puntuación o incluso plurales o singulares no se tengan en cuenta a la hora de determinar si una palabra coincide o no con la que aparece en un documento.

Supongamos, por ejemplo, que tenemos un documento con el texto “Recibos telefonía.” y un usuario busca “recibo de teléfono”. La lógica nos lleva a pensar que el documento es relevante para dicha búsqueda. Sin embargo, si nos fijamos únicamente en las palabras y los caracteres que las forman, vemos que no coinciden.

“Recibos” y “recibo” no tienen los mismos caracteres, lo mismo pasa con “teléfono” y “telefonía” y además el usuario está buscando la palabra “de” que no aparece en el documento.

Nosotros sabemos que esas variaciones en las palabras no alteran el significado de las mismas tanto como para descartar el documento, pero un algoritmo solo ve cadenas de texto diferentes.

Ahora bien, si hacemos uso de algunos de los analizadores de texto que nos proporciona Elasticsearch podríamos realizar las siguientes transformaciones:

Documento
Original Recibos telefonía.
Mapping Recibos telefonia.
Tokenizer Recibos telefonia
Lowercase recibos telefonia
Stop recibos telefonia
Stemmer recib telefon
Búsqueda
Original recibo de teléfono
Mapping recibo de telefono
Tokenizer recibo de telefono
Lowercase recibo de telefono
Stop recibo telefono
Stemmer recib telefon

A tener en cuenta

Conclusión

Una vez que se tienen claros estos conceptos resulta más sencillo, al menos, tener una idea de cuál puede ser la causa de un error y de cómo solucionarlo.

Los problemas de despliegue y disponibilidad suelen estar relacionados bien con la configuración de los nodos o bien con un número no apropiado de réplicas o shards. En esas situaciones, tener acceso a una herramienta que nos muestre la distribución de los shards en el cluster es fundamental.

Cuando se trata de un error funcional, muchos de los problemas más comunes suelen producirse por un uso incorrecto de los analizadores de texto. En esos casos, comprender exactamente qué transformaciones se están llevando a cabo y en qué orden nos puede evitar muchos quebraderos de cabeza.

Por supuesto, únicamente tres claves no dan para cubrir todos los posibles errores con los que nos podemos encontrar a la hora de trabajar con Elasticsearch, pero tener una base sobre la que trabajar nos ayudará a la hora de afrontarlos.

Bonus

Si te has quedado con ganas de más, te recomendamos echar un vistazo a nuestro curso de Elasticsearch.

Si quieres estar al tanto de todos nuestros vídeos, ¡suscríbete a nuestro canal de YouTube!

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.