Elasticsearch

Publicado por

Índice

  1. Introducción
  2. Índices y sharding
  3. Manejar datos
  4. Ejemplos

1. Introducción

Elasticsearch es un servidor de búsqueda y analítica distribuido y RESTful basado en Lucene que es capaz de cubrir multitud de casos de uso. Una de las partes fundamentales de Elastic es la centralización de datos de forma indexada.

Shay Banon creó Compass en 2004. Mientras pensaba en la tercera versión de Compass, llegó a la conclusión de que habría que reescribir grandes partes de su código para “crear una solución de búsqueda escalable”. Lo que le llevo a empezar el desarrollo de una solución distribuida desde el principio.

Uno de los requisitos era implementar la interfaz JSON sobre el protocolo HTTP, muy común y adecuada para lenguajes de programación que no sean Java. Shay Banon liberó la primera versión en febrero de 2010. En Junio de 2014 la compañía anuncio la recaudación de $70 millones de un ronda de financiación de la serie C, tras 18 meses desde la creación de la misma.

Con Elasticsearch podremos realizar y combinar multitud de búsquedas, estructurada, sin estructructurar, geo, métricas sobre el conjunto de datos disponibles, por ejemplo, sobre millones de registros de logs para hacer zoom y explorar tendencias y descubrir patrones en los datos.

Elasticsearch implementa índices invertidos para realizar búsquedas de texto completo, árboles BKD que guardan datos numéricos y geo, y un almacén columnar para el análisis. Como todos los datos están indexados, el acceso a ellos se produce a una velocidad muy alta, es realmente rápido. El corazón de Elasticsearch es Lucene, el mismo motor de indexación y búsqueda que utiliza SolR, por lo que estas dos tecnologías comparten muchas funcionalidades. 

Ir del prototipo a la producción sin problemas de escalabilidad es sencillo, Elasticsearch puede ejecutarse en un solo nodo de la misma forma que se ejecutaría en un clúster de 300. Se escala horizontalmente para manejar millones de eventos por segundo, mientras que administra automáticamente la forma en que los índices y las consultas se distribuyen en el clúster para que las operaciones se realicen sin problemas.

Para interaccionar con Elasticsearch a través de código se utilizan implementaciones estándar de APIs RESTFul y JSON. Se pueden construir clientes con diferentes lenguajes de programación como Java, Python, .NET, SQL y PHP. Además existe una comunidad que contribuye al crecimiento de las APIs y los distintos lenguajes disponibles. 

2. Índices y Sharding

La plataforma de Elasticsearch proporciona respuestas cercanas al tiempo real lo que significa que desde que se indexa un documento hasta que está disponible, pasa alrededor de un segundo.

Un índice es una colección de documentos que tienen características en común. Por ejemplo, existen índices para los datos de clientes, otro para los productos del catálogo, otro para los datos sobre pedidos, etc. El índice se identifica por un nombre y este nombre es utilizado para realizar operaciones sobre el índice como indexar, buscar, actualizar y borrar los documentos contenidos en el.

Un documento es la unidad básica de información que puede ser indexada. Por ejemplo existe un documento referido a un único cliente, otro documento para referirse a un producto, y otro que sean los datos de un solo pedido. El documento se expresa en JSON que es un formato muy extendido en el intercambio de datos en Internet. Dentro de un índice se pueden guardar todos los documentos que necesites. 

Un índice puede almacenar tal cantidad de datos que exceda las limitaciones del hardware de una sola máquina. Por ejemplo un índice con billones de documentos ocupando 1TB de espacio en disco, puede no entrar en un solo disco o puede que sea muy lento accediendo a los datos para devolver en una búsqueda.

Para resolver este problema, Elasticsearch se ayuda de los principios de motor de búsqueda Lucene, y proporciona la capacidad de subdividir el índice en múltiples piezas distribuidas en distintas máquinas llamadas shards. Cuando se crea un índice, hay que especificar el número de shards en los que quieres dividir el índice, cada uno de los shards es un índice funcionalmente completo e independiente que puede estar alojado en cualquier nodo del clúster. 

El sharding es importante porque permite escalar horizontalmente el volumen de los datos. Y además permite distribuir y paralelizar las operaciones sobre los shards, incrementando el rendimiento de la plataforma. 

Los shards están replicados por el clúster para evitar que una parte de los datos queden indisponibles en caso de un fallo en el nodo, la replicación es importante porque proporciona alta disponibilidad. Con las replicas también se proporciona un sistema de escalabilidad ya que las peticiones sobre los índices se pueden realizar en paralelo sobre las réplicas de los shards.

En resumen, cada índice puede ser dividido en múltiples shards. Un índice puede ser replicado 0 o más veces. Una vez replicado cada índice dispondrá de los shards primarios y las réplicas.

El número de shards y réplicas es definido en la creación del índice. Una vez que el índice es creado, se pueden modificar el número de réplicas dinámicamente en cualquier momento. El número de shards se pueden modificar utilizando las funciones _shrink y _spli, no es una tarea trivial.

Por defecto, cada índice de Elastic se crea con 5 shards primarios y una réplica lo que significa que si tiene por lo menos dos nodos, el índice tendrá 5 shards primarios y 5 réplicas, con un total de 10 shards por índice.

3. Manejar Datos

Elastic incluye un REST API para interactuar con el clúster, con el podemos realizar operaciones como:

  • Comprobar el estado del clúster, nodos, índices y estadísticas
  • Administrar clúster y nodos, indexar datos y metadatos
  • Realizar operaciones CRUD y de búsqueda contra el índice
  • Ejecutar operaciones avanzadas de búsqueda como paginar, ordenar, filtrar, agregaciones y muchas otras

El API de búsqueda (Search API)

Para empezar tenemos que diferenciar entre dos tipos de peticiones: una es enviando los parametros en la URI de la petición REST o enviando los parámetros a traves del body de la petición REST. Enviando los parámetros en el body suele ser más expresivo ya que se puede utilizar una estructura de JSON para definir los datos. 

Para acceder al REST API de búsqueda hay que acceder al recurso _search, ej:

GET /bank/_search?q=*&sort=account_number:asc&pretty

Con la petición anterior estamos buscando sobre el índice bank, y con el parámetro q=* le estamos diciendo que nos devuelva todos los documentos del índice. También le estamos diciendo que queremos ordenar los resultados de forma ascendente por número de cuenta y que el resultado lo pinte bonito en JSON.

El ejemplo anterior utilizando el body sería:

GET /bank/_search {   "query": { "match_all": {} },   "sort": [     { "account_number": "asc" }   ] }


Para conocer más el lenguaje en formato JSON llamado Query DSL podemos mirar la documentación. Query DSL

Una vez lanzada la petición y recibidos los datos, Elasticsearch no mantiene ningún tipo de conexión abierta con el cliente. 

También se pueden realizar agregaciones y conteos por distintos tipos de atributos. 

POST /sales/_search?size=0 {     "aggs" : {         "types_count" : { "value_count" : { "field" : "type" } }     } }

Response

{     ...     "aggregations": {         "types_count": {             "value": 7         }     } }

Con Elasticsearch puedes ir desde la búsqueda más sencilla a la más compleja.

 

4. Ejemplos

Curl

curl -H "Content-Type: application/json" -XGET 'http://localhost:9200/social-*/_search' -d '{   "query": {     "match": {       "message": "myProduct"     }   },   "aggregations": {     "top_10_states": {       "terms": {         "field": "state",         "size": 10       }     }   } }'

Java

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(                     new HttpHost("localhost", 9200, "http"))); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery());            searchSourceBuilder.aggregation(AggregationBuilders.terms("top_10_states").field("state").size(10)); SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("social-*"); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest);

Python

from elasticsearch import Elasticsearch esclient = Elasticsearch(['localhost:9200']) response = esclient.search( index='social-*', body={     "query": {         "match": {             "message": "myProduct"         }     },     "aggs": {         "top_10_states": {             "terms": {                 "field": "state",                 "size": 10             }         }     } } )

Javascript

var elasticsearch = require('elasticsearch'); var esclient = new elasticsearch.Client({   host: 'localhost:9200' }); esclient.search({   index: 'social-*',   body: {     query: {       match: { message: 'myProduct' }     },     aggs: {       top_10_states: {         terms: {             field: 'state',             size: 10         }       }     }   } } ).then(function (response) {     var hits = response.hits.hits; } );

Fuentes: 

Elasticsearch

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s