Uno de los proyectos súper interesantes en los que estuve trabajando durante mi primer año en Elastic es el cliente oficial para Elastic Enterprise Search. Fue mi primer proyecto de cero, y una experiencia excelente. Trabajé en conjunto con el equipo de Enterprise Search, aprendí un montón de esos servicios y la recepción fue súper positiva.

Gracias a esto también empecé a dar mis primeras charlas en inglés. Participé de una charla en ElasticON Global junto a dos compañeros de equipo. Hablamos sobre el trabajo que hemos venido haciendo en el equipo, y en mi parte hablé de Enterprise Search y los clientes. Más adelante di un webinar para la comunidad Elastic donde pude extenderme un poco más y mostrar con código qué se puede hacer en Enterprise Search usando los clientes.

Recientemente participé del Ruby Advent Calendar 2020, 25 días con 25 posts sobre gemas Ruby. Mi primer post fue sobre elastic-enterprise-search, y a continuación reproduzco el contenido en español:

Gema elastic-enterprise-search – Workplace Search, App Search, y Site Search todo junto. Esta gema es el cliente oficial para Elastic Enterprise Search y está actualmente disponible en beta. Enterprise Search es una solución de Elastic para la búsqueda en la empresa. Está construida sobre el Stack Elastic y Elasticsearch, así que obtenemos todo lo bueno que ya conocemos en un paquete único para nuestro equipo. Es una solución paraguas que contiene Workplace Search, App Search y Site Search. El cliente se enfoca en App Search y Workplace Search.

¿Qué es Workplace Search?

Workplace Search es una solución de búsqueda unificada para equipos. Una de las cosas interesantes sobre Workplace Search para mí es que en trabajos anteriores hubiera deseado tener un producto como éste. Teníamos distintos documentos y manuales en varios servicios diferentes: wikis, Jira, email, Dropbox, Basecamp. Cuando necesitaba encontrar un documento específico, tenía que encontrar dónde buscarlo, y después buscar.

Workplace nos da una experiencia única de búsqueda para todo nuestro contenido. Ya hay integraciones incluidas para Google Drive, Sharepoint, GitHub y otros servicios populares. Pero también se puede agregar fuentes de documentos personalizadas si estamos usando un sistema que todavía no tiene una integración y empezar a indexar documentos desde ahí.

¿Qué es App Search?

App Search es una solución de búsqueda lista para usar que incluye analítica y ajuste de relevancia amigable para el usuario. Se puede usar para agregar experiencias de búsqueda a una aplicación, página web, etc. En App Search creamos motores (engines), repositorios de información que se especializan en búsqueda. Es muy fácil indexar documentos JSON y hacerlos accesibles desde la búsqueda enseguida, no necesitamos especificar un esquema, se crea automáticamente.

La gema Enterprise Search

Basado en nuestra experiencia manteniendo los clientes para Elasticsearch, una de las ideas que tuvimos durante el desarrollo de este cliente fue reutilizar la capa de transporte HTTP de los clientes Elasticsearch. Éstos clientes están bastante bien probados y fueron diseñados de manera modular. Así que abrimos una rama de desarrollo para incluir la dependencia en elasticsearch-transport, borramos todo el código de conexiones http de los nuevos clientes y los probamos. Fue relativamente fácil, como pueden ver en el siguiente código, está optimizado para usar con Elasticsearch pero sigue siendo una biblioteca HTTP:

require 'elasticsearch-transport'
 
client = Elasticsearch::Transport::Client.new(
  host: 'http://jsonplaceholder.typicode.com:80'
)
 
client.perform_request('get', 'posts/42').body
 
#=> {"userId"=>5, "id"=>42, "title"=>"commodi ullam sint et excepturi error explicabo praesentium voluptas",
#  "body"=>"odio fugit voluptatum ducimus earum autem est incidunt voluptatem\n
#           odit reiciendis aliquam sunt sequi nulla dolorem\n
#           non facere repellendus voluptates quia\nratione harum vitae ut"}

Así que el cliente Enterprise Search fue desarrollado con la capa HTTP del cliente Elasticsearch y las APIs de cada servicio en Enterprise Search. El código de cada una de las APIs se genera de una especificación JSON OpenAPI en la cual hemos trabajado en conjunto con los equipos de Enterprise Search, Workplace Search y App Search. De esta forma cuando la API de cualquiera de los servicios cambia en una versión nueva, sólo necesitamos actualizar la especificación Open API y volver a generar el código.

Con estos clientes, tu aplicación puede integrarse sin problemas con Elastic Enterprise Search. Puedes ver el código en GitHub o instalarla desde RubyGems:

$ gem install elastic-enterprise-search --pre

El código fuente incluye una tarea rake para ejecutar el stack Enterprise Search por medio de Docker: rake stack[version], pero también podemos levantar una instancia en Elastic Cloud. Una vez iniciada una instancia, ya sea por Docker o Cloud, podemos probar el cliente:

require 'elastic-enterprise-search'
 
# Éstas son las credenciales por defecto si estás usando la tarea rake:
http_auth = { user: 'elastic', password: 'changeme' }
host = 'localhost:3002'
 
client = Elastic::EnterpriseSearch::Client.new(log: true, host: host, http_auth: http_auth)
response = client.health

El objeto respuesta es una instancia de Elasticsearch::Transport::Transport::Response de elasticsearch-transport. Podemos llamar headers y status en el objeto, pero usualmente vamos a usar response.body para ver la respuesta JSON del servidor. La API EnterpriseSearch::Client nos proporciona algunos endpoints útiles para ver el estado del clúster y gestionar el modo sólo lectura. Puedes leer más acá.

Si queremos usar Workplace Search y App Search, podemos instanciar un cliente nuevo o compartir la capa de transporte con un cliente Enterprise Search que ya hayamos creado. Esto significa que van a compartir el mismo host, pero Workplace Search y App Search tienen sus propios métodos de autenticación respectivamente.

Usando Workplace Search

Para empezar a usar el cliente, necesitamos abrir la interfaz de usuario web de Enterprise Search en nuestro navegador y elegir Workplace Search de la pantalla inicial. Una vez ahí, vamos a ver una pantalla que dice “Shared content sources” y un botón para agregar fuentes de contenidos (“Add sources”). También podemos agregar contenidos desde “Sources” en el menú de la izquierda. En la pantalla de “Add a shared content source”, necesitamos elegir “Custom API Source”, darle un nombre y presionar “Create Custom API Source”:

Workplace Search Custom API Source

Una vez creada la fuente de contenido, obtenemos un Access Token y una Key:

Workplace Search: Ruby Client Created

Dado el cliente instanciado en el ejemplo anterior, podemos empezar a interactuar con Workplace Search:

access_token = '<PEGAR Access Token DE WORKPLACE SEARCH>'
content_source_key = '<PEGAR Key DE WORKPLACE SEARCH>'
workplace_search = client.workplace_search(http_auth: access_token)

Vamos a usar content_source_key cuando llamemos a la API para indicarle qué fuente de contenido estamos usando. Ahora vamos a indexar algunos documentos:

documents = [
  { title: '20,000 Leagues Under the Sea', year: 1916, director: 'Stuart Paton' },
  { title: 'Dr. Jekyll and Mr. Hyde', year: 1920, director: 'John S.Robertson' },
  { title: 'Frankenstein', year: 1910, director: 'J. Searle Dawley' },
  { title: 'Metropolis', year: 1927, director: 'Fritz Lang' },
  { title: 'Nanook of the North', year: 1922, director: 'Robert J. Flaherty' },
  { title: 'Night of the Living Dead', year: 1968, director: 'George A. Romero' },
  { title: 'Plan 9 from Outer Space', year: 1959, director: 'Ed Wood' },
  { title: 'Popeye the Sailor Meets Ali Baba\'s Forty Thieves', year: 1937, director: 'Dave Fleischer' },
  { title: 'The Immigrant', year: 1917, director: 'Charles Chaplin' }
]
 
response = workplace_search.index_documents(content_source_key, body: documents)

El cuerpo de la respuesta debería mostrarnos las id’s que Workplace Search generó automáticamente para nuestros documentos y arrays de errores para cada uno, los cuales con suerte van a estar vacíos si todo salió bien. Ahora que indexamos algunos documentos, podemos visitar {host}/ws/search (http://localhost:3002/ws/search si estás usando el contenedor Docker del repositorio) y ver que nuestros documentos han sido indexados y podemos realizar búsquedas sobre ellos.

El cliente provee más funcionalidades de Workplace Search que puedes leer acá.

Usando App Search

Para usar App Search necesitamos volver a la página inicial de Enterprise Search en nuestro navegador y elegir App Search. Podemos ignorar el onboarding, y se nos va a presentar la pantalla de “Create Engine” para crear un motor de búsqueda. Vamos a crear un motor del cliente, pero necesitamos acceder a la página de Credenciales desde el menú de la izquierda. Podemos crear una API Key nueva para el cliente, o para este ejemplo usar la clave private-key proporcionada que tiene acceso de lectura y escritura. Copia el valor de esta llave y pégala en el código Ruby. Como con Workplace Search, podemos crear un nuevo cliente o compartir la capa de transporte con un cliente Enterprise Search creado anteriormente:

api_key = '<PEGAR Api Key DE APP SEARCH>'
app_search = client.app_search(http_auth: api_key)
 
engine_name = 'books'
response = app_search.create_engine(name: engine_name)
app_search.list_engines

Ahora que tenemos un motor, indexemos algunos documentos de nuevo:

documents = [
  { title: 'Beowulf: An Anglo-Saxon Epic Poem', author: 'J. Lesslie Hall' },
  { title: 'Frankenstein; Or, The Modern Prometheus', author: 'Mary Wollstonecraft Shelley' },
  { title: 'Jungle Tales', author: 'Horacio Quiroga' },
  { title: 'Lenguas de diamante', author: 'Juana de Ibarbourou' },
  { title: 'Leviathan', author: 'Thomas Hobbes' },
  { title: 'Metamorphosis', author: 'Franz Kafka' },
  { title: 'Moby Dick; Or, The Whale', author: 'Herman Melville' },
  { title: 'Pride and Prejudice', author: 'Jane Austen' },
  { title: 'Shetland Folk Tales', author: 'Lawrence Tulloch' },
  { title: 'Siddhartha', author: 'Hermann Hesse' },
  { title: 'The Jungle Book', author: 'Rudyard Kipling' },
  { title: 'The Masque of the Red Death', author: 'Edgar Allan Poe' },
  { title: 'The Republic', author: 'Plato' },
  { title: 'The Strange Case of Dr. Jekyll and Mr. Hyde', author: 'Robert Louis Stevenson' },
  { title: 'The War of the Worlds', author: 'H. G. Wells' }
]
 
app_search.index_documents(engine_name, body: documents)

Por supuesto podemos buscar:

app_search.search(engine_name, body: { query: 'Jungle' })
app_search.multi_search(engine_name, queries: [{ query: 'Jungle'}, {query: 'Herman' }])

Podemos aprovechar la interfaz de App Search para interactuar con los documentos que acabamos de indexar, ver los logs de la API o crear una interfaz de búsqueda de referencia para el motor que acabamos de crear. El cliente provee más funcionalidades para App Search que puedes leer acá.

Conclusión

La gema todavía está en beta pero en constante desarrollo. Pruébala, y revisa el repositorio para reportar cualquier problema o contribuir. Y si quieres aprender más sobre Enterprise Search, recomiendo estas guías rápidas.

Actualmente hay clientes para App Search y Workplace Search empaquetados por separado como gemas Ruby. Éstos clientes todavía funcionan pero van a ser desfazados en favor del cliente nuevo una vez que alcanze un nivel de estabilidad general en el futuro. Migrar al cliente nuevo no debería requerir mucho esfuerzo debido a la similaridad entre las APIs.

No hay comentarios en este post

Feed de comentarios

Dejar un comentario

Notificarme los nuevos comentarios por correo electrónico. Tambien puedes suscribirte sin comentar.

Toasty!