インデックス作成フレームワーク

データベースクエリを使用してモデルエンティティを検索する場合を除き(ほとんどの場合は推奨されません)、Liferay DXPの各アセットは検索エンジンでインデックス化する必要があります。アセットの開発者はインデックス作成するフィールドと検索クエリに適用するフィルターを把握しているので、インデックスコードは各アセットに固有です。

Liferay DXPの過去のバージョンでは、アセットにインデックス作成が必要な場合、com.liferay.portal.kernel.search.BaseIndexer<T>を拡張して新しいインデクサーを実装していました。Liferay DXP 7.1では、継承ではなく構成に依存する新しいパターンを導入しています。 古いアプローチを使用する場合は、BaseIndexerを拡張できます。これも引き続きサポートされています。

検索とインデックス作成の概要

LiferayのオリジナルのSearch APIは、Lucene検索およびインデックス作成ライブラリを中心に構築されました。今までは、Luceneに精通していれば、LiferayのSearch APIについてもスムーズに理解することが可能でした。しかし、Liferay DXPの7.0バージョンから、Luceneに密接に関連する部分がより汎用的になるように、Search APIが改訂されています。Elasticsearchのサポートが追加され(Solrに加えて)、新しい検索およびインデックス作成APIのほとんどはElasticsearch APIを活用/マップすることを目的としています。これは、多くの場合(Queryタイプなど)、Liferay APIとElasticsearch APIの間に1対1のマッピングがあることを意味します。

Elasticsearch中心のAPIに加えて、Liferayの検索インフラストラクチャには、以下の目的に役立つ追加のAPIが含まれています。

  • インデックス付きドキュメントに、Liferay DXPに必要なフィールドが含まれている(例:entryClassNameentryClassPKassetTagNamesassetCategoriescompanyIdgroupId、ステージングステータス)。
  • 適切なフィルターを検索要求に適用することにより、返される検索結果の範囲を適切にする。
  • 権限チェックとヒットサマリーを提供して、検索ポートレットに表示する。

検索およびインデックス作成コードがカスタムモデルをシームレスに検索可能にする方法を理解するには、検索およびインデックス作成サイクルの各部分に影響を与える方法を知る必要があります。

インデックス作成

モデルエンティティは、データベースにデータフィールドを格納します。たとえば、ゲストブックには_名前_フィールドが保存されます。サイクルのインデックス作成ステップでは、検索エンジンに送信され、後で検索時に使用されるモデルのフィールドを定義することにより、検索可能なモデルエンティティを準備します。

検索エンジンドキュメントでモデルエンティティフィールドのインデックスを作成する方法を制御するには、

ModelDocumentContributorクラスは、モデルエンティティの検索エンジンドキュメントでインデックスを作成するデータベースフィールドを指定します。このクラスのcontributeメソッドは、エンティティのサービスレイヤーでaddおよびupdateメソッドが呼び出されるたびに呼び出されます。

ModelIndexerWriterContributorクラスは、モデルエンティティに対するインデックス再作成とバッチインデックス再作成の動作を構成します。このクラスのメソッドが呼び出されるのは、[コントロールパネル] → [設定] → [Search]にある検索管理アプリケーションからインデックスの再作成がトリガーされたとき、 またはmodelIndexedメソッドがコントリビュータに実装されている_場合_は、エンティティでCRUD操作が行われたときです。

DocumentContributorクラス(indexer.class.nameコンポーネントプロパティまたは型パラメーターなし)は、インデックス付けされているベースエンティティに関係なく、特定のフィールドをすべてのインデックスドキュメントに提供します。たとえば、GroupedModelDocumentContributorは、GroupedModelでもあるバッキングエンティティを持つすべてのドキュメントのGROUP_IDおよびSCOPE_GROUP_IDフィールドを提供します。

検索

検索は、ユーザーが検索バーにキーワードを入力することから始まります。入力されたキーワードは、バックエンド検索インフラストラクチャによって処理され、検索エンジンが理解できるクエリに変換され、各検索ドキュメントのフィールドとの照合に使用されます。

モデルエンティティドキュメントの検索方法を制御するには、

KeywordQueryContributorクラスは、進行中の検索クエリに句を提供します。これは検索時に呼び出され、インデックスを作成したすべてのフィールドも検索対象になるようにします。 たとえば、サイトロケールが追加されたフィールド(title_en_usなど)にインデックスを作成する場合に、ドキュメントの検索時に検索クエリに同じロケールを含めるとします。検索クエリに別のロケール(title_es_ESなど)が含まれているか、プレーンフィールド(title)が検索される場合、不正確な結果が返されます。

検索するベースエンティティに関係なく、すべての検索にクエリ句を提供するには、indexer.class.nameコンポーネントプロパティなしで登録されたKeywordQueryContributorクラスを実装します。例については、AlwaysPresentFieldsKeywordQueryContributorを参照してください。

ModelPreFilterContributorは、検索エンジンから返される前に検索結果をフィルター処理する方法を制御します。たとえば、クエリにワークフローステータスを追加すると、ごみ箱内のエンティティが検索結果に返されなくなります。

検索するベースエンティティに関係なく、すべての検索にフィルター句を提供するには、QueryPreFilterContributorを実装します。 QueryPreFilterContributorは、検索中にルートフィルターの下に1回だけ構築されます。例については、AssetCategoryTitlesKeywordQueryContributorを参照してください。

QueryPreFilterContributorModelPreFilterContributorの違いは何でしょうか。 QueryPreFilterContributorは検索中にルートフィルターの下に1回だけ構築されますが、ModelPreFilterContributorはモデルエンティティごとに1回構築され、各特定のエンティティのサブフィルターの下に追加されます。

結果を返す

検索要求中にモデルエンティティのインデックス作成済み検索ドキュメントが取得されると、モデルエンティティのサマリーに変換されます。

モデルエンティティドキュメントの結果の概要を制御するには、

ModelSummaryContributorクラスは各検索ドキュメント用に作成されたSummaryオブジェクトを取得するため、特定のフィールドを追加するか、表示されるコンテンツの長さを設定することでオブジェクトを操作できます。

ModelVisibilityContributorクラスは、検索コンテキストで、他のアセットタイプに添付できるモデルエンティティの可視性を制御します(たとえば、ファイルエントリをWikiページに添付できます)。

上記のクラスが検索フレームワークによって検出されることを確認するために、1つの重要なステップを実行する必要があります。

検索サービスの登録

Liferayの検索フレームワークにモデルエンティティを登録するには、

SearchRegistrarは、検索フレームワークのレジストリを使用して、検索エンジンからドキュメントを取得するためにデフォルトで使用されるフィールドや、エンティティに登録されているオプションの検索サービスなど、モデルエンティティのModelSearchDefinitionに関する特定の項目を定義します。登録は、コンポーネントがアクティブ化されるとすぐに行われます(ポータルの起動時またはバンドルのデプロイ時)。

複合検索とインデックス作成フレームワークのIndexer/BaseIndexerコードへのマッピング

カスタムエンティティのインデックス作成の古い方法(BaseIndexerの拡張、Indexerの抽象的な実装)に慣れている方のために、下の表に、Indexerインターフェイスのメソッドがいくつかの新しいクラスとメソッドにどのように分解されたかについての簡単な概要を示します。

Indexer/BaseIndexerメソッド同等の複合インデクサー
クラスコンストラクターSearchRegistrarGuestbookSearchRegistrar
setDefaultSelectedFieldNamesSearchRegistrar.activateGuestbookSearchRegistrar
setDefaultSelectedLocalizedFieldNamesSearchRegistrar.activateGuestbookSearchRegistrar
setPermissionAwareModelResourcePermissionRegistrarGuestbookModelResourcePermissionRegistrar
setFilterSearchModelResourcePermissionRegistrarGuestbookModelResourcePermissionRegistrar
getDocument/doGetDocumentModelDocumentContributorGuestbookModelDocumentContributor
reindex/doReindexModelIndexerWriterContributorGuestbookModelIndexerWriterContributor
addRelatedEntryFieldsRelatedEntryIndexerDLFileEntryRelatedEntryIndexer
postProcessContextBooleanFilter/PostProcessContextQueryModelPreFilterContributorDLFileEntryModelPreFilterContributor
postProcessSearchQueryKeywordQueryContributorGuestbookKeywordQueryContributor
getFullQuerySearchContextContributorDLFileEntryModelSearchContextContributor
isVisible/isVisibleRelatedEntryModelVisibilityContributorDLFileEntryModelVisibilityContributor
getSummary/createSummary/doGetSummaryModelSummaryContributorGuestbookModelSummaryContributor
Indexer.search/searchCount変更なしゲストブックview_search.jsp
Indexer.delete/doDelete変更なしMBMessageLocalServiceImpl.deleteDiscussionMessages

さらに、ExpandoBridge属性にインデックスを作成することができます。これは以前、BaseIndexergetBaseModelDocumentで行われていました。 ここで、ExpandoBridgeRetrieverを実装します。実装例については、DLFileEntryExpandoBridgeRetrieverを参照してください。

権限に対応した検索とインデックス作成

以前のバージョンのLiferay DXPでは、アプリケーション開発者がIndexerクラスのコンストラクターで次の行を指定した場合、検索は_権限のみに対応_していました(エンティティの権限でインデックス作成され、権限はそのままで検索される)。

setPermissionAware(true);

現在、これらのチュートリアルで説明されている_新しい権限アプローチ_がアプリケーションに実装されている場合、検索はデフォルトで権限を認識します。

インデックス作成をトリガーするサービスメソッドに注釈を付ける

エンティティをデータベースエンティティ_と_検索エンジンドキュメントに変換すると、データベースと検索エンジン間で状態が一致しない可能性があります。 たとえば、データベースでブログエントリの追加、更新、または削除が行われた場合、対応する変更を検索エンジンで行う必要があります。これを行うには、サービスレイヤーに介入する必要があります。Service Builderエンティティの場合、これはLocalServiceImplクラスで発生します。これを簡素化するアノテーションは@Indexableです。これは、REINDEXまたはDELETEの2つの値を持つことができるtypeプロパティを取ります。一般に、サービスレイヤーのdeleteEntityメソッドには次のように注釈が付けられます。

@Indexable(type = IndexableType.DELETE)
@Override
@SystemEvent(type = SystemEventConstants.TYPE_DELETE)
public BlogsEntry deleteEntry(BlogsEntry entry) throws PortalException {
...
}

@IndexableアノテーションはLiferayのSpringインフラストラクチャによって実行されます。そのため、そのアノテーションを持つメソッドがある場合は、スプリングでラップされたロジックでサービスインスタンス変数を使用して呼び出す必要があります。参照は、Service Builderで生成された*LocalServiceImplクラスでデフォルトで使用可能です。この宣言は親の*LocalServiceBaseImplで行われたものだからです。

@BeanReference(type = BlogsEntryLocalService.class)
protected BlogsEntryLocalService blogsEntryLocalService;

これは、*LocalServiceImplで以下を呼び出してはいけないことを意味しています。

this.deleteEntry(...)

アノテーションは実行されず、検索エンジンドキュメントとデータベース列の状態は一致しないままとなります。代わりに、Liferay DXPのコードのパターンに従い、サービスインスタンス変数を使用してサービスメソッドを呼び出します。

blogsEntryLocalService.deleteEntry(entry);

モデルエンティティのインデックス作成の詳細な手順については、Webアプリケーションの開発チュートリアルの「検索とインデックス作成」セクションをご覧ください。

« Elasticsearchロギング資産フレームワーク »
この記事は役に立ちましたか?
1人中1人がこの記事が役に立ったと言っています