概要
データストアプラグインを開発することで、Fess に新しいデータソースからの コンテンツ取得機能を追加できます。データストアは、データベース・API・ファイルなどの 外部システムからレコードを取得し、管理画面で設定したマッピングスクリプトに従って インデックスフィールドへ変換したうえで、Fess のインデックスへ登録します。
CSV・JSON・データベース・Git・各種クラウドサービスなど、公開されている コネクター(fess-ds-*)はすべてこの仕組みで実装されています。実装の雛形として fess-ds-example が公開されているため、 新しいコネクターを作成する場合はこれをコピーして始めるのが簡単です。
基本構造
データストアプラグインは、次の3点で構成されます。
AbstractDataStoreを継承したクラスを作成するgetName()とstoreData()の2つのメソッドを実装するfess_ds++.xmlでコンポーネントとして登録する
最小実装
注釈
getName() と storeData() はいずれも protected の抽象メソッドです。 DataConfig のパッケージは Fess 15.x では org.codelibs.fess.opensearch.config.exentity である点に注意してください(以前の org.codelibs.fess.es.config.exentity は廃止されています)。
コンポーネントの登録
作成したデータストアを Fess に認識させるため、src/main/resources/fess_ds++.xml に コンポーネントを登録します。
<postConstruct name="register"> により、コンポーネント生成後に AbstractDataStore が持つ register() メソッドが自動的に呼び出され、DataStoreFactory へ自身が登録されます。 このとき登録される名前が getName() の戻り値(上記の例では ExampleDataStore)であり、 管理画面のデータストア設定で選択する「ハンドラー名」になります。
AbstractDataStore
主要メソッド
| メソッド | 区分 | 説明 |
|---|---|---|
getName() | 実装(必須) | データストアのハンドラー名を返す抽象メソッド。getClass().getSimpleName() を返すのが慣例 |
storeData() | 実装(必須) | データの取得・変換・インデックス登録を行う抽象メソッド |
register() | 継承(通常は変更不要) | fess_ds++.xml の postConstruct から自動呼び出しされ、DataStoreFactory へ登録する |
store() | 継承(フレームワーク呼び出し) | フレームワークが呼び出す入口。defaultDataMap などを準備して storeData() を呼ぶ |
convertValue() | 継承(ヘルパー) | scriptMap の値(テンプレート)をスクリプトエンジンで評価する |
getScriptType() | 継承(ヘルパー) | script_type パラメーターを取得する(既定は Groovy) |
getReadInterval() | 継承(ヘルパー) | readInterval パラメーター(ミリ秒)を取得する |
sleep() | 継承(ヘルパー) | 指定ミリ秒スリープする(レコード間の待機に使用) |
storeData のパラメーター
storeData() メソッドに渡されるパラメーター:
| パラメーター | 型 | 説明 |
|---|---|---|
dataConfig | DataConfig | データストア設定(ID・ハンドラー名・パラメーター・スクリプトなど) |
callback | IndexUpdateCallback | 生成したドキュメントをインデックスへ登録するコールバック |
paramMap | DataStoreParams | 管理画面「パラメーター」欄の設定値。getAsString(key) / getAsString(key, default) / get(key) / asMap() / containsKey(key) でアクセスする |
scriptMap | Map<String, String> | 管理画面「スクリプト」欄の設定。キーがインデックスフィールド名、値が評価対象のスクリプトテンプレート |
defaultDataMap | Map<String, Object> | 各ドキュメントの既定フィールド値(設定ID・boost・role・mimetype・仮想ホストなど)。フレームワークが用意する |
警告
paramMap の型は Map<String, String> ではなく DataStoreParams です。 DataStoreParams は Map を実装していないため、値の取得には get() ではなく 文字列を返す getAsString() を使用してください。
データ処理の流れ
storeData() の実装は、次の流れでデータを処理します。
外部システムからソースレコードを取得する。
paramMap.asMap()にソースレコードのフィールドをマージしてresultMapを構築する (スクリプトはこのresultMapに対して評価される)。scriptMapの各エントリをconvertValue(scriptType, template, resultMap)で評価し、 結果をdataMapに格納する。マッピングはコード内にハードコードするのではなく、 管理者が「スクリプト」欄で定義する点が重要です。callback.store(paramMap, dataMap)を呼び出してドキュメントとしてインデックス登録する。
実装例
シンプルなデータストア
外部 API からレコードを取得してインデックス登録する例です。
fetchRecords() は外部システムからレコード一覧を取得する独自メソッドです。取得した 各レコード(Map<String, Object>)のフィールド名が、scriptMap のスクリプトから 参照できる名前になります。DataStoreException は org.codelibs.fess.exception パッケージのクラスです。
ページネーション対応
大量のデータを扱う場合は、ページ単位で取得しながら処理します。1レコードあたりの処理 (resultMap の構築・scriptMap の評価・callback.store() の呼び出し)を processRecord() のようなメソッドに切り出しておくと、取得ロジックと分離できます。
認証の実装
外部システムの認証は、コネクター側で実装します。以下は一般的な HTTP クライアント ライブラリを用いた実装例で、Fess が提供する API ではありません。利用するライブラリは プラグインの依存関係として同梱してください。
OAuth 2.0
APIキー認証
エラーハンドリング
処理を中断すべき致命的なエラーでは DataStoreException をスローします。
注釈
fess-ds-example をはじめとする実際のコネクターでは、1レコードのエラーで クロール全体を止めないよう、レコード単位で CrawlingAccessException を捕捉し、 FailureUrlService にエラー URL を記録しています。また DataStoreCrawlingException の中断フラグを用いて、クロール全体を中断するかどうかを 制御しています。堅牢なコネクターを実装する場合は ExampleDataStore の実装を参照してください。
テスト
ユニットテスト
Fess のプラグインは UTFlute の LastaDiTestCase を用いてテストします。テストは JUnit 5(Jupiter)で記述します。IndexUpdateCallback を、登録された dataMap を 収集する実装に差し替えることで、モックライブラリを使わずにマッピング結果を検証できます。
注釈
setUp は基底クラスで @BeforeEach が付与されているため、オーバーライド側に ライフサイクルアノテーションを付け直す必要はありません。各テストメソッドには @Test(org.junit.jupiter.api.Test)を付与します。
ビルドとインストール
pom.xml
プラグインは fess-parent を親 POM とする jar としてビルドします。fess および opensearch への依存は、実行時に Fess 本体から提供されるため provided にします。
テストには JUnit 5 と org.dbflute.utflute:utflute-lastaflute を利用します。
ビルド
target/ ディレクトリに fess-ds-example-15.8.0.jar が生成されます。
インストール
生成した JAR を Fess にインストールし、Fess を再起動します。インストール手順の詳細は プラグイン を参照してください。インストール後、管理画面の 「クローラー > データストア」から新規設定を作成し、「ハンドラー名」に getName() が返す名前 (この例では ExampleDataStore)を指定します。
設定例
管理画面での設定例:
パラメーター
「パラメーター」欄には、コネクターが paramMap から読み取るキーと値を記述します。
スクリプト
「スクリプト」欄には、左辺=右辺 の形式でマッピングを記述します。左辺がインデックス フィールド名、右辺がソースレコードのフィールドを参照するスクリプト(既定では Groovy)です。 以下は、ソースレコードが url / title / content / updated_at / content_type フィールドを持つ場合の例です。
注釈
右辺で参照できるフィールド名は、コネクターが resultMap に格納する値 (paramMap の値とソースレコードのフィールド)によって決まります。CSV や JSON など 既存コネクターでは data.* のような独自のプレフィックスが付く場合があるため、 各コネクターのドキュメントを参照してください。
参考情報
プラグインアーキテクチャ - プラグインアーキテクチャ
プラグイン - プラグインのインストール
データストアコネクタの概要 - データストアコネクター概要
fess-ds-example - データストアプラグインの実装テンプレート
GitHub: fess-ds-* - 公開コネクターの例