Cómo crear tu motor de búsqueda con Elasticsearch 7 y FOSElasticaBundle en Symfony 5

Cómo crear tu motor de búsqueda con Elasticsearch 7 y FOSElasticaBundle en Symfony 5

Elasticsearch es una herramienta útil que te permite almacenar, buscar y analizar grandes volúmenes de datos de forma rápida y en tiempo real, proporcionando respuestas en milisegundos. Puedes pensar en Elasticsearch como un servidor que puede procesar solicitudes JSON y devolverte datos JSON de acuerdo con los parámetros dados. Elasticsearch es extremadamente útil para aplicaciones que dependen en gran medida de una plataforma de búsqueda para el acceso, la recuperación y la generación de informes de datos, así como para búsquedas efectivas y precisas.

En este artículo, te explicaré cómo interactuar con tu servidor Elasticsearch en tu proyecto de Symfony 5.

Requisitos

Para seguir este artículo, asumiremos que ya tienes un servidor Elasticsearch en funcionamiento. En nuestro caso, usaremos una instancia local de Elasticsearch v7.12 que se ejecuta a través de Docker y está disponible en http://localhost:9200/.

Teniendo esto en cuenta, comencemos con el tutorial.

1. Instala FOSElasticaBundle

Para interactuar con tu servidor Elasticsearch en Symfony, la mejor forma de hacerlo es a través del FOSElasticaBundle. Este paquete te ayuda a:

  • Integra la biblioteca Elastica en un entorno Symfony (Elastica en sí mismo es un cliente PHP para Elasticsearch).
  • Utilice JmsSerializer o Symfony Serializer para convertir entre objetos PHP y datos de Elasticsearch.
  • Indexa la configuración para Elasticsearch o envía datos sin configuración para usar la función de mapeo dinámico de Elasticsearch
  • Oyentes de eventos de Doctrine para indexación automática

Hasta la fecha, el soporte para Elasticsearch v7 solo está disponible en la versión beta de FOSElasticaBundle (v6.0.0-beta3). Para instalar esta versión, ejecute el siguiente comando (tenga en cuenta que hasta la fecha, la versión v6 no está disponible, si está disponible, instálela en su lugar):

composer require friendsofsymfony/elastica-bundle v6.0.0-beta3

Una vez que finalice la instalación, procede con los pasos de configuración. Para obtener más información sobre este paquete, visita el repositorio oficial en Github aquí.

2. Configurar la URL de acceso

En tu archivo .env, encontrarás una nueva propiedad que indicará el endpoint de Elasticsearch:

# project/.env
###> friendsofsymfony/elastica-bundle ###
ELASTICSEARCH_URL=http://localhost:9200/
###< friendsofsymfony/elastica-bundle ###

En caso de que no lo esté, defínelo y reemplaze su valor con el endpoint.

3. Crear entidad de ejemplo

La idea del motor de búsqueda en este ejemplo es buscar algunos artículos con una palabra clave determinada. Los artículos se almacenan en una base de datos MySQL y Doctrine se usa como ORM, la entidad se ve así:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Articles
 *
 * @ORM\Table(name="articles")
 * @ORM\Entity(repositoryClass="App\Repository\ArticlesRepository")
 */
class Articles
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="slug", type="string", length=255, nullable=false)
     */
    private $slug;
    
    /**
     * @var string|null
     *
     * @ORM\Column(name="preview", type="string", length=255, nullable=true, options={"default"="NULL"})
     */
    private $preview;
    
    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text", length=0, nullable=false)
     */
    private $content;

    /**
     * @var string|null
     *
     * @ORM\Column(name="tags", type="string", length=255, nullable=true, options={"default"="NULL"})
     */
    private $tags;
}

Los artículos se almacenaran en Elasticsearch indicando esta entidad más adelante. Asegúrate de que algunos artículos hayan sido guardados ya en tu base de datos.

4. Configurar índices

En Elasticsearch, un índice se puede considerar como una colección optimizada de documentos y cada documento es una colección de campos, que son los pares clave-valor que contienen sus datos. De forma predeterminada, Elasticsearch indexa todos los datos en cada campo y cada campo indexado tiene una estructura de datos dedicada y optimizada. En este caso, podemos crear un índice para la entidad artículos, que almacenará las propiedades definidas en mi entidad, usando la entidad Artículos como modelo. Puede definir todos sus índices en el archivo fos_elastica.yaml de esta manera:

# app/config/packages/fos_elastica.yaml
# Read the documentation: https://github.com/FriendsOfSymfony/FOSElasticaBundle/blob/master/doc/setup.md
fos_elastica:
    clients:
        default: { url: '%env(ELASTICSEARCH_URL)%' }
    indexes:
        articles:
            properties:
                name: ~
                slug: ~
                preview: ~
                content: ~
                tags: ~
            persistence:
                driver: orm
                model: App\Entity\Articles

5. Crea índices

Ahora, debe crear los índices en Elasticsearch. Esto se puede hacer fácilmente ejecutando el siguiente comando:

php bin/console fos:elastica:create

6. Adquirir datos

Finalmente, puedes completar la información de la tabla en Elasticsearch ejecutando el siguiente comando:

php bin/console fos:elastica:populate

Esto generará una salida similar a la siguiente:

Resetting articles
    0/1480 [>---------------------------]   0%
  200/1480 [===>------------------------]  13%
  300/1480 [=====>----------------------]  20%
  500/1480 [=========>------------------]  33%
  600/1480 [===========>----------------]  40%
  800/1480 [===============>------------]  54%
  900/1480 [=================>----------]  60%
 1100/1480 [====================>-------]  74%
 1200/1480 [======================>-----]  81%
 1400/1480 [==========================>-]  94%
 1480/1480 [============================] 100%
Populating articles Refreshing articles

Como puedes ver, en la tabla de artículos de mi base de datos, hay 1480 entidades de artículos que ahora se han indexado en Elasticsearch, por lo que ahora podemos ejecutar algunas consultas en el motor dentro de los controladores o servicios del proyecto Symfony.

7. Registrar buscador

Hay varias formas en las que puedes ejecutar algunas consultas en Elasticsearch a través de Elastica, puedes consultar la información detallada sobre ellas en esta página. En este ejemplo, procederemos con el ejemplo más básico, para que puedas investigar más sobre la búsqueda avanzada más adelante.

Lo primero que debes hacer es registrar el buscador para su índice en tu archivo services.yaml. Dependiendo de tus necesidades, puedes registrar el buscador en un solo controlador o servicio como este:

# app/config/services.yaml
App\Controller\ExampleController:
        tags: [controller.service_arguments]
        bind:
            # replace "articles" with the name of your index
            # and replace the class of the Finder 
            FOS\ElasticaBundle\Finder\TransformedFinder $articlesFinder: '@fos_elastica.finder.articles'

Para que puedas obtener el servicio solo en el controlador específico:

<?php

// app/src/Controller/ExampleController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use FOS\ElasticaBundle\Finder\TransformedFinder;
use Elastica\Util;

class ExampleController extends AbstractController
{
    public function someAction(TransformedFinder $articlesFinder) : Response
    {
        // do something with $articlesFinder
    }
}

Alternativamente, puedes vincular el buscador donde lo necesites con:

# app/config/services.yaml
services:
    _defaults:
        # replace "articles" with the name of your index
        # and replace the class of the Finder 
        bind:
            FOS\ElasticaBundle\Finder\TransformedFinder $articlesFinder: '@fos_elastica.finder.articles'

8. Ejecución de una búsqueda

Como último paso, ahora puedes probar si todo funciona como se esperaba ejecutando algunas consultas. Este ejemplo ejecutará una consulta en el índice de artículos y devolverá todas las entidades que coincidan con tus términos de búsqueda. En este caso, se ejecutará dentro de un controlador:

<?php

// app/src/Controller/ExampleController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use FOS\ElasticaBundle\Finder\TransformedFinder;
use Elastica\Util;

class ExampleController extends AbstractController
{
    public function someAction(TransformedFinder $articlesFinder) : Response
    {
        $search = Util::escapeTerm("Bleu de channel parfum");
        
        $result = $articlesFinder->findHybrid($search, 10);
        
        dump($result);
        
        return $this->render("views/empty.html.twig");
    }
}

El contenido volcado se ve así, por lo que todos los artículos que coinciden con la búsqueda "Bleu de channel parfum":

Elasticsearch Results Hybrid

La documentación de Elasticsearch y Elastica es bastante extensa, así que no olvides consultar la documentación para ver ejemplos más avanzados de cómo interactuar con Elasticsearch en tu aplicación Symfony 5.

Que te diviertas ❤️!

Esto podria interesarte

Conviertete en un programador más sociable