Laboratorio de Implementación de un Sistema de Búsqueda e Indexación de Datos parte 1

Objetivo:

Introducir a los estudiantes a la implementación de sistemas de búsqueda e indexación de datos, utilizando herramientas y técnicas modernas.

Descripción:

Los estudiantes desarrollarán un sistema de búsqueda para una aplicación web que permita a los usuarios buscar y filtrar productos, documentos o artículos. Implementarán un motor de búsqueda utilizando Elasticsearch y configurarán el índice de datos para optimizar la búsqueda.

Conceptos Cubiertos:

  • Indexación y búsqueda de datos.
  • Integración de motores de búsqueda con aplicaciones web.
  • Optimización de índices y consultas de búsqueda.

Herramientas:

  • Elasticsearch
  • Node.js/NestJS
  • Docker

Paso 1: Configuración del Entorno con Docker

1.1. Crear el archivo Dockerfile para Node.js/NestJS:

Crea un archivo llamado Dockerfile en el directorio raíz de tu proyecto:

# Usar la imagen oficial de Node.js
FROM node:18-alpine

# Crear el directorio de la aplicación
WORKDIR /app

# Copiar los archivos de package.json y package-lock.json desde search-app/
COPY search-app/package*.json ./

# Instalar las dependencias de la aplicación
RUN npm install

# Copiar el resto de los archivos de la aplicación desde search-app/
COPY search-app/ .

# Exponer el puerto de la aplicación
EXPOSE 3000

# Comando para iniciar la aplicación
CMD ["npm", "run", "start:dev"]

1.2. Crear el archivo docker-compose.yml:

Crea un archivo llamado docker-compose.yml en el directorio raíz del proyecto:

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.5.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - network.host=0.0.0.0
      - ES_JAVA_OPTS=-Xms1g -Xmx1g  # Ajusta según los recursos disponibles
      - xpack.security.enabled=false  # Deshabilitar seguridad para desarrollo
    ports:
      - '9200:9200'
      - '9300:9300'
    networks:
      - default
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  nestjs-app:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - ./search-app:/app:delegated
      - /app/node_modules
    depends_on:
      - elasticsearch
    environment:
      - ELASTICSEARCH_HOST=${ELASTICSEARCH_HOST}
      - ELASTICSEARCH_PORT=${ELASTICSEARCH_PORT}
    networks:
      - default

networks:
  default:
    driver: bridge

volumes:
  elasticsearch_data:
    driver: local

Manejemos variables de entorno en el archivo docker-compose.yml:

ELASTICSEARCH_HOST=elasticsearch
ELASTICSEARCH_PORT=9200

Este archivo define dos servicios: uno para la aplicación NestJS y otro para Elasticsearch.

Paso 2: Crear la Aplicación NestJS

2.1. Crear una nueva aplicación NestJS

Usa npx para crear una nueva aplicación NestJS:

npx @nestjs/cli new search-app
cd search-app

2.2. Instalar Dependencias de Elasticsearch

Dentro del directorio de tu proyecto, instala las dependencias necesarias para conectarte a Elasticsearch:

npm install @nestjs/elasticsearch elasticsearch

Paso 3: Implementar el Motor de Búsqueda

3.1. Configurar el Módulo de Elasticsearch

Crea un módulo para Elasticsearch en src/elasticsearch/elasticsearch.module.ts:

import { Module } from '@nestjs/common';
import { ElasticsearchModule } from '@nestjs/elasticsearch';
import { MyElasticsearchService } from './elasticsearch.service'; // Cambia ElasticsearchService por MyElasticsearchService

@Module({
  imports: [
    ElasticsearchModule.register({
      node: process.env.ELASTICSEARCH_HOST || 'http://localhost:9200',
    }),
  ],
  providers: [MyElasticsearchService],
  exports: [MyElasticsearchService],
})
export class MyElasticsearchModule {}

3.2. Crear el Serviczio de Elasticsearch

Crea un servicio en src/elasticsearch/elasticsearch.service.ts:

import { Injectable } from '@nestjs/common';
import { ElasticsearchService } from '@nestjs/elasticsearch'; // Esto está bien

@Injectable()
export class MyElasticsearchService {
  constructor(private readonly elasticsearchService: ElasticsearchService) {}

  async indexData(index: string, document: any) {
    return await this.elasticsearchService.index({
      index,
      body: document,
    });
  }

  async search(index: string, query: any) {
    return await this.elasticsearchService.search({
      index,
      body: {
        query,
      },
    });
  }
}

Este servicio proporciona métodos para indexar datos y realizar búsquedas.

3.3. Crear un Controlador para Manejar las Búsquedas

Crea un controlador en src/search/search.controller.ts:

import { Controller, Get, Query } from '@nestjs/common';
import { MyElasticsearchService } from './elasticsearch.service'; // Esto está bien

@Controller('search')
export class SearchController {
  constructor(private readonly elasticsearchService: MyElasticsearchService) {}

  @Get()
  async search(@Query('q') query: string) {
    const results = await this.elasticsearchService.search('products', {
      match: { name: query },
    });
    return results.hits.hits;
  }
}

Este controlador permite a los usuarios buscar productos por nombre.

Paso 4: Probar la Aplicación

4.1 Levanta los servicios con Docker Compose:

docker compose build --no-cache

En el comando anterior se construyen las imágenes de Docker para la aplicación NestJS y Elasticsearch.

docker compose up

En el comando anterior se inician los contenedores de Docker para la aplicación NestJS y Elasticsearch.

Paso 5: Configurar el Índice de Elasticsearch

5.1. Crear el Índice

Para crear un índice en Elasticsearch, puedes agregar un script que se ejecute cuando se inicie la aplicación, o hacerlo manualmente usando cURL:

Paso 6: Probar la Aplicación

Para probar si tu aplicación está funcionando correctamente, puedes seguir estos pasos:

6.1. Verificar el Estado de los Contenedores

Primero, asegúrate de que los contenedores están en ejecución:

docker compose ps

Esto debería mostrar que tanto elasticsearch como nestjs-app están en estado Up.

6.2. Probar Elasticsearch

Verificar la Disponibilidad del Servicio

Puedes verificar si Elasticsearch está funcionando enviando una solicitud HTTP al puerto 9200. Usa curl para hacer una solicitud simple:

curl http://localhost:9200

Deberías recibir una respuesta JSON con información sobre el estado del clúster de Elasticsearch.

Consultar el Estado de Elasticsearch desde el Contenedor de NestJS

Para verificar la conectividad entre los servicios, puedes usar curl dentro del contenedor de NestJS:

docker exec -it laboratorio_indexacion_datos-nestjs-app-1 sh
# Dentro del contenedor
apk add --no-cache curl  # Si `curl` no está instalado
curl http://elasticsearch:9200

Esto debería dar un resultado como este:

Esto verifica si el contenedor de NestJS puede conectarse al servicio de Elasticsearch por nombre de host.

6.3. Probar la Aplicación NestJS

Verificar la Disponibilidad del Servicio de NestJS

Puedes probar si tu aplicación NestJS está funcionando accediendo al puerto 3000:

curl http://localhost:3000

Esto debería devolver la respuesta “Hello World!” u otro mensaje configurado en tu aplicación NestJS.

Verificar la Conectividad con Elasticsearch desde la Aplicación NestJS

Para probar la integración de tu aplicación NestJS con Elasticsearch:

  • Asegúrate de que tu aplicación NestJS tiene configurado correctamente el host y puerto de Elasticsearch.
  • Implementa una ruta en tu aplicación que realice una consulta a Elasticsearch y devuelva los resultados.

Revisar los Logs de los Contenedores

Si encuentras problemas, revisa los logs de los contenedores para identificar errores o mensajes informativos:

docker compose logs elasticsearch
docker compose logs nestjs-app

Esto te ayudará a diagnosticar problemas con la inicialización o la conexión entre los servicios.

Pruebas Adicionales

  • Pruebas Unitarias/Integración:
  • Si has escrito pruebas unitarias o de integración para tu aplicación, asegúrate de ejecutarlas para verificar que todos los componentes funcionan correctamente en conjunto.

Interfaz de Usuario:

  • Si tu aplicación tiene una interfaz de usuario (UI), verifica que las páginas se carguen correctamente y que las funcionalidades (como la búsqueda en Elasticsearch) funcionen según lo esperado.

Reto

  • Implementa datos de prueba para indexar en Elasticsearch, como productos, documentos o artículos.
  • Implementa una funcionalidad de autocompletado en la barra de búsqueda de tu aplicación.
  • Agrega filtros de búsqueda para permitir a los usuarios refinar los resultados por categoría, precio, etc.
  • Implementa paginación para mostrar los resultados de búsqueda en varias páginas.

Conclusión

Este laboratorio proporciona a los estudiantes una introducción completa a la implementación de un sistema de búsqueda e indexación utilizando Elasticsearch y NestJS. Aprenden a configurar un entorno de desarrollo con Docker, indexar datos, y realizar búsquedas optimizadas. Al finalizar, los estudiantes tendrán una comprensión sólida de cómo integrar motores de búsqueda en aplicaciones web y cómo optimizar los índices y consultas para mejorar el rendimiento.