すべてのプロダクト
Search
ドキュメントセンター

Tablestore:強調表示

最終更新日:Dec 28, 2024

サーチインデックスを作成する際に、テキストフィールドに対して強調表示機能を有効にすることができます。この方法では、サーチインデックスを使用してテキストフィールドに基づいてデータをクエリする際に、強調表示パラメータを設定して、クエリ条件を満たす行のセグメント内のクエリ文字列を強調表示できます。

シナリオ

全文検索で強調表示機能を使用して、クエリ条件を満たす行のセグメント内のクエリ文字列を強調表示できます。強調表示機能は、Web検索、チャット履歴の取得、ドキュメント検索などのシナリオに適しています。

機能概要

強調表示機能を使用して、クエリ結果内のクエリ文字列と一致または関連するテキストを強調表示できます。これにより、ユーザーがクエリ文字列をすばやく見つけることができるため、情報検索効率が向上します。強調表示機能を使用して、JSON構造などの複雑な構造を持つネストされたデータ内の必要な情報を正確に特定できます。デフォルトでは、Tablestoreは<em></em>を使用してクエリ結果内のクエリ文字列を強調表示します。

強調表示機能を使用するには、次の設定を完了する必要があります。

  1. サーチインデックスを作成する際に、テキストフィールドのenableHighlightingパラメータをTrueに設定します。詳細については、サーチインデックスの作成を参照してください。

    重要

    強調表示機能は、テキストフィールドに対してのみ有効にできます。

  2. クエリリクエストで強調表示機能を使用する際に、強調表示されたテキストフラグメントのエンコード方法、各行で返す強調表示されたテキストフラグメントの最大数、開始タグ、終了タグなどのパラメータを設定することで、カスタムの強調表示スタイルを指定できます。

たとえば、サーチインデックスを作成する際に、テキストフィールドに対して強調表示機能を有効にします。テキストフィールドに西湖クエリ文字列を含むデータをクエリするために一致フレーズクエリを実行し、強調表示パラメータを設定すると、テキストフィールドの値が杭州西湖風景区である行がクエリ条件を満たし、強調表示されたテキストセグメント杭州<em>西湖</em>風景区が返されます。

使用上の注意

  • 一致クエリまたは一致フレーズクエリで強調表示機能を有効にすると、クエリ結果内のクエリ文字列が複数の開始タグ(preTag)と終了タグ(postTag)を使用して強調表示される場合があります。

  • テキストフィールドのトークン化方法が最大意味単位ベースのトークン化(MaxWord)の場合、テキストフィールドで一致フレーズクエリを実行するときに強調表示機能はサポートされません。

  • 複数のフラグメントを返す場合、フラグメント内のクエリ文字列が分割される場合があります。この場合、クエリ文字列は強調表示されない場合があります。

API操作

強調表示機能を使用するには、Search操作を呼び出し、クエリタイプをTermQueryTermsQueryMatchQueryMatchPhraseQueryPrefixQueryWildcardQuery、またはNestedQueryに設定します。

パラメータ

ほとんどの場合、強調表示パラメータを設定して強調表示機能を使用できます。ネストされたフィールドのサブフィールドの場合は、InnerHitsパラメータを設定して強調表示機能を使用する必要があります。

強調表示パラメータ

パラメータ

説明

highlightEncoder

強調表示されたテキストフラグメントのエンコード方法。有効な値:

  • PLAIN(デフォルト):エンコードせずに強調表示されたテキストフラグメントを表示します。

  • HTML:強調表示されたテキストフラグメントでHTMLエンコードを実行します。HTMLエンコードが完了すると、<&lt;に、>&gt;に、"&quot;に、'&#x27;に、/&#x2F;に変換されます。Webページを表示する場合は、HTML形式を使用することをお勧めします。

fieldHighlightParams

フィールドの強調表示設定。SearchQueryオブジェクトで指定されたキーワードを含むフィールドに対してのみ、強調表示機能を有効にできます。

HighlightParameter

numberOfFragments

返す強調表示されたテキストフラグメントの最大数。値を1に設定することをお勧めします。

fragmentSize

返す各テキストフラグメントの長さ。デフォルト値:100。

重要

返されるテキストフラグメントの実際の長さは、このパラメータの値と異なる場合があります。

preTag

クエリキーワードを強調表示するために使用される開始タグ。例:<em>および<b>。デフォルト値:<em>。ビジネス要件に基づいてカスタムの開始タグを指定できます。preTagパラメータは、次の文字セットをサポートしています:< > " ' /a-zA-Z、および0-9

postTag

クエリキーワードを強調表示するために使用される終了タグ。例:</em>および</b>。デフォルト値:<em>。ビジネス要件に基づいてカスタムの終了タグを指定できます。postTagパラメータは、次の文字セットをサポートしています:< > " ' /a-zA-Z、および0-9

highlightFragmentOrder

返す強調表示されたテキストフラグメントの並べ替えルール。

  • TEXT_SEQUENCE(デフォルト):強調表示されたテキストフラグメントは、元のテキストでの出現順に並べ替えられます。

  • SCORE:強調表示されたテキストフラグメントは、ヒットキーワードのスコアに基づいて並べ替えられます。

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 JavaTablestore SDK for GoTablestore 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

参考資料