From c1418d8c5e8fbc1cec6353a5f34675ca6090c5ae Mon Sep 17 00:00:00 2001 From: Shinsuke Sugaya Date: Thu, 16 Jul 2026 02:02:10 +0900 Subject: [PATCH] docs(dev): correct and expand 15.8 Ingest plugin guide against implementation The Ingest plugin guide described an API that does not exist in the source. Rewrite it to match the actual implementation and apply the fix to all languages. - Replace the non-existent ``IngestHandler`` interface with the real ``org.codelibs.fess.ingest.Ingester`` abstract class and its four ``process`` overloads (Map, Map+DataStoreParams, Map+AccessResult, ResultData+ResponseData), noting which one to override. - Correct registration to ``fess_ingest++.xml`` (DI merge convention) with ```` calling ``Ingester#register()``. - Remove the fabricated ``ingest.handler.example.enabled`` property; there are no ingest-related ``fess_config.properties`` settings. - Document ``priority``-based execution order (default 99, ascending), the three invocation points in the crawl/index pipeline, the null-return caveat, and reference implementations (fess-ingest-example, fess-webapp-multimodal). - Update ja and re-translate en/de/fr/es/ko/zh-cn (diacritics preserved). --- de/15.8/dev/ingest-plugin.rst | 175 ++++++++++++++++++++++------ en/15.8/dev/ingest-plugin.rst | 167 +++++++++++++++++++++------ es/15.8/dev/ingest-plugin.rst | 190 ++++++++++++++++++++++++------- fr/15.8/dev/ingest-plugin.rst | 184 +++++++++++++++++++++++------- ja/15.8/dev/ingest-plugin.rst | 149 ++++++++++++++++++------ ko/15.8/dev/ingest-plugin.rst | 148 ++++++++++++++++++------ zh-cn/15.8/dev/ingest-plugin.rst | 144 +++++++++++++++++------ 7 files changed, 906 insertions(+), 251 deletions(-) diff --git a/de/15.8/dev/ingest-plugin.rst b/de/15.8/dev/ingest-plugin.rst index 7c728ab0d..5f6fd8b15 100644 --- a/de/15.8/dev/ingest-plugin.rst +++ b/de/15.8/dev/ingest-plugin.rst @@ -5,74 +5,177 @@ Ingest-Plugin Übersicht ========= -Ingest-Plugins bieten Funktionen zur Verarbeitung und Transformation von Daten, -bevor Dokumente im Index registriert werden. +Ingest-Plugins bieten eine Funktion zur Verarbeitung und Transformation von +Daten, unmittelbar bevor Dokumente im Index registriert werden. Jedes durch +den Crawl abgerufene Dokument durchläuft vor der Übermittlung an den Index +die registrierten Ingester. -Anwendungsfalle +Anwendungsfälle =============== -- Textnormalisierung (z.B. Vollbreite/Halbbreite-Konvertierung) -- Hinzufugen von Metadaten +- Textnormalisierung (z. B. Konvertierung zwischen Vollbreiten- und + Halbbreitenzeichen, Formatierung von Leerzeichen usw.) +- Hinzufügen von Metadaten oder benutzerdefinierten Feldern - Maskierung sensibler Informationen -- Hinzufugen benutzerdefinierter Felder +- Umwandlung von Werten (z. B. Dekodierung kodierter Vektor-Embeddings) -Grundimplementierung -==================== +Ingester-Klasse +=============== + +Die Ingest-Funktion wird implementiert, indem die abstrakte Klasse +``org.codelibs.fess.ingest.Ingester`` erweitert wird. ``Ingester`` stellt +``process``-Methoden bereit, die je nach Crawl-Typ und Verarbeitungsphase +aufgerufen werden. Da alle Standardimplementierungen das empfangene +``target`` unverändert zurückgeben (also nichts tun), müssen nur die +benötigten Methoden überschrieben werden. + +- ``protected Map process(Map target)`` + + Dies ist das gemeinsame Delegationsziel der beiden ``Map``-Varianten der + Methode. Wird diese Methode überschrieben, gilt sie sowohl für Dokumente + aus dem Datenspeicher-Crawl als auch für Dokumente aus dem Web-/Datei-Crawl + (bei der Indexregistrierung). Für die meisten Anwendungsfälle genügt es, + nur diese Methode zu überschreiben. + +- ``public Map process(Map target, DataStoreParams params)`` + + Wird beim Datenspeicher-Crawl aufgerufen. Standardmäßig wird an + ``process(target)`` delegiert. + +- ``public Map process(Map target, AccessResult accessResult)`` + + Wird bei der Indexregistrierung im Web-/Datei-Crawl aufgerufen. + Standardmäßig wird an ``process(target)`` delegiert. + +- ``public ResultData process(ResultData target, ResponseData responseData)`` + + Wird bei der Antwortverarbeitung im Web-/Datei-Crawl aufgerufen (bevor das + Zugriffsergebnis gespeichert wird). Standardmäßig wird ``target`` + unverändert zurückgegeben. + +Ausführungsreihenfolge (priority) +---------------------------------- + +Wenn mehrere Ingester registriert sind, werden sie in aufsteigender +Reihenfolge des Felds ``priority`` ausgeführt (kleinere Werte zuerst). Der +Standardwert ist ``99``. Er kann direkt im Konstruktor gesetzt oder über +``setPriority(int)`` geändert werden. + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) + +Implementierungsbeispiel +========================= -Implementieren Sie das ``IngestHandler``-Interface: +Ein Beispiel, bei dem ``process(Map)`` überschrieben wird, +um den Inhalt zu normalisieren und ein benutzerdefiniertes Feld +hinzuzufügen: .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // Ausführungsreihenfolge festlegen (kleinere Werte werden zuerst ausgeführt; Standard ist 99) + setPriority(50); + } @Override - public Map process(Map document) { - // Inhaltsnormalisierung - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + protected Map process(final Map target) { + // Normalisierung des Inhalts + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } - // Benutzerdefiniertes Feld hinzufugen - document.put("processed_at", new Date()); - - return document; - } + // Hinzufügen eines benutzerdefinierten Felds + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - private String normalizeText(String text) { - // Normalisierungslogik - return text.trim().replaceAll("\\s+", " "); + // Das verarbeitete Dokument zurückgeben + return target; } } +.. note:: + + Wenn die ``process``-Methode ``null`` zurückgibt, schlägt die + Indexregistrierung fehl. Da es keinen Mechanismus zum Überspringen von + Dokumenten gibt, muss stets ``target`` zurückgegeben werden. + Registrierung ============= -``fess_ingest.xml``: +Ingester werden über den DI-Container registriert. Das Plugin enthält dafür +die Datei ``fess_ingest++.xml``. Das ``++`` am Ende des Dateinamens ist eine +Merge-Konvention, mit der die Konfiguration an die Datei +``fess_ingest.xml`` (welche die ``ingestFactory``, die die Ingester +verwaltet, definiert) der |Fess|-Kernanwendung angehängt wird. .. code-block:: xml - - - + + + + + + + -Konfiguration -============= +Durch ```` wird nach der Erzeugung der +Komponente ``Ingester#register()`` aufgerufen, wodurch sie sich selbst bei +der ``ingestFactory`` registriert. + +Für die Ingest-Funktion gibt es keine Konfigurationseinträge in +``fess_config.properties``. Aktivierung bzw. Deaktivierung erfolgt durch das +Vorhandensein des Plugins, und die Ausführungsreihenfolge wird über +``priority`` gesteuert. + +Ausführungsablauf +================== + +Ingester werden unmittelbar bevor das verarbeitete Dokument an den Index +übermittelt wird, an den folgenden Stellen in aufsteigender Reihenfolge von +``priority`` aufgerufen: + +- **Datenspeicher-Crawl**: Unmittelbar bevor das Dokument gesendet wird, + wird ``process(Map, DataStoreParams)`` aufgerufen. +- **Web-/Datei-Crawl (bei der Antwortverarbeitung)**: Bevor das + Crawl-Ergebnis gespeichert wird, wird ``process(ResultData, ResponseData)`` + aufgerufen. +- **Web-/Datei-Crawl (bei der Indexregistrierung)**: Unmittelbar bevor das + Dokument gesendet wird, wird ``process(Map, AccessResult)`` aufgerufen. + +In allen Fällen wird, wenn ein Ingester eine Ausnahme auslöst, eine +Warnmeldung protokolliert und die Verarbeitung fortgesetzt (die +Indexregistrierung des betreffenden Dokuments wird dadurch nicht +abgebrochen). + +.. note:: + + Da Ingester in der Ausführungsumgebung des Crawlers (``ingestFactory``) + registriert werden, arbeiten sie als Teil des Crawl-Prozesses. -``fess_config.properties``: +Referenzimplementierungen +========================== -:: +Als Referenz für die Implementierung sind die folgenden Plugins auf GitHub +unter `CodeLibs `__ veröffentlicht: - ingest.handler.example.enabled=true +- ``fess-ingest-example`` - Minimalistische Beispielimplementierung +- ``fess-webapp-multimodal`` - Plugin mit ``EmbeddingIngester``, der + Vektor-Embeddings dekodiert Referenzinformationen -===================== +====================== - :doc:`plugin-architecture` - Plugin-Architektur diff --git a/en/15.8/dev/ingest-plugin.rst b/en/15.8/dev/ingest-plugin.rst index fd767d43d..133bbfcae 100644 --- a/en/15.8/dev/ingest-plugin.rst +++ b/en/15.8/dev/ingest-plugin.rst @@ -6,74 +6,169 @@ Overview ======== Ingest plugins provide functionality to process and transform data -before documents are registered in the index. +immediately before a document is registered in the index. Each document +retrieved by a crawl passes through the registered Ingesters before it is +sent to the index. Use Cases ========= -- Text normalization (full-width/half-width conversion, etc.) -- Adding metadata +- Text normalization (full-width/half-width conversion, whitespace formatting, etc.) +- Adding metadata or custom fields - Masking sensitive information -- Adding custom fields +- Value conversion (e.g., decoding encoded vector embeddings) -Basic Implementation -==================== +Ingester Class +============== -Implement the ``IngestHandler`` interface: +Ingest functionality is implemented by extending the +``org.codelibs.fess.ingest.Ingester`` abstract class. ``Ingester`` provides +``process`` methods that are invoked depending on the type of crawl and the +processing stage. Since the default implementations simply return the +received ``target`` unchanged (i.e., do nothing), you only need to override +the methods you actually need. + +- ``protected Map process(Map target)`` + + This is the common delegation target for the two ``Map``-based methods. + Overriding this method applies it to documents from both data store crawls + and web/file crawls (at index registration time). For most use cases, + overriding only this method is sufficient. + +- ``public Map process(Map target, DataStoreParams params)`` + + Called during a data store crawl. By default, it delegates to + ``process(target)``. + +- ``public Map process(Map target, AccessResult accessResult)`` + + Called when registering a document from a web/file crawl into the index. + By default, it delegates to ``process(target)``. + +- ``public ResultData process(ResultData target, ResponseData responseData)`` + + Called during response processing of a web/file crawl (before the access + result is saved). By default, it returns ``target`` unchanged. + +Execution Order (priority) +--------------------------- + +When multiple Ingesters are registered, they are executed in ascending +order of the ``priority`` field (lower values run first). The default +value is ``99``. You can set it directly in the constructor, or change it +using ``setPriority(int)``. + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) + +Implementation Example +======================= + +The following example overrides ``process(Map)`` to +normalize the content and add a custom field: .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // Set the execution order (lower values execute first; default is 99) + setPriority(50); + } @Override - public Map process(Map document) { - // Content normalization - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + protected Map process(final Map target) { + // Normalize the content + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } - // Add custom field - document.put("processed_at", new Date()); - - return document; - } + // Add a custom field + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - private String normalizeText(String text) { - // Normalization logic - return text.trim().replaceAll("\\s+", " "); + // Return the processed document + return target; } } +.. note:: + + Returning ``null`` from the ``process`` method will cause index + registration to fail. There is no mechanism for skipping a document, + so always return ``target``. + Registration ============ -``fess_ingest.xml``: +Ingesters are registered via the DI container. Include ``fess_ingest++.xml`` +in your plugin. The ``++`` suffix in the file name follows the merge +convention that appends the configuration to |Fess|'s own +``fess_ingest.xml`` (which defines the ``ingestFactory`` that manages +Ingesters). .. code-block:: xml - - - + + + + + + + -Configuration -============= +With ````, ``Ingester#register()`` is +called after the component is created, registering itself with the +``ingestFactory``. -``fess_config.properties``: +There are no ``fess_config.properties`` settings related to the Ingest +functionality. Whether it is enabled or disabled is determined by whether +the plugin is installed, and the execution order is controlled by +``priority``. -:: +Execution Flow +============== - ingest.handler.example.enabled=true +Ingesters are called, in ascending order of ``priority``, immediately +before the processed document is sent to the index, at the following +points: -Reference -========= +- **Data store crawl**: ``process(Map, DataStoreParams)`` is called + immediately before the document is sent. +- **Web/file crawl (response processing)**: ``process(ResultData, + ResponseData)`` is called before the crawl result is saved. +- **Web/file crawl (index registration)**: ``process(Map, AccessResult)`` + is called immediately before the document is sent. -- :doc:`plugin-architecture` - Plugin Architecture +In every case, if an Ingester throws an exception, a warning is logged and +processing continues (index registration of that document is not +interrupted). +.. note:: + + Since Ingesters are registered in the crawler's runtime environment + (``ingestFactory``), they operate as part of the crawl process. + +Reference Implementations +========================== + +For reference, the following plugins are published on GitHub under +`CodeLibs `__: + +- ``fess-ingest-example`` - A minimal sample implementation +- ``fess-webapp-multimodal`` - A plugin that includes ``EmbeddingIngester``, which decodes vector embeddings + +References +========== + +- :doc:`plugin-architecture` - Plugin Architecture diff --git a/es/15.8/dev/ingest-plugin.rst b/es/15.8/dev/ingest-plugin.rst index 4f056129f..7bcc7c9a7 100644 --- a/es/15.8/dev/ingest-plugin.rst +++ b/es/15.8/dev/ingest-plugin.rst @@ -2,77 +2,181 @@ Plugin Ingest ================================== -Vision General +Visión General ============== -Los plugins Ingest proporcionan funcionalidad para procesar y transformar -datos antes de que los documentos se registren en el indice. +Los plugins Ingest proporcionan la funcionalidad de procesar y transformar +datos justo antes de que los documentos se registren en el índice. Cada +documento obtenido mediante el rastreo pasa por los Ingester registrados +antes de enviarse al índice. Casos de Uso ============ -- Normalizacion de texto (conversion de ancho completo/medio, etc.) -- Adicion de metadatos -- Enmascaramiento de informacion sensible -- Adicion de campos personalizados +- Normalización de texto (conversión de ancho completo/medio, ajuste de + espacios en blanco, etc.) +- Adición de metadatos y campos personalizados +- Enmascaramiento de información sensible +- Conversión de valores (por ejemplo: decodificación de embeddings + vectoriales codificados) -Implementacion Basica -===================== +Clase Ingester +============== + +La funcionalidad de Ingest se implementa heredando de la clase abstracta +``org.codelibs.fess.ingest.Ingester``. ``Ingester`` proporciona métodos +``process`` que se invocan según el tipo de rastreo y la etapa de +procesamiento. Dado que todas las implementaciones por defecto devuelven +el ``target`` recibido tal cual (sin hacer nada), solo es necesario +sobrescribir los métodos que se necesiten. + +- ``protected Map process(Map target)`` + + Es el destino común de delegación de las dos versiones de métodos + ``Map``. Si se sobrescribe, se aplica tanto a los documentos del + rastreo de almacén de datos como a los del rastreo web/de archivos + (durante el registro en el índice). Para la mayoría de los casos de + uso, basta con sobrescribir únicamente este método. + +- ``public Map process(Map target, DataStoreParams params)`` + + Se invoca durante el rastreo de almacén de datos. Por defecto, + delega en ``process(target)``. + +- ``public Map process(Map target, AccessResult accessResult)`` + + Se invoca durante el registro en el índice del rastreo web/de + archivos. Por defecto, delega en ``process(target)``. + +- ``public ResultData process(ResultData target, ResponseData responseData)`` + + Se invoca durante el procesamiento de la respuesta del rastreo + web/de archivos (antes de guardar el resultado de acceso). Por + defecto, devuelve el ``target`` tal cual. + +Orden de ejecución (priority) +----------------------------- + +Cuando hay varios Ingester registrados, se ejecutan en orden ascendente +del campo ``priority`` (los valores más pequeños se ejecutan primero). +El valor por defecto es ``99``. Se puede establecer directamente en el +constructor o modificar mediante ``setPriority(int)``. + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) -Implemente la interfaz ``IngestHandler``: +Ejemplo de Implementación +========================= + +Ejemplo que sobrescribe ``process(Map)`` para normalizar +el contenido y añadir un campo personalizado: .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // Establece el orden de ejecución (los valores más pequeños se ejecutan primero; el valor por defecto es 99) + setPriority(50); + } @Override - public Map process(Map document) { - // Normalizacion de contenido - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + protected Map process(final Map target) { + // Normalización del contenido + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } - // Adicion de campo personalizado - document.put("processed_at", new Date()); - - return document; - } + // Adición de un campo personalizado + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - private String normalizeText(String text) { - // Logica de normalizacion - return text.trim().replaceAll("\\s+", " "); + // Devuelve el documento procesado + return target; } } +.. note:: + + Si el método ``process`` devuelve ``null``, el registro en el + índice fallará. Como no existe un mecanismo para omitir documentos, + asegúrese siempre de devolver ``target``. + Registro ======== -``fess_ingest.xml``: +Los Ingester se registran a través del contenedor DI. El plugin debe +incluir ``fess_ingest++.xml``. El sufijo ``++`` al final del nombre del +archivo es una convención de fusión que añade la configuración a +``fess_ingest.xml`` (que define ``ingestFactory``, encargado de +gestionar los Ingester) del núcleo de |Fess|. .. code-block:: xml - - - - -Configuracion -============= - -``fess_config.properties``: - -:: - - ingest.handler.example.enabled=true - -Informacion de Referencia -========================= + + + + + + + + +Gracias a ````, tras crear el componente +se invoca ``Ingester#register()``, con lo que se registra a sí mismo en +``ingestFactory``. + +No existen elementos de configuración relacionados con la +funcionalidad de Ingest en ``fess_config.properties``. La activación o +desactivación depende de si el plugin está instalado, y el orden de +ejecución se controla mediante ``priority``. + +Flujo de Ejecución +================== + +Los Ingester se invocan en orden ascendente de ``priority`` justo antes +de que el documento procesado se envíe al índice, en los siguientes +puntos: + +- **Rastreo de almacén de datos**: se invoca + ``process(Map, DataStoreParams)`` justo antes de enviar el documento. +- **Rastreo web/de archivos (procesamiento de la respuesta)**: se + invoca ``process(ResultData, ResponseData)`` antes de guardar el + resultado del rastreo. +- **Rastreo web/de archivos (registro en el índice)**: se invoca + ``process(Map, AccessResult)`` justo antes de enviar el documento. + +En cualquiera de estos puntos, si un Ingester lanza una excepción, se +emite un registro de advertencia y el procesamiento continúa (el +registro en el índice de ese documento no se interrumpe). + +.. note:: + + Dado que los Ingester se registran en el entorno de ejecución del + rastreador (``ingestFactory``), funcionan como parte del proceso + de rastreo. + +Implementación de Referencia +============================ + +Como referencia de implementación, los siguientes plugins están +publicados en `CodeLibs `__ en GitHub: + +- ``fess-ingest-example`` - Implementación de ejemplo con la + configuración mínima +- ``fess-webapp-multimodal`` - Plugin que incluye ``EmbeddingIngester``, + encargado de decodificar embeddings vectoriales + +Información de Referencia +========================== - :doc:`plugin-architecture` - Arquitectura de plugins diff --git a/fr/15.8/dev/ingest-plugin.rst b/fr/15.8/dev/ingest-plugin.rst index 2a388d17e..12dfb7f75 100644 --- a/fr/15.8/dev/ingest-plugin.rst +++ b/fr/15.8/dev/ingest-plugin.rst @@ -5,74 +5,178 @@ Plugin Ingest Vue d'ensemble ============== -Les plugins Ingest fournissent des fonctionnalites de traitement et de transformation -des donnees avant leur enregistrement dans l'index. +Les plugins Ingest fournissent une fonctionnalité de traitement et de +transformation des données juste avant que les documents ne soient +enregistrés dans l'index. Chaque document récupéré lors du crawl passe +par les Ingester enregistrés avant d'être envoyé à l'index. Cas d'utilisation ================= -- Normalisation du texte (conversion pleine largeur/demi-largeur, etc.) -- Ajout de metadonnees +- Normalisation du texte (conversion pleine largeur/demi-largeur, + mise en forme des espaces, etc.) +- Ajout de métadonnées ou de champs personnalisés - Masquage d'informations sensibles -- Ajout de champs personnalises +- Conversion de valeurs (par exemple : décodage d'embeddings vectoriels + encodés) -Implementation de base -====================== +Classe Ingester +=============== -Implementez l'interface ``IngestHandler``: +La fonctionnalité Ingest s'implémente en héritant de la classe abstraite +``org.codelibs.fess.ingest.Ingester``. ``Ingester`` fournit des méthodes +``process`` appelées selon le type de crawl et l'étape de traitement. +Les implémentations par défaut renvoient toutes le ``target`` reçu tel +quel (elles ne font rien), il suffit donc de ne surcharger que les +méthodes nécessaires. + +- ``protected Map process(Map target)`` + + Point de délégation commun aux deux méthodes basées sur ``Map``. En la + surchargeant, elle s'applique aux documents du crawl de datastore ainsi + qu'à ceux du crawl Web/fichier (lors de l'enregistrement dans l'index). + Pour de nombreux cas d'usage, surcharger uniquement cette méthode + suffit. + +- ``public Map process(Map target, DataStoreParams params)`` + + Appelée lors du crawl de datastore. Par défaut, elle délègue à + ``process(target)``. + +- ``public Map process(Map target, AccessResult accessResult)`` + + Appelée lors de l'enregistrement dans l'index pour le crawl Web/fichier. + Par défaut, elle délègue à ``process(target)``. + +- ``public ResultData process(ResultData target, ResponseData responseData)`` + + Appelée lors du traitement de la réponse pour le crawl Web/fichier + (avant l'enregistrement du résultat d'accès). Par défaut, elle renvoie + ``target`` tel quel. + +Ordre d'exécution (priority) +---------------------------- + +Lorsque plusieurs Ingester sont enregistrés, ils s'exécutent par ordre +croissant du champ ``priority`` (les valeurs les plus petites en +premier). La valeur par défaut est ``99``. Elle peut être définie +directement dans le constructeur ou modifiée via ``setPriority(int)``. + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) + +Exemple d'implémentation +======================== + +Exemple de surcharge de ``process(Map)`` qui normalise +le contenu et ajoute un champ personnalisé : .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // Définit l'ordre d'exécution (plus la valeur est petite, plus tôt l'exécution a lieu ; la valeur par défaut est 99) + setPriority(50); + } @Override - public Map process(Map document) { + protected Map process(final Map target) { // Normalisation du contenu - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } - // Ajout d'un champ personnalise - document.put("processed_at", new Date()); + // Ajout d'un champ personnalisé + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - return document; - } - - private String normalizeText(String text) { - // Logique de normalisation - return text.trim().replaceAll("\\s+", " "); + // Renvoie le document traité + return target; } } +.. note:: + + Si la méthode ``process`` renvoie ``null``, l'enregistrement dans + l'index échoue. Comme il n'existe aucun mécanisme pour ignorer un + document, veillez à toujours renvoyer ``target``. + Enregistrement ============== -``fess_ingest.xml``: +Les Ingester s'enregistrent via le conteneur DI. Le plugin doit inclure +``fess_ingest++.xml``. Le suffixe ``++`` à la fin du nom de fichier +correspond à la convention de fusion qui ajoute la configuration au +fichier ``fess_ingest.xml`` du cœur de |Fess| (qui définit +``ingestFactory``, chargé de gérer les Ingester). .. code-block:: xml - - - - -Configuration -============= - -``fess_config.properties``: - -:: - - ingest.handler.example.enabled=true - -Informations complementaires -============================ + + + + + + + + +Grâce à ````, ``Ingester#register()`` +est appelée après la création du composant, ce qui l'enregistre +lui-même dans ``ingestFactory``. + +Il n'existe aucun paramètre de configuration dans +``fess_config.properties`` pour la fonctionnalité Ingest. L'activation +ou la désactivation dépend de l'installation ou non du plugin, et +l'ordre d'exécution est contrôlé par ``priority``. + +Flux d'exécution +================ + +Les Ingester sont appelés par ordre croissant de ``priority``, juste +avant que le document traité ne soit envoyé à l'index, aux emplacements +suivants : + +- **Crawl de datastore** : ``process(Map, DataStoreParams)`` est + appelée juste avant l'envoi du document. +- **Crawl Web/fichier (traitement de la réponse)** : + ``process(ResultData, ResponseData)`` est appelée avant + l'enregistrement du résultat du crawl. +- **Crawl Web/fichier (enregistrement dans l'index)** : + ``process(Map, AccessResult)`` est appelée juste avant l'envoi du + document. + +Dans tous les cas, si un Ingester lève une exception, un message +d'avertissement est journalisé et le traitement se poursuit +(l'enregistrement du document dans l'index n'est pas interrompu). + +.. note:: + + Comme les Ingester sont enregistrés dans l'environnement + d'exécution du crawler (``ingestFactory``), ils fonctionnent dans + le cadre du traitement de crawl. + +Implémentations de référence +============================= + +À titre de référence pour l'implémentation, les plugins suivants sont +publiés sur GitHub par `CodeLibs `__ : + +- ``fess-ingest-example`` - exemple d'implémentation minimale +- ``fess-webapp-multimodal`` - plugin contenant ``EmbeddingIngester``, + qui décode les embeddings vectoriels + +Informations complémentaires +============================= - :doc:`plugin-architecture` - Architecture des plugins diff --git a/ja/15.8/dev/ingest-plugin.rst b/ja/15.8/dev/ingest-plugin.rst index 221beab81..191c6e298 100644 --- a/ja/15.8/dev/ingest-plugin.rst +++ b/ja/15.8/dev/ingest-plugin.rst @@ -5,72 +5,157 @@ Ingestプラグイン 概要 ==== -Ingestプラグインは、ドキュメントがインデックスに登録される前に -データを加工・変換する機能を提供します。 +Ingestプラグインは、ドキュメントがインデックスに登録される直前に +データを加工・変換する機能を提供します。クロールで取得した各ドキュメントは、 +インデックスへ送信される前に登録済みの Ingester を通過します。 用途 ==== -- テキストの正規化(全角/半角変換など) -- メタデータの追加 +- テキストの正規化(全角/半角変換、空白の整形など) +- メタデータやカスタムフィールドの追加 - センシティブ情報のマスキング -- カスタムフィールドの追加 +- 値の変換(例: エンコードされたベクトル埋め込みのデコード) -基本実装 -======== +Ingester クラス +=============== + +Ingest機能は ``org.codelibs.fess.ingest.Ingester`` 抽象クラスを継承して +実装します。``Ingester`` には、クロールの種類や処理ステージに応じて +呼び出される ``process`` メソッドが用意されています。デフォルト実装は +いずれも受け取った ``target`` をそのまま返す(何もしない)ため、 +必要なメソッドだけをオーバーライドします。 + +- ``protected Map process(Map target)`` + + 2つの ``Map`` 版メソッドの共通の委譲先です。これをオーバーライドすると、 + データストアクロールとWeb/ファイルクロール(インデックス登録時)の + 両方のドキュメントに適用されます。多くの用途では、このメソッドだけを + オーバーライドすれば十分です。 + +- ``public Map process(Map target, DataStoreParams params)`` + + データストアクロール時に呼び出されます。デフォルトでは + ``process(target)`` に委譲します。 + +- ``public Map process(Map target, AccessResult accessResult)`` + + Web/ファイルクロールのインデックス登録時に呼び出されます。 + デフォルトでは ``process(target)`` に委譲します。 + +- ``public ResultData process(ResultData target, ResponseData responseData)`` + + Web/ファイルクロールのレスポンス処理時(アクセス結果を保存する前)に + 呼び出されます。デフォルトでは ``target`` をそのまま返します。 + +実行順序(priority) +-------------------- + +複数の Ingester が登録されている場合は、``priority`` フィールドの昇順 +(値が小さいものが先)に実行されます。デフォルト値は ``99`` です。 +コンストラクタで直接設定するか、``setPriority(int)`` で変更できます。 + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) + +実装例 +====== -``IngestHandler`` インターフェースを実装します: +``process(Map)`` をオーバーライドし、コンテンツを正規化して +カスタムフィールドを追加する例です: .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // 実行順序を設定(値が小さいほど先に実行。デフォルトは 99) + setPriority(50); + } @Override - public Map process(Map document) { + protected Map process(final Map target) { // コンテンツの正規化 - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } // カスタムフィールドの追加 - document.put("processed_at", new Date()); - - return document; - } + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - private String normalizeText(String text) { - // 正規化ロジック - return text.trim().replaceAll("\\s+", " "); + // 加工したドキュメントを返す + return target; } } +.. note:: + + ``process`` メソッドで ``null`` を返すとインデックス登録に失敗します。 + ドキュメントをスキップする仕組みはないため、必ず ``target`` を返してください。 + 登録 ==== -``fess_ingest.xml``: +Ingester は DIコンテナ経由で登録します。プラグインには ``fess_ingest++.xml`` +を含めます。ファイル名末尾の ``++`` は、|Fess| 本体の ``fess_ingest.xml`` +(Ingester を管理する ``ingestFactory`` を定義)へ設定を追記するマージ規約です。 .. code-block:: xml - - - + + + + + + + -設定 -==== +```` により、コンポーネント生成後に +``Ingester#register()`` が呼び出され、``ingestFactory`` に自身が登録されます。 -``fess_config.properties``: +Ingest機能に関する ``fess_config.properties`` の設定項目はありません。 +有効・無効はプラグインの導入有無で、実行順序は ``priority`` で制御します。 + +実行フロー +========== + +Ingester は、加工されたドキュメントがインデックスへ送信される直前に、 +以下の箇所で ``priority`` の昇順に呼び出されます: + +- **データストアクロール**: ドキュメントを送信する直前に + ``process(Map, DataStoreParams)`` が呼び出されます。 +- **Web/ファイルクロール(レスポンス処理時)**: クロール結果を保存する前に + ``process(ResultData, ResponseData)`` が呼び出されます。 +- **Web/ファイルクロール(インデックス登録時)**: ドキュメントを送信する直前に + ``process(Map, AccessResult)`` が呼び出されます。 + +いずれの箇所でも、ある Ingester が例外をスローした場合は警告ログを出力して +処理を継続します(そのドキュメントのインデックス登録は中断されません)。 + +.. note:: + + Ingester はクローラの実行環境(``ingestFactory``)に登録されるため、 + クロール処理の一部として動作します。 + +参考実装 +======== -:: +実装の参考として、以下のプラグインが GitHub の +`CodeLibs `__ で公開されています: - ingest.handler.example.enabled=true +- ``fess-ingest-example`` - 最小構成のサンプル実装 +- ``fess-webapp-multimodal`` - ベクトル埋め込みをデコードする ``EmbeddingIngester`` を含むプラグイン 参考情報 ======== diff --git a/ko/15.8/dev/ingest-plugin.rst b/ko/15.8/dev/ingest-plugin.rst index 68aa5bb86..64827c2f7 100644 --- a/ko/15.8/dev/ingest-plugin.rst +++ b/ko/15.8/dev/ingest-plugin.rst @@ -5,72 +5,156 @@ Ingest 플러그인 개요 ==== -Ingest 플러그인은 문서가 인덱스에 등록되기 전에 -데이터를 가공/변환하는 기능을 제공합니다. +Ingest 플러그인은 문서가 인덱스에 등록되기 직전에 +데이터를 가공·변환하는 기능을 제공합니다. 크롤링으로 수집한 각 문서는, +인덱스로 전송되기 전에 등록된 Ingester를 통과합니다. 용도 ==== -- 텍스트 정규화(전각/반각 변환 등) -- 메타데이터 추가 +- 텍스트 정규화(전각/반각 변환, 공백 정리 등) +- 메타데이터나 커스텀 필드 추가 - 민감한 정보 마스킹 -- 커스텀 필드 추가 +- 값 변환(예: 인코딩된 벡터 임베딩 디코딩) -기본 구현 -======== +Ingester 클래스 +=============== + +Ingest 기능은 ``org.codelibs.fess.ingest.Ingester`` 추상 클래스를 상속하여 +구현합니다. ``Ingester``에는 크롤링 종류나 처리 단계에 따라 +호출되는 ``process`` 메서드가 준비되어 있습니다. 기본 구현은 +모두 전달받은 ``target``을 그대로 반환(아무 작업도 하지 않음)하므로, +필요한 메서드만 오버라이드합니다. + +- ``protected Map process(Map target)`` + + 두 ``Map`` 버전 메서드가 공통으로 위임하는 대상입니다. 이 메서드를 오버라이드하면 + 데이터 스토어 크롤링과 Web/파일 크롤링(인덱스 등록 시) 양쪽 문서에 모두 적용됩니다. + 대부분의 용도에서는 이 메서드만 오버라이드하면 충분합니다. + +- ``public Map process(Map target, DataStoreParams params)`` + + 데이터 스토어 크롤링 시 호출됩니다. 기본적으로 + ``process(target)``에 위임합니다. + +- ``public Map process(Map target, AccessResult accessResult)`` + + Web/파일 크롤링의 인덱스 등록 시 호출됩니다. + 기본적으로 ``process(target)``에 위임합니다. + +- ``public ResultData process(ResultData target, ResponseData responseData)`` + + Web/파일 크롤링의 응답 처리 시(액세스 결과를 저장하기 전)에 + 호출됩니다. 기본적으로 ``target``을 그대로 반환합니다. + +실행 순서(priority) +-------------------- + +여러 Ingester가 등록되어 있는 경우 ``priority`` 필드의 오름차순 +(값이 작은 것이 먼저)으로 실행됩니다. 기본값은 ``99``입니다. +생성자에서 직접 설정하거나 ``setPriority(int)``로 변경할 수 있습니다. + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) + +구현 예시 +====== -``IngestHandler`` 인터페이스를 구현합니다: +``process(Map)``를 오버라이드하여 콘텐츠를 정규화하고 +커스텀 필드를 추가하는 예시입니다: .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // 실행 순서를 설정(값이 작을수록 먼저 실행됨. 기본값은 99) + setPriority(50); + } @Override - public Map process(Map document) { + protected Map process(final Map target) { // 콘텐츠 정규화 - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } // 커스텀 필드 추가 - document.put("processed_at", new Date()); - - return document; - } + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - private String normalizeText(String text) { - // 정규화 로직 - return text.trim().replaceAll("\\s+", " "); + // 가공한 문서를 반환 + return target; } } +.. note:: + + ``process`` 메서드에서 ``null``을 반환하면 인덱스 등록이 실패합니다. + 문서를 건너뛰는 방법은 없으므로 반드시 ``target``을 반환해야 합니다. + 등록 ==== -``fess_ingest.xml``: +Ingester는 DI 컨테이너를 통해 등록합니다. 플러그인에는 ``fess_ingest++.xml`` +을 포함합니다. 파일명 끝의 ``++``는 |Fess| 본체의 ``fess_ingest.xml`` +(Ingester를 관리하는 ``ingestFactory``를 정의)에 설정을 추가하는 병합 규칙입니다. .. code-block:: xml - - - + + + + + + + -설정 -==== +````에 의해 컴포넌트 생성 후 +``Ingester#register()``가 호출되어 ``ingestFactory``에 자신이 등록됩니다. -``fess_config.properties``: +Ingest 기능과 관련된 ``fess_config.properties`` 설정 항목은 없습니다. +활성화 여부는 플러그인 도입 여부로, 실행 순서는 ``priority``로 제어합니다. + +실행 흐름 +========== + +Ingester는 가공된 문서가 인덱스로 전송되기 직전에, +다음 위치에서 ``priority`` 오름차순으로 호출됩니다: + +- **데이터 스토어 크롤링**: 문서를 전송하기 직전에 + ``process(Map, DataStoreParams)``가 호출됩니다. +- **Web/파일 크롤링(응답 처리 시)**: 크롤링 결과를 저장하기 전에 + ``process(ResultData, ResponseData)``가 호출됩니다. +- **Web/파일 크롤링(인덱스 등록 시)**: 문서를 전송하기 직전에 + ``process(Map, AccessResult)``가 호출됩니다. + +어느 위치에서든 특정 Ingester가 예외를 던지면 경고 로그를 출력하고 +처리를 계속합니다(해당 문서의 인덱스 등록은 중단되지 않습니다). + +.. note:: + + Ingester는 크롤러 실행 환경(``ingestFactory``)에 등록되므로 + 크롤링 처리의 일부로 동작합니다. + +참고 구현 +======== -:: +구현 참고 자료로 다음 플러그인이 GitHub의 +`CodeLibs `__ 에 공개되어 있습니다: - ingest.handler.example.enabled=true +- ``fess-ingest-example`` - 최소 구성의 샘플 구현 +- ``fess-webapp-multimodal`` - 벡터 임베딩을 디코딩하는 ``EmbeddingIngester``를 포함하는 플러그인 참고 정보 ======== diff --git a/zh-cn/15.8/dev/ingest-plugin.rst b/zh-cn/15.8/dev/ingest-plugin.rst index 434e7594d..55a1fe29b 100644 --- a/zh-cn/15.8/dev/ingest-plugin.rst +++ b/zh-cn/15.8/dev/ingest-plugin.rst @@ -5,74 +5,154 @@ Ingest插件 概述 ==== -Ingest插件提供在文档注册到索引之前进行数据加工和转换的功能。 +Ingest插件提供在文档注册到索引之前对数据进行加工和转换的功能。 +通过抓取获取的各个文档,在发送到索引之前都会经过已注册的 Ingester。 用途 ==== -- 文本规范化(全角/半角转换等) -- 添加元数据 +- 文本规范化(全角/半角转换、空白整理等) +- 添加元数据或自定义字段 - 敏感信息脱敏 -- 添加自定义字段 +- 值转换(例如:解码已编码的向量嵌入) -基本实现 -======== +Ingester 类 +=============== + +Ingest 功能通过继承 ``org.codelibs.fess.ingest.Ingester`` 抽象类来实现。 +``Ingester`` 提供了根据抓取类型和处理阶段调用的 ``process`` 方法。由于 +默认实现均直接返回接收到的 ``target``(不做任何处理),因此只需重写 +所需的方法即可。 + +- ``protected Map process(Map target)`` + + 这是两个 ``Map`` 版本方法共同的委托目标。重写此方法后,将同时适用于 + 数据存储抓取以及 Web/文件抓取(索引注册时)的文档。在多数场景下, + 只需重写此方法即可满足需求。 + +- ``public Map process(Map target, DataStoreParams params)`` + + 在数据存储抓取时被调用。默认情况下会委托给 ``process(target)``。 + +- ``public Map process(Map target, AccessResult accessResult)`` + + 在 Web/文件抓取的索引注册时被调用。默认情况下会委托给 ``process(target)``。 + +- ``public ResultData process(ResultData target, ResponseData responseData)`` -实现 ``IngestHandler`` 接口: + 在 Web/文件抓取的响应处理时(保存访问结果之前)被调用。默认情况下 + 会直接返回 ``target``。 + +执行顺序(priority) +-------------------- + +当注册了多个 Ingester 时,将按照 ``priority`` 字段的升序(值越小越先 +执行)执行。默认值为 ``99``。可以在构造函数中直接设置,也可以通过 +``setPriority(int)`` 进行修改。 + +.. code-block:: java + + public int getPriority() + public void setPriority(final int priority) + +实现示例 +====== + +以下是重写 ``process(Map)`` 方法,对内容进行规范化并 +添加自定义字段的示例: .. code-block:: java package org.codelibs.fess.ingest.example; - import org.codelibs.fess.ingest.IngestHandler; import java.util.Map; - public class ExampleIngestHandler implements IngestHandler { + import org.codelibs.fess.ingest.Ingester; + + public class ExampleIngester extends Ingester { + + public ExampleIngester() { + // 设置执行顺序(值越小越先执行。默认值为 99) + setPriority(50); + } @Override - public Map process(Map document) { + protected Map process(final Map target) { // 内容规范化 - String content = (String) document.get("content"); - if (content != null) { - content = normalizeText(content); - document.put("content", content); + final Object content = target.get("content"); + if (content instanceof String) { + target.put("content", ((String) content).trim().replaceAll("\\s+", " ")); } // 添加自定义字段 - document.put("processed_at", new Date()); - - return document; - } + target.put("ingested_by", ExampleIngester.class.getSimpleName()); - private String normalizeText(String text) { - // 规范化逻辑 - return text.trim().replaceAll("\\s+", " "); + // 返回加工后的文档 + return target; } } +.. note:: + + 在 ``process`` 方法中返回 ``null`` 会导致索引注册失败。由于没有跳过 + 文档的机制,因此请务必返回 ``target``。 + 注册 ==== -``fess_ingest.xml``: +Ingester 通过 DI 容器进行注册。插件中需包含 ``fess_ingest++.xml`` +文件。文件名末尾的 ``++`` 是一种合并约定,表示将配置追加到 |Fess| +本体的 ``fess_ingest.xml``(其中定义了管理 Ingester 的 ``ingestFactory``)中。 .. code-block:: xml - - - + + + + + + + -配置 -==== +通过 ````,组件生成后会调用 +``Ingester#register()``,从而将自身注册到 ``ingestFactory`` 中。 + +关于 Ingest 功能,``fess_config.properties`` 中没有相应的配置项。 +是否启用取决于插件是否安装,执行顺序则通过 ``priority`` 控制。 -``fess_config.properties``: +执行流程 +========== -:: +在加工后的文档发送到索引之前,Ingester 会在以下位置按照 ``priority`` +的升序被调用: - ingest.handler.example.enabled=true +- **数据存储抓取**:在发送文档之前,会调用 + ``process(Map, DataStoreParams)``。 +- **Web/文件抓取(响应处理时)**:在保存抓取结果之前,会调用 + ``process(ResultData, ResponseData)``。 +- **Web/文件抓取(索引注册时)**:在发送文档之前,会调用 + ``process(Map, AccessResult)``。 + +无论在哪个位置,如果某个 Ingester 抛出异常,都会输出警告日志并继续 +处理(该文档的索引注册不会中断)。 + +.. note:: + + 由于 Ingester 是注册到抓取器的运行环境(``ingestFactory``)中的, + 因此它作为抓取处理的一部分运行。 + +参考实现 +======== + +作为实现参考,以下插件已在 GitHub 的 +`CodeLibs `__ 上公开: + +- ``fess-ingest-example`` - 最小配置的示例实现 +- ``fess-webapp-multimodal`` - 包含用于解码向量嵌入的 ``EmbeddingIngester`` 的插件 参考信息 ======== - :doc:`plugin-architecture` - 插件架构 -