Indexer Post Processor. ¿Lo conoces?

28 de octubre de 2022

Liferay tiene innumerables componentes, algunos más conocidos que otros.

Os cuento mi nuevo descubrimiento: Indexer Post Processor.

1. Antecedentes

Como sabemos, Liferay utiliza un motor de búsqueda que por defecto es Elasticsearch.

A grandes rasgos, Elasticsearch usa un Indexador para convertir las entidades de la base de datos en un objeto JSON llamado documento y que usaremos para realizar las búsquedas.

Este Indexador especifica qué campos de nuestra entidad se deben agregar a cada documento.

Aquí tenemos un ejemplo para la entidad JournalArticle

La categoría a la que pertenece un contenido, también aparece en este documento, de la siguiente forma.

2. Requerimiento

Hace poco en un proyecto se nos planteó la necesidad de ordenar los contenidos por categorías. ¿Pero cómo ordenar por un campo que se define como no ordenable? ¿Y si además queremos añadir algún otro criterio?

Imaginaos que necesito ordenar los contenidos de la siguiente forma:

  1. Los contenidos que pertenezcan a la categoría 70000 aparezcan en primer lugar.
    
  2. Los contenidos con título testing article en segundo lugar.
    
  3. Los contenidos creados por userName test en último lugar.
    

3. Solución

Después de valorar las alternativas que teníamos, todas ellas muy costosas, estuve revisando la documentación de Liferay y de pronto me encontré con esto.

Según la documentación,uno de los posibles usos del IndexerPostProcessor es modificar los Documents antes de que sean enviados al motor de búsqueda.

Así que, podría añadir un nuevo parámetro al Document del JournalArticle, para poder usarlo luego en la búsqueda.

4. Implementación

Para añadir un nuevo IndexerPostProcessor hay que seguir estos pasos.

  1. Implementar la interfaz com.liferay.portal.kernel.search.IndexerPostProcessor
  2. Publicarlo en OSGI con la propiedad indexer.class.name. En nuestro caso com.liferay.journal.model.JournalArticle.

Esta interfaz sobrescribe varios métodos pero nosotros nos vamos a centrar en el que nos interesa que es este:


@Component(immediate = true,
        property = {"indexer.class.name=com.liferay.journal.model.JournalArticle"},
        service = IndexerPostProcessor.class)


public class JournalArticlePostProcessor implements IndexerPostProcessor {


    @Override
    public void postProcessDocument(Document document, Object obj) {
        
            final JournalArticle journalArticle = (JournalArticle) obj;
            
            int order = populateOrder(journalArticle);
            
            document.addNumberSortable("order", order);
        
    }
}

postProcessDocument recibe 2 parámetros:

Calcula el orden de cada journalArticle y lo añade al documento.

Al desplegar el componente comprobamos su funcionamiento cada vez que es necesario llamar al Indexador, por ejemplo, al salvar el contenido. Si queremos que este campo aparezca en todos los documentos tendremos que lanzar una reindexación completa de la entidad.

Una vez reindexado aparecerá este nuevo campo en cada documento:

"order_Number_sortable": 1

Lo único que nos queda es añadir la funcionalidad en el searchContext para implementar el orden.

SearchContext searchContext = SearchContextFactory.getInstance(PortalUtil.getHttpServletRequest(request));
Sort order = new Sort("order_Number_sortable",Sort.INT_TYPE, Boolean.FALSE)
searchContext.setSorts(new Sort[] {order});

4. Conclusión

Conocer todos los componentes que ofrece Liferay además de sus usos, nos permite aportar la solución adecuada en cada momento.

5. Más Información

Podéis encontrar más información en los links en los que me he basado para redactar este post:

https://help.liferay.com/hc/es/articles/360018170871-Indexer-Post-Processor

https://github.com/liferay/liferay-blade-samples/tree/7.4/liferay-workspace/extensions/indexer-post-processor

Sobre el autor: Mirian Arrabal Trigueros

Desarrolladora Liferay y friki en mis tiempos libres.

Comments
Únete a nosotros