サーチインデックスを作成する際に、テキストフィールドに対して強調表示機能を有効にすることができます。この方法では、サーチインデックスを使用してテキストフィールドに基づいてデータをクエリする際に、強調表示パラメータを設定して、クエリ条件を満たす行のセグメント内のクエリ文字列を強調表示できます。
シナリオ
全文検索で強調表示機能を使用して、クエリ条件を満たす行のセグメント内のクエリ文字列を強調表示できます。強調表示機能は、Web検索、チャット履歴の取得、ドキュメント検索などのシナリオに適しています。
機能概要
強調表示機能を使用して、クエリ結果内のクエリ文字列と一致または関連するテキストを強調表示できます。これにより、ユーザーがクエリ文字列をすばやく見つけることができるため、情報検索効率が向上します。強調表示機能を使用して、JSON構造などの複雑な構造を持つネストされたデータ内の必要な情報を正確に特定できます。デフォルトでは、Tablestoreは<em></em>
を使用してクエリ結果内のクエリ文字列を強調表示します。
強調表示機能を使用するには、次の設定を完了する必要があります。
サーチインデックスを作成する際に、テキストフィールドのenableHighlightingパラメータをTrueに設定します。詳細については、サーチインデックスの作成を参照してください。
重要強調表示機能は、テキストフィールドに対してのみ有効にできます。
クエリリクエストで強調表示機能を使用する際に、強調表示されたテキストフラグメントのエンコード方法、各行で返す強調表示されたテキストフラグメントの最大数、開始タグ、終了タグなどのパラメータを設定することで、カスタムの強調表示スタイルを指定できます。
たとえば、サーチインデックスを作成する際に、テキストフィールドに対して強調表示機能を有効にします。テキストフィールドに西湖
クエリ文字列を含むデータをクエリするために一致フレーズクエリを実行し、強調表示パラメータを設定すると、テキストフィールドの値が杭州西湖風景区
である行がクエリ条件を満たし、強調表示されたテキストセグメント杭州<em>西湖</em>風景区
が返されます。
使用上の注意
一致クエリまたは一致フレーズクエリで強調表示機能を有効にすると、クエリ結果内のクエリ文字列が複数の開始タグ(preTag)と終了タグ(postTag)を使用して強調表示される場合があります。
テキストフィールドのトークン化方法が最大意味単位ベースのトークン化(MaxWord)の場合、テキストフィールドで一致フレーズクエリを実行するときに強調表示機能はサポートされません。
複数のフラグメントを返す場合、フラグメント内のクエリ文字列が分割される場合があります。この場合、クエリ文字列は強調表示されない場合があります。
API操作
強調表示機能を使用するには、Search操作を呼び出し、クエリタイプをTermQuery、TermsQuery、MatchQuery、MatchPhraseQuery、PrefixQuery、WildcardQuery、またはNestedQueryに設定します。
パラメータ
ほとんどの場合、強調表示パラメータを設定して強調表示機能を使用できます。ネストされたフィールドのサブフィールドの場合は、InnerHitsパラメータを設定して強調表示機能を使用する必要があります。
強調表示パラメータ
パラメータ | 説明 | |
highlightEncoder | 強調表示されたテキストフラグメントのエンコード方法。有効な値:
| |
fieldHighlightParams | フィールドの強調表示設定。SearchQueryオブジェクトで指定されたキーワードを含むフィールドに対してのみ、強調表示機能を有効にできます。 | |
HighlightParameter | numberOfFragments | 返す強調表示されたテキストフラグメントの最大数。値を1に設定することをお勧めします。 |
fragmentSize | 返す各テキストフラグメントの長さ。デフォルト値:100。 重要 返されるテキストフラグメントの実際の長さは、このパラメータの値と異なる場合があります。 | |
preTag | クエリキーワードを強調表示するために使用される開始タグ。例: | |
postTag | クエリキーワードを強調表示するために使用される終了タグ。例: | |
highlightFragmentOrder | 返す強調表示されたテキストフラグメントの並べ替えルール。
|
InnerHitsパラメータ
パラメータ | 説明 |
sort | ネストされたフィールドの子行の並べ替えルール。 |
offset | ネストされたフィールドが複数の子行で構成されている場合に返す子行の開始位置。 |
limit | ネストされたフィールドが複数の子行で構成されている場合に返す子行の最大数。デフォルト値:3。 |
highlight | ネストされたフィールドのサブフィールドの強調表示設定。詳細については、強調表示パラメータを参照してください。 |
メソッド
強調表示機能は、Tablestore SDKを使用してのみ使用できます。
強調表示機能を使用する前に、次の準備が整っていることを確認してください。
Alibaba CloudアカウントまたはTablestore操作権限を持つRAMユーザーが作成されている。RAMユーザーにTablestore操作権限を付与する方法については、RAMポリシーを使用してRAMユーザーに権限を付与するを参照してください。
Tablestore SDKを使用して強調表示機能を使用する場合、Alibaba CloudアカウントまたはRAMユーザーのAccessKeyペアが作成されている。詳細については、AccessKeyペアの作成を参照してください。
データテーブルが作成されている。詳細については、データテーブルの操作を参照してください。
データテーブルのサーチインデックスが作成され、特定のフィールドに対して強調表示機能が有効になっている。詳細については、サーチインデックスの作成を参照してください。
Tablestore SDKを使用して強調表示機能を使用する場合、OTSClientインスタンスが初期化されている。詳細については、OTSClientインスタンスの初期化を参照してください。
強調表示機能を使用するには、次のTablestore SDKを使用できます:Tablestore SDK for Java、Tablestore SDK for Go、Tablestore SDK for Python、およびTablestore SDK for Node.js。この例では、Tablestore SDK for Javaを使用します。
ネストされていないフィールドをクエリする際に強調表示機能を使用する
次のサンプルコードは、MatchQuery機能を使用してCol_Textフィールドからhangzhou shanghai
と一致するデータをクエリし、クエリ結果内のキーワードを強調表示する方法の例を示しています。この例では、Col_Textフィールドはテキスト型です。
/**
* MatchQueryオブジェクト内のキーワードに対して強調表示機能を有効にします。
*/
public static void matchQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<テーブル名>") // テーブル名を指定
.indexName("<サーチインデックス名>") // サーチインデックス名を指定
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.bool()
.should(QueryBuilders.match("Col_Text", "hangzhou shanghai")))
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Text", HighlightParameter.newBuilder()
.highlightFragmentOrder(HighlightFragmentOrder.TEXT_SEQUENCE)
.preTag("<b>")
.postTag("</b>")
.build())
.build())
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// 強調表示されたクエリ結果を表示します。ネストされていないフィールドをクエリする場合は、プレフィックスパラメータをnullに設定します。
printSearchHit(resp.getSearchHits(), "");
}
/**
* クエリ条件を満たすコンテンツを表示します。
* @param searchHits searchHits
* 出力が@param prefixネスト構造を使用する場合は、プレフィックスを追加して階層情報を表示します。
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s スコア: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s オフセット: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s 行: %s\n", prefix, searchHit.getRow().toString());
}
// 各フィールドの強調表示されたフラグメントを表示します。
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s 強調表示: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
System.out.println();
}
}
ネストされたフィールドをクエリする際に強調表示機能を使用する
次のサンプルコードは、ネストされたクエリを使用して、Col_Nestedという名前のネストされた列のLevel1_Col1_Nestedサブ列の値がhangzhou shanghai
と一致する行をクエリし、クエリ結果内のクエリ文字列を強調表示する方法の例を示しています。
/**
* ネストされたクエリにinnerHitsパラメータを使用して強調表示機能を有効にします。
*/
public static void nestedQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<テーブル名>") // テーブル名を指定
.indexName("<サーチインデックス名>") // サーチインデックス名を指定
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.nested()
.path("Col_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.match("Col_Nested.Level1_Col1_Nested", "hangzhou shanghai"))
.innerHits(InnerHits.newBuilder()
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col1_Nested", HighlightParameter.newBuilder().build())
.build())
.build()))
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// 強調表示された結果を表示します。
printSearchHit(resp.getSearchHits(), "");
}
/**
* クエリ条件を満たすコンテンツを表示します。
* @param searchHits searchHits
* 出力が@param prefixネスト構造を使用する場合は、プレフィックスを追加して階層情報を表示します。
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s スコア: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s オフセット: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s 行: %s\n", prefix, searchHit.getRow().toString());
}
// 各行の列の強調表示されたテキストセグメントを表示します。
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s 強調表示: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
// ネストされた列の強調表示された結果。
for (SearchInnerHit searchInnerHit : searchHit.getSearchInnerHits().values()) {
System.out.printf("%s パス: %s\n", prefix, searchInnerHit.getPath());
System.out.printf("%s 内部ヒット: \n", prefix);
printSearchHit(searchInnerHit.getSubSearchHits(), prefix + " ");
}
System.out.println();
}
}
たとえば、Col_Nestedフィールドは、テキスト型のLevel1_Col1_Textサブフィールドとネスト型のLevel1_Col2_Nestedサブフィールドで構成されています。ネスト型のLevel1_Col2_NestedサブフィールドもLevel2_Col1_Textフィールドで構成されています。
次のサンプルコードは、ネストされたクエリにブールクエリを追加して、Level1_Col1_TextフィールドとLevel1_Col2_NestedフィールドのLevel2_Col1_Textサブフィールドのクエリ文字列を強調表示する方法の例を示しています。
public static void nestedQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<テーブル名>") // テーブル名を指定
.indexName("<サーチインデックス名>") // サーチインデックス名を指定
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.nested()
.path("Col_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.bool()
.should(QueryBuilders.match("Col_Nested.Level1_Col1_Text", "hangzhou shanghai"))
.should(QueryBuilders.nested()
.path("Col_Nested.Level1_Col2_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.match("Col_Nested.Level1_Col2_Nested.Level2_Col1_Text", "hangzhou shanghai"))
.innerHits(InnerHits.newBuilder()
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col2_Nested.Level2_Col1_Text", HighlightParameter.newBuilder().build()) // Level2_Col1_Textフィールドの強調表示設定を追加
.build())
.build())))
.innerHits(InnerHits.newBuilder()
.sort(new Sort(Arrays.asList(
new ScoreSort(),
new DocSort()
)))
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col1_Text", HighlightParameter.newBuilder().build()) // Level1_Col1_Textフィールドの強調表示設定を追加
.build())
.build()))
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// 強調表示された結果を表示します。
printSearchHit(resp.getSearchHits(), "");
}
/**
* クエリ条件を満たすコンテンツを表示します。
* @param searchHits searchHits
* 出力が@param prefixネスト構造を使用する場合は、プレフィックスを追加して階層情報を表示します。
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s スコア: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s オフセット: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s 行: %s\n", prefix, searchHit.getRow().toString());
}
// 各行のフィールドの強調表示されたテキストセグメントを表示します。
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s 強調表示: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
// ネストされた列の強調表示された結果。
for (SearchInnerHit searchInnerHit : searchHit.getSearchInnerHits().values()) {
System.out.printf("%s パス: %s\n", prefix, searchInnerHit.getPath());
System.out.printf("%s 内部ヒット: \n", prefix);
printSearchHit(searchInnerHit.getSubSearchHits(), prefix + " ");
}
System.out.println();
}
}
課金ルール
データをクエリする際に使用する強調表示機能は、Tablestoreの既存の課金ルールには影響しません。
サーチインデックスを使用してデータをクエリする場合は、消費された読み取りスループットに対して課金されます。詳細については、サーチインデックスの課金対象項目を参照してください。
FAQ
参考資料
サーチインデックスを使用してデータをクエリする場合は、次のクエリメソッドを使用できます:用語クエリ、複数用語クエリ、すべて一致クエリ、一致クエリ、一致フレーズクエリ、プレフィックスクエリ、範囲クエリ、ワイルドカードクエリ、あいまいクエリ、ブールクエリ、地理クエリ、ネストされたクエリ、KNNベクトル検索クエリ、および存在クエリ。ビジネス要件に基づいてクエリメソッドを選択し、複数のディメンションからデータをクエリできます。
並べ替えおよびページング機能を使用して、クエリ条件を満たす行を並べ替えたりページングしたりできます。詳細については、並べ替えとページングの実行を参照してください。
折りたたみ(重複排除)機能を使用して、特定の列に基づいて結果セットを折りたたむことができます。このようにして、指定されたタイプのデータはクエリ結果に1回だけ表示されます。詳細については、折りたたみ(重複排除)を参照してください。
データテーブル内のデータを分析する場合は、Search操作の集計機能を使用するか、SQLステートメントを実行できます。たとえば、最小値、最大値、合計、および行の総数を取得できます。詳細については、集計およびSQLクエリを参照してください。
行を並べ替えることなく、クエリ条件を満たすすべての行を取得する場合は、ParallelScanおよびComputeSplits操作を呼び出して並列スキャン機能を使用できます。詳細については、並列スキャンを参照してください。