Introducción
Este artículo es parte de la serie de píldoras para Product Managers que quieren tomarle el pulso a la tecnología, que puedan probarla, instalarla y demostrar sus capacidades. En taniwa creemos que es osado presentarse como PM o Leader de un proyecto en cuyo ámbito de conocimiento seas un ignorante.
Saber es poder
Piensa en ElasticSearch (ES) siempre que tu producto necesite de:
- Búsquedas indexadas, osea, buscar un texto en diferentes partes de un documento de forma inteligente.
- Agrupaciones por tipologías de documentos. Por ejemplo un catálogo de Ikea y sus facetas (“Deporte”, “Color”, “Talla”).
- Velocidad tanto en las búsquedas como en las sugerencias de la barra de búsqueda.
- Centralizar mucha información de forma que puedas buscar en ella en tiempo real. Los logs de aplicaciones por grandes que sean.
ES en un producto viejuno, basado en Apache Lucene, pero que ha sabido mantenerse en la lucha haciendo muy bien unas cuantas cosas que muchas empresas quieren en sus productos:
- Búsquedas textuales, en el idioma que sea y aplicando algoritmos de text-mining muy flexibles.
- Robusto. Montar un clúster de ES que funcione de verdad es fácil (no como otros).
- Rápido. Inserciones velocísimas y paralelas y fulgurantes búsquedas en millones de documentos.
- Interfaz REST y resultados en JSON. Desde el primer día, lo que le adelantó en su tiempo a los demás (ahora ya no).
Además de su motor de búsquedas e indexación tiene otros elementos cargados de valor como:
- Logstash: Inserciones de los documentos desde ficheros de log, por ejemplo.
- Kibana: Consola Web para explotar y visualizar los datos.
Suelen instalarse juntas y por eso se habla de una solución ELK.
No vamos a incluir en este artículo cómo instalar ES pero tienes muchas opciones que en orden de preferencia para nosotros son:
- Cloud de ES, que te permite soltarlo en máquinas de AWS, Azure o Google Cloud entre otras.
- Bajarte un Docker en local y ponerte a jugar.
- Crearte tu propio clúster. No tan preferida si no es necesario.
Amazon tiene un servicio propio similar que se llama OpenSearch con su historia de robos que puedes leer aquí Amazon: NO ESTÁ BIEN - por qué tuvimos que cambiar el licenciamiento de Elastic
Documentos y Mappings
Un documento es una estructura de campos cada uno con su tipo de datos. Por ejemplo una entrada de este blog tendría:
|
|
ElasticSearch te permite crear un índice en el que albergar tus documentos. Con que guardes un documento en un índice al que le das un nombre, ElasticSearch ya se hace cargo de todo:
- Crear el índice con un mapping automático.
- Distribuir el índice entre los diferentes nodos.
- Recibir queries y responder muy rápido.
Un mapping es la asociación de los campos de tus documentos con un tipo de dato y un analizador de texto.
Un analizador lo que hace es construir un índice inverso de tus documentos para luego, cuando buscas una cadena de 3 palabras, traerte los documentos con más “aciertos”.
|
|
Si mi búsqueda es “artículo que habla de monos”
|
|
Como blog1 tiene 3 aciertos y blog2 tiene 2 aciertos, ES devolvería primero blog1, que no parece lo más adecuado en este caso.
Seleccionar bien el analizador es lo que hace que seamos muy “listos” en las búsquedas o al menos en las que pensamos que necesitamos responder.
Nota para PM, define el tipo de búsquedas y ejemplos que tendrá que defender tu motor de ES.
Los analizadores hacen cosas como:
- Pasar todo a minúscula. Al insertar los documentos el campo título pasaría de “Perros” a “perro” y lo mismo al buscar “Perro …”
- Cortar los textos en palabras (tokenizer). Puede separar por espacios, por “,” ó “.” u otras.
- Pueden quitar todas las etiquetas HTML que en pincipio no aportan a las búsquedas.
- Pueden eliminar palabras cortas que no aportan valor semántico (stop words) como preposiciones y artículos. Osea “Aquí se hablaría de monos rabiando” quedaría “hablaría monos”
- Pueden llevar palabras a su raíz (stemming). Por ejemplo “Jugar, Jugamos, Jugaríamos, " podrían sustituirse por el verbo en infinitivo “jugar”.
- Tratar con sinónimos. “Perro” y “Can” son la misma cosa.
Esto pemite que la anterior búsqueda resulte así:
|
|
Ahora blog1 tiene 1 acierto y blog2 tiene 2 aciertos, con lo que ES devolvería primero blog2, que si parece que es lo que queremos.
ES nos da de partida los analizadores preparados, pero también podemos montarnos el nuestro tratando los textos de salida de una parte como entrada de otro.
Si imaginamos millones de documentos, con cientos de campos, unos de texto libre, otros de textos limitados (colores por ejemplo), fechas, números y precios, ES lo gestiona bien y rápido permitiéndonos dividir la carga sin enterarnos, traer resultados con sentido, filtrar por campos de cualquier tipo y agrupar. ES agrupa a toda pastilla devolviendo los documentos que pertenecen a cada valor de cada campo: Tipo de Producto, por colores, por talla, por rango de precio y por deporte.
Pasamos a la parte más técnica en la que vamos a hablar con un ES usando llamadas http y viendo los resultados JSON.
Leer la documentación de ElasticSearch siempre ayuda y siempre está ahí como ayuda.
Queries comunes
- Ejemplos en un terminal Linux o Mac
- Instalar “curl” y jq
Ver el mapping de un índice:
|
|
Ver el mapping de un campo de un índice :
|
|
|
|
Si añadimos un campo, sus datos se almacenan pero no se indexan y por tanto no estará disponible para búsquedas.
Si necesitamos cambiar el mapping de un campo, crear un nuevo índice con el mapping correcto y reindexar los datos del índice original al nuevo.
|
|
Tipos de dato para los mappings
Tenemos varios tipos de dato: boolean, long, and string types. “String” es el tipo de dato en el que somos fuertes con ES. Podemos indexar (analizar) campos de tipo cadena a “text” o como “keyword” sabiendo que:
- text Se analizan para poder ser buscados con toda la potencia de ES.
- keyword Las cadenas de dejan como vienen para acciones como ordenar por ellas o filtrar (Tráeme sólo los productos de color azul).
Los tipos de los campos están agrupados por familia. Los tipos dato de la misma familia se comportan igual respecto a las búsquedas pero pueden almacenarse de diferente manera y con diferente peso por razones de rendimiento.
Hay dos grandes grupos de familias, “keyword” y “text”. Otros tipos de familias tienen un tipo de campo simple, por ejemplo la familia de “booleanos” consiste un campo de tipo “boolean”.
Tipos comunes
-
binary: Binario como una cadena en Base64.
-
boolean: Campo Boolean que acepta los valores JSON true y false, pero también cadenas qe pueden ser “true” y “false”.
-
keyword: Es una familia.
- keyword, usado como contenido estructurado como IDs, email direcciones, hostnames, códigos de estado, códigos postales, o etiquetas.
- constant_keyword para campos que siempre almacenan el mismo valor.
- wildcard para contenido no estructurado generado por algoritomos.
-
date: JSON no tiene un tipo de dato fecha, así que en Elasticsearch pueden ser:
- Cadenas con formato de fecha, p.e. “2015-01-01” ó “2015/01/01 12:10:30”.
- Número representando milisegundos-desde-epoch.
- Número representando segundos-desde-epoch.
Para usar fechas con múltiples formatos:
1 2 3 4 5 6 7 8 9 10 11
PUT my-index-000001 { "mappings": { "properties": { "date": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } } } }
-
object: En JSON los documentos son gerárquicos: un documento puede contener objetos que a su vez contengan otros objetos.
Ejemplo:
1 2 3 4 5 6 7 8 9 10 11
PUT my-index-000001/_doc/1 { "region": "US", "manager": { "age": 30, "name": { "first": "John", "last": "Smith" } } }
Internamente:
1 2 3 4 5 6
{ "region": "US", "manager.age": 30, "manager.name.first": "John", "manager.name.last": "Smith" }
Mapping explícito:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
PUT my-index-000001 { "mappings": { "properties": { "region": { "type": "keyword" }, "manager": { "properties": { "age": { "type": "integer" }, "name": { "properties": { "first": { "type": "text" }, "last": { "type": "text" } } } } } } } }
-
nested:Versión especial de un objecto que permite que un array de objetos se indexe de manera que puedan ser buscados independientemente Útil con array. Ver ejemplo en el enlace
-
text family: La familia “text” , incluyendo “text” y “match_only_text”.
- text, para el uso tradicional de contenido de tipo texto como el contenido de un email o la descripción de un producto.
- match_only_text, variante que optimiza el almacenamiento que elimina el scoring y que se usa sobretodo en mensajes de log.
El parámetro “analyzer” en el “mapping” se usa para los campos tipo “text” tanto en tiempo de indexación como al lanzar las búsquedas.
Los campos tipo “text” son indexados por defecto y no están disponibles para agregaciones u ordenaciones.
- annotated-text: Text con marcas especiales. Usaod para identificar entidades (named entities).
- completion: Para sugerencias de autocompletado..
- search_as_you_type: Para completar las cadenas de búsquedas mientras tecleas.
Analizadores
ES trae analizadores incluidos:
-
El analizador estándar divide el texto en términos en los límites de las palabras, según lo definido por el algoritmo de segmentación de texto Unicode. Elimina la mayoría de los signos de puntuación, pone los términos en minúsculas y admite la eliminación de palabras vacías.
-
El analizador simple divide el texto en términos cuando encuentra un carácter que no es una letra. Todos los términos se escriben en minúsculas.
-
El analizador de espacios en blanco divide el texto en términos siempre que encuentra algún carácter de espacio en blanco. No pone en minúsculas los términos.
-
El analizador stop es como el analizador simple, pero también admite la eliminación de “stop words”.
-
El analizador de palabras clave es un analizador “noop” que acepta cualquier texto que se le dé y emite exactamente el mismo texto como un solo término.
-
El analizador de patrones utiliza una expresión regular para dividir el texto en términos. Admite las minúsculas y las “stop words”.
-
Elasticsearch ofrece muchos analizadores específicos para cada idioma, como el inglés o el francés.
-
El analizador de huellas dactilares es un analizador especializado que crea una huella dactilar que puede utilizarse para la detección de duplicados.
Analizadores personalizados
Cuando los analizadores incorporados no satisfacen tus necesidades, puedes crear un analizador personalizado que utilice la combinación adecuada de:
- cero o más filtros de caracteres
- un tokenizador
- cero o más filtros de tokens.
Un ejemplo:
|
|
Para comprobar cómo funciona con un texto:
|
|
|
|
Para traer sólo unos campos:
|
|
Recomendaciones generales:
- Sinónimos: Está bien utilizar una base de datos de sinónimos para materiales, formas y términos de diseño.
- Campos a buscar: Sólo el conjunto principal. palabras clave y textos.
- Campos de agregación: Palabras clave y coincidencia de términos.
- Textos: Inglés, sin palabras de parada, stemming, corrección de errores ortográficos.
- Colores: Ver: este artículo y este).
- IMPORTANTE: Crear los mapeos y analizadores antes de ingerir los datos y después de realizar el análisis.
Mappings:
Creando un índice usando un mapping en un fichero:
|
|
Borrar el índice:
|
|
Reindexar, me llevo los datos de un índice a otro con el nuevo mapping.
|
|
Queries
Simple Query interface
Documentación aquí Example:
|
|
Ejemplo:
Recupera documentos con “aged dark” Y “timber” O “floor” Y NO “ceiling”” y busca sólo en los campos “material_description” y “product_description” multiplicando por 5 la relevancia cuando haya coincidencia en material_description sobre product_description:
"query": "\"aged dark\" +(timber | floor) -ceiling",
"default_operator": "and"
"fields": ["material_description^5", "product_description"]
Antentos al parámetro “size” para traer más documentos.
|
|
|
|
|
|
Para probar un analizador u otro con una cadena específica:
|
|
Synomyms
Parece razonable incorporar sinónimos al analizador de búsquedas e índices.
WordNet es una base de datos léxica de relaciones semánticas entre palabras en más de 200 idiomas. WordNet vincula las palabras en relaciones semánticas que incluyen sinónimos, hipónimos y merónimos.
Un ejemplo para recuperar una lista de sinónimos de “timber”
|
|
Ejemplo de cómo añadir sinónimos al analizador english_analyzer (sl_english):
|
|
Foto de mentatdgt en Pexels