Cómo indexar entidades manualmente en Elasticsearch usando FOSElasticaBundle en Symfony 5

Habrá algunos casos en los que necesitarás indexar tus entidades en Elasticsearch cuando lo necesites específicamente, no cada vez que una entidad se actualice, ya que este es el comportamiento predeterminado de FOSElasticaBundle. Para hacerlo aún más claro, imagina el siguiente caso, donde tienes una entidad llamada Artículos. Cuando creas un artículo, la información se indexa automáticamente en Elasticsearch gracias al paquete, ¡genial! Cuando el artículo se actualiza, también se actualiza en Elasticsearch y cuando se elimina de tu aplicación, también se elimina de Elasticsearch. FOSElasticaBundle ¡es simplemente genial! El problema surge en algunos escenarios cuando necesita este comportamiento, pero necesita establecer específicamente en qué líneas de código se debe indexar, actualizar o eliminar la información. Por ejemplo, si la entidad Artículo almacena el número de visitas que tiene el artículo y cada vez que un nuevo visitante visita el artículo, este número se actualiza, por lo tanto, la entidad también se actualiza y la información en Elasticsearch también se actualiza innecesariamente. Idealmente, la información debería volver a indexarse ​​cuando el autor del artículo actualice el contenido del artículo únicamente, no cuando se actualice alguno de los campos de la entidad.

Con la lógica personalizada, deberías poder saber cuándo debe actualizarse el documento en Elasticsearch y eso es lo que te voy a explicar en este artículo para Symfony 5.

1. Deshabilita la indexación automática de documentos predeterminada

Como mencioné anteriormente, de forma predeterminada, FOSElasticaBundle indexa automáticamente como documentos tus entidades en los eventos del ciclo de vida de doctrine. Por lo tanto, se ejecutará una solicitud a Elascticsearch cuando:

  • insertes
  • actualices
  • Elimines

Cualquier entidad que esté asociada con un índice en Elasticsearch. Como el objetivo de hacerlo manualmente es controlar por nosotros mismos cómo se maneja esto, necesitamos deshabilitar el comportamiento predeterminado de la indexación automática. Esto se puede hacer fácilmente proporcionando un objeto con la propiedad enabled establecida en falso en la clave persistence.listener de tu índice (en nuestro caso, nuestro índice se llama articles):

# app/config/packages/fos_elastica.yaml
fos_elastica:
    clients:
        default: { url: '%env(ELASTICSEARCH_URL)%' }
    indexes:
        articles:
            properties:
                name: ~
                slug: ~
                preview: ~
                content: ~
                tags: ~
            persistence:
                driver: orm
                model: App\Entity\Articles
                # ¡Deshabilita el oyente de persistencia predeterminado!
                listener: { enabled: false }

Esto hará que cuando intentes insertar, actualizar o eliminar cualquier entidad de Artículos en tu base de datos, el índice de Elasticsearch no se actualizará, por lo que básicamente, por ahora, la información estará desactualizada si no actualizas la información manualmente pero eso es lo que vamos a explicar en este artículo.

2. Transferir objeto persister de tu índice

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

# app/config/services.yaml
App\Controller\ExampleController:
        tags: [controller.service_arguments]
        bind:
            # reemplace "articles" con el nombre de tu índice
            FOS\ElasticaBundle\Persister\ObjectPersister $articlesPersister: "@fos_elastica.object_persister.articles"

Alternativamente, puedes vincular el persister donde lo necesites con:

# app/config/services.yaml
services:
    _defaults:
        bind:
            # reemplace "articles" con el nombre de tu índice
            FOS\ElasticaBundle\Persister\ObjectPersister $articlesPersister: "@fos_elastica.object_persister.articles"

3. Indexación manual de datos en Elasticsearch

La idea y el objetivo de este tutorial son cómo indexar los datos de tus entidades en Elasticsearch en lugar de hacerlo automáticamente como lo hace FOSElasticaBundle por defecto. El lugar habitual para seguir el mismo flujo de trabajo pero decidir dónde hacerlo por ti mismo es en el CRUD predeterminado de una entidad dentro de un controlador. En este caso, utilizaremos los 3 métodos de un controlador predeterminado que permite crear, actualizar y eliminar una entidad de Artículos en la aplicación. Todo lo que necesitas hacer es importar el ObjectPersister que usa el índice que necesita (registrado en el paso 2) y llamar a cualquiera de los métodos necesarios para crear, actualizar o eliminar el documento en Elasticsearch:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

// Mi entidad, en este caso artículos
use App\Entity\Articles;

// Importar ObjectPersister
use FOS\ElasticaBundle\Persister\ObjectPersister;

class ExampleController extends AbstractController
{
    // Ejemplo 1. Creando una nueva entidad
    public function new(
        Request $request,
        ObjectPersister $articlesPersister
    ): Response
    {
        $article = new Articles();
        
        // Registrar documento en Elasticsearch
        $articlesPersister->insertOne($article);
    }

    // Ejemplo # 2. Actualizar una entidad existente
    public function edit(
        Request $request, 
        Articles $article,
        ObjectPersister $articlesPersister
    ): Response
    {
        // Actualizar documento en Elasticsearch
        // Tenga en cuenta que para actualizar, el documento debe existir.
        $articlesPersister->replaceOne($article);
    }
    
    // Ejemplo # 3. Eliminar una entidad
    public function delete(
        Request $request,
        Articles $article,
        ObjectPersister $articlesPersister
    ): Response
    {
        // Eliminar documento de Elasticsearch
        $articlesPersister->deleteOne($article);
    }
}

Y así es como puede indexar fácilmente tus entidades manualmente en Elasticsearch a través de FOSElasticaBundle.

Que te diviertas ❤️!

Esto podria interesarte

Conviertete en un programador más sociable