Visión General
Al desarrollar un plugin de almacén de datos, puede agregar a Fess la funcionalidad de obtener contenido desde nuevas fuentes de datos. El almacén de datos obtiene registros de sistemas externos, como bases de datos, API o archivos, los convierte en campos de índice de acuerdo con el script de mapeo configurado en la consola de administración, y los registra en el índice de Fess.
Todos los conectores públicos (fess-ds-*), como CSV, JSON, bases de datos, Git y diversos servicios en la nube, están implementados con este mecanismo. Como plantilla de implementación se publica fess-ds-example, por lo que, al crear un nuevo conector, resulta sencillo comenzar copiando este proyecto.
Estructura Básica
El plugin de almacén de datos se compone de los siguientes tres elementos:
Crear una clase que herede de
AbstractDataStoreImplementar los dos métodos
getName()ystoreData()Registrarla como componente en
fess_ds++.xml
Implementación Mínima
Nota
Tanto getName() como storeData() son métodos abstractos protected. Tenga en cuenta que, en Fess 15.x, el paquete de DataConfig es org.codelibs.fess.opensearch.config.exentity (el anterior org.codelibs.fess.es.config.exentity ha quedado obsoleto).
Registro del Componente
Para que Fess reconozca el almacén de datos creado, registre el componente en src/main/resources/fess_ds++.xml.
Mediante <postConstruct name="register">, tras la creación del componente se invoca automáticamente el método register() que posee AbstractDataStore, y este se registra a sí mismo en DataStoreFactory. El nombre registrado en este momento es el valor devuelto por getName() (ExampleDataStore en el ejemplo anterior), y es el que se selecciona como «nombre del manejador» en la configuración del almacén de datos de la consola de administración.
AbstractDataStore
Métodos Principales
| Método | Categoría | Descripción |
|---|---|---|
getName() | Implementación (obligatoria) | Método abstracto que devuelve el nombre del manejador del almacén de datos. La convención es devolver |
storeData() | Implementación (obligatoria) | Método abstracto que obtiene, convierte y registra los datos en el índice |
register() | Heredado (normalmente no requiere cambios) | Se invoca automáticamente desde el |
store() | Heredado (invocado por el framework) | Punto de entrada invocado por el framework. Prepara |
convertValue() | Heredado (auxiliar) | Evalúa con el motor de scripts el valor (plantilla) de scriptMap |
getScriptType() | Heredado (auxiliar) | Obtiene el parámetro |
getReadInterval() | Heredado (auxiliar) | Obtiene el parámetro readInterval (en milisegundos) |
sleep() | Heredado (auxiliar) | Duerme durante los milisegundos indicados (se utiliza para esperar entre registros) |
Parámetros de storeData
Parámetros que se pasan al método storeData():
| Parámetro | Tipo | Descripción |
|---|---|---|
dataConfig | DataConfig | Configuración del almacén de datos (ID, nombre del manejador, parámetros, scripts, etc.) |
callback | IndexUpdateCallback | Callback para registrar en el índice los documentos generados |
paramMap | DataStoreParams | Valores configurados en el campo «Parámetros» de la consola de administración. Se accede a ellos mediante |
scriptMap | Map<String, String> | Configuración del campo «Script» de la consola de administración. La clave es el nombre del campo de índice, y el valor es la plantilla de script que se evalúa |
defaultDataMap | Map<String, Object> | Valores predeterminados de campo para cada documento (ID de configuración, boost, role, mimetype, host virtual, etc.). El framework los prepara |
Advertencia
El tipo de paramMap no es Map<String, String>, sino DataStoreParams. Dado que DataStoreParams no implementa Map, utilice getAsString(), que devuelve una cadena, en lugar de get() para obtener los valores.
Flujo de Procesamiento de Datos
La implementación de storeData() procesa los datos siguiendo este flujo.
Obtener los registros de origen desde el sistema externo.
Combinar los campos del registro de origen con
paramMap.asMap()para construirresultMap(el script se evalúa sobre esteresultMap).Evaluar cada entrada de
scriptMapconconvertValue(scriptType, template, resultMap)y almacenar el resultado endataMap. Es importante que el mapeo no se codifique de forma fija en el código, sino que lo defina el administrador en el campo «Script».Invocar
callback.store(paramMap, dataMap)para registrar el documento en el índice.
Ejemplo de Implementación
Almacén de Datos Simple
Ejemplo que obtiene registros desde una API externa y los registra en el índice.
fetchRecords() es un método propio que obtiene la lista de registros del sistema externo. Los nombres de los campos de cada registro obtenido (Map<String, Object>) son los nombres que se pueden referenciar desde los scripts de scriptMap. DataStoreException es una clase del paquete org.codelibs.fess.exception.
Soporte de Paginación
Cuando se manejan grandes volúmenes de datos, el procesamiento se realiza obteniendo los registros página por página. Si se extrae el procesamiento por registro (la construcción de resultMap, la evaluación de scriptMap y la llamada a callback.store()) a un método como processRecord(), es posible separarlo de la lógica de obtención.
Implementación de Autenticación
La autenticación con el sistema externo se implementa en el lado del conector. A continuación se muestra un ejemplo de implementación con una biblioteca cliente HTTP habitual; no se trata de una API proporcionada por Fess. Incluya la biblioteca que utilice como dependencia del plugin.
OAuth 2.0
Autenticación con Clave API
Manejo de Errores
Para errores fatales que deben interrumpir el procesamiento, lance DataStoreException.
Nota
En conectores reales, como fess-ds-example, para evitar que el error de un solo registro detenga todo el rastreo, se captura CrawlingAccessException a nivel de registro y se registra la URL con error en FailureUrlService. Además, se controla si se debe interrumpir todo el rastreo mediante el indicador de interrupción de DataStoreCrawlingException. Si desea implementar un conector robusto, consulte la implementación de ExampleDataStore.
Pruebas
Pruebas Unitarias
Los plugins de Fess se prueban utilizando LastaDiTestCase de UTFlute. Las pruebas se escriben con JUnit 5 (Jupiter). Al sustituir IndexUpdateCallback por una implementación que recopila los dataMap registrados, es posible verificar el resultado del mapeo sin utilizar bibliotecas de mocks.
Nota
setUp ya tiene la anotación @BeforeEach en la clase base, por lo que no es necesario volver a añadir anotaciones de ciclo de vida al sobrescribirlo. Cada método de prueba debe llevar la anotación @Test (org.junit.jupiter.api.Test).
Construcción e Instalación
pom.xml
El plugin se construye como un jar que utiliza fess-parent como POM padre. Las dependencias de fess y opensearch se marcan como provided, ya que en tiempo de ejecución las proporciona el propio Fess.
Para las pruebas se utilizan JUnit 5 y org.dbflute.utflute:utflute-lastaflute.
Construcción
Se generará fess-ds-example-15.8.0.jar en el directorio target/.
Instalación
Instale el JAR generado en Fess y reinicie Fess. Para más detalles sobre el procedimiento de instalación, consulte Complemento. Después de la instalación, cree una nueva configuración desde «Rastreador > Almacén de Datos» en la consola de administración y especifique en «Nombre del manejador» el nombre que devuelve getName() (ExampleDataStore en este ejemplo).
Ejemplo de Configuración
Ejemplo de configuración en la consola de administración:
Parámetros
En el campo «Parámetros» se describen las claves y los valores que el conector lee desde paramMap.
Script
En el campo «Script» se describe el mapeo con el formato lado izquierdo=lado derecho. El lado izquierdo es el nombre del campo de índice, y el lado derecho es un script (Groovy de forma predeterminada) que referencia un campo del registro de origen. A continuación se muestra un ejemplo para el caso en que el registro de origen tiene los campos url, title, content, updated_at y content_type.
Nota
Los nombres de campo que se pueden referenciar en el lado derecho dependen de los valores que el conector almacena en resultMap (los valores de paramMap y los campos del registro de origen). En conectores existentes, como CSV o JSON, puede añadirse un prefijo propio como data.*, por lo que debe consultar la documentación de cada conector.
Información de Referencia
Arquitectura de Plugins - Arquitectura de plugins
Complemento - Instalación de plugins
Descripción General de los Conectores de Almacén de Datos - Descripción general de los conectores de almacén de datos
fess-ds-example - Plantilla de implementación de plugins de almacén de datos
GitHub: fess-ds-* - Ejemplos de conectores públicos