全部產品
Search
文件中心

Tablestore:查詢高亮

更新時間:Sep 13, 2024

要使用查詢高亮,您需要在建立多元索引時為Text類型的欄位開啟查詢高亮(Highlight)功能,然後在查詢資料時通過設定高亮參數,返回命中查詢關鍵詞的片段資訊並對關鍵詞進行高亮顯示。

情境

查詢高亮功能可用於全文檢索索引情境中提取關鍵片段並高亮命中的關鍵詞,適用於網頁搜尋、聊天記錄檢索、文檔搜尋等情境。

功能概述

查詢高亮功能可用於在搜尋結果中對與查詢詞匹配或相關的文本進行高亮顯示,協助使用者快速識別到所需的相關查詢內容,提高資訊檢索的效率。對於包含巢狀型別的複雜資料結構(例如JSON)也支援使用查詢高亮功能來精準定位所需資訊。Table Store預設使用<em></em>標籤來標記匹配的關鍵詞。

要使用查詢高亮功能,您需要完成如下配置:

  1. 在建立多元索引時,設定Text類型欄位的enableHighlighting參數為True。具體操作,請參見建立多元索引

    重要

    只支援為Text類型欄位開啟查詢高亮功能。

  2. 在資料查詢中使用查詢高亮功能時,通過指定高亮分區的編碼方式、返回高亮分區的最大數量、前置Tag、後置Tag等參數來自訂高亮顯示的樣式。

假設建立多元索引時已為某個Text類型欄位開啟查詢高亮功能,當該Text類型欄位的值為查詢高亮測試時,在通過MatchPhrase功能查詢關鍵詞高亮,並指定高亮參數後,可返回高亮片段查詢<em>高亮</em>測試

注意事項

  • 在MatchQuery和MatchPhraseQuery中使用查詢高亮功能時,關鍵詞可能會被多個preTag、postTag高亮顯示。

  • 如果Text欄位的分詞類型為最大語義分詞,則使用MatchPhraseQuery功能進行資料查詢時不支援使用查詢高亮功能。

  • 分區切分可能會將文本中的查詢關鍵詞分割,此時該關鍵詞可能不會被高亮。

介面

查詢高亮的介面為Search,具體的Query類型支援TermQueryTermsQueryMatchQueryMatchPhraseQueryPrefixQueryWildcardQueryNestedQuery

參數

使用查詢高亮時,一般情況下通過Highlight參數設定高亮參數。對於巢狀型別的子列,則需要通過InnerHits參數設定高亮參數。

Highlight參數

參數

說明

highlightEncoder

對高亮分區原文內容的編碼方式。取值範圍如下:

  • PLAIN(預設):原文展示,不進行編碼。

  • HTML:對高亮分區原文進行HTML轉義,轉義包括<轉義為&lt;>轉義為&gt;"轉義為&quot;'轉義為&#x27;/轉義為&#x2F;,網頁展示時推薦使用HTML格式。

fieldHighlightParams

欄位高亮參數,僅支援設定SearchQuery中包含關鍵詞查詢的欄位。

HighlightParameter

numberOfFragments

返回高亮分區的最大數量,推薦設定為1。

fragmentSize

每個分區的長度。預設值100。

重要

實際返回分區的長度不會與該值嚴格相等。

preTag

查詢關鍵詞高亮的前置Tag,例如<em><b>。預設值為<em>,您可以按需自訂前置Tag。preTag支援的字元集包括< > " ' /a-zA-Z0-9

postTag

查詢關鍵詞高亮的後置Tag,例如</em></b>。預設值為</em>,您可以按需自訂前置Tag。postTag支援的字元集包括< > " ' /a-zA-Z0-9

highlightFragmentOrder

當高亮欄位返回多個分區時,分區的定序。

  • TEXT_SEQUENCE(預設):片段在文本中出現的順序。

  • SCORE:根據命中關鍵詞評分排序多個分區。

InnerHits參數

參數

說明

sort

Nested子行返回時的定序。

offset

當Nested列包含多個子行時,子行返回的起始位置。

limit

當Nested列包含多個子行時,返回子行的數量。預設值為3。

highlight

Nested子列高亮參數配置。具體配置說明請參見Highlight參數

使用方式

重要

只支援通過SDK方式使用查詢高亮功能。

進行高亮查詢之前,您需要完成如下準備工作。

  • 使用阿里雲帳號或者具有Table Store操作許可權的RAM使用者進行操作。如果需要為RAM使用者授權Table Store操作許可權,請參見通過RAM Policy為RAM使用者授權進行配置。

    使用SDK方式進行操作時,如果當前無可用AccessKey,則需要為阿里雲帳號或者RAM使用者建立AccessKey。具體操作,請參見建立AccessKey

  • 已建立資料表。具體操作,請參見資料表操作

  • 已為資料表建立多元索引且為指定欄位開啟了高亮查詢功能。具體操作,請參見建立多元索引

  • 使用SDK方式進行操作時,還需要完成初始化Client。具體操作,請參見初始化OTSClient

您可以通過Java SDKGo SDKPython SDKNode.js SDK使用查詢高亮功能。此處以Java SDK為例介紹查詢高亮功能的使用。

查詢非巢狀型別欄位時使用查詢高亮

以下樣本用於使用MatchQuery功能查詢表中Col_Text列的值能夠匹配hangzhou shanghai的資料,並在返回結果中對關鍵詞進行高亮顯示。其中Col_Text列為Text類型。

/**
 * MatchQuery關鍵詞高亮。
 */
public static void matchQueryWithHighlighting(SyncClient client) {
    SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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);

    // 列印查詢和高亮結果。查詢非巢狀型別欄位時設定prefix為空白即可。
    printSearchHit(resp.getSearchHits(), "");
}

/**
 * 列印searchHit內容。
 * @param searchHits searchHits
 * @param prefix Nested結構輸出時,增加首碼以列印層次資訊。
 */
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
    for (SearchHit searchHit : searchHits) {
        if (searchHit.getScore() != null) {
            System.out.printf("%s Score: %s\n", prefix, searchHit.getScore());
        }

        if (searchHit.getOffset() != null) {
            System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
        }

        if (searchHit.getRow() != null) {
            System.out.printf("%s Row: %s\n", prefix, searchHit.getRow().toString());
        }

        // 列印各欄位高亮分區結果。
        if (searchHit.getHighlightResultItem() != null) {
            System.out.printf("%s Highlight: \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();
    }
}

查詢巢狀型別欄位時使用查詢高亮

以下樣本用於使用NestedQuery功能查詢表中Col_Nested巢狀型別欄位中Level1_Col1_Nested子列的值能夠匹配hangzhou shanghai的資料,並在返回結果中對關鍵詞進行高亮顯示。

/**
 * NestedQuery查詢高亮,通過innerHits設定參數。
 */
public static void NestedQueryQueryWithHighlighting1(SyncClient client) {
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName("<TABLE_NAME>")
                .indexName("<SEARCH_INDEX_NAME>")
                .returnAllColumnsFromIndex(true)
                .searchQuery(SearchQuery.newBuilder()
                        .limit(5)
                        .query(QueryBuilders.nested()
                                .path("Col_Nested")
                                .scoreMode(ScoreMode.Min)
                                .query(QueryBuilders.match("Col_Nested.Level1_Colqia1_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(), "");
}

/**
 * 列印searchHit內容。
 * @param searchHits searchHits
 * @param prefix Nested結構輸出時,增加首碼以列印層次資訊。
 */
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
    for (SearchHit searchHit : searchHits) {
        if (searchHit.getScore() != null) {
            System.out.printf("%s Score: %s\n", prefix, searchHit.getScore());
        }

        if (searchHit.getOffset() != null) {
            System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
        }

        if (searchHit.getRow() != null) {
            System.out.printf("%s Row: %s\n", prefix, searchHit.getRow().toString());
        }

        // 列印各欄位高亮分區結果。
        if (searchHit.getHighlightResultItem() != null) {
            System.out.printf("%s Highlight: \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 Path: %s\n", prefix, searchInnerHit.getPath());
            System.out.printf("%s InnerHit: \n", prefix);
            printSearchHit(searchInnerHit.getSubSearchHits(), prefix + "    ");
        }

        System.out.println();
    }
}

假設多層級巢狀型別欄位Col_Nested中包括Level1_Col1_Text(Text類型)和Level1_Col2_Nested(Nested類型)兩列,其中Level1_Col2_Nested巢狀型別欄位包括Level2_Col1_Text子列。

以下樣本用於通過在NestedQuery中添加BoolQuery對Col_Nested欄位中的Level1_Col1_Text子列和Level1_Col2_Nested下的Level2_Col1_Text子列同時使用查詢高亮功能。

public static void NestedQueryWithHighlighting(SyncClient client) {
    SearchRequest searchRequest = SearchRequest.newBuilder()
        .tableName("<TABLE_NAME>")
        .indexName("<SEARCH_INDEX_NAME>")
        .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())
                                .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())
                        .build())
                .build())))
        .build();
    SearchResponse resp = client.search(searchRequest);

    // 列印高亮結果。
    printSearchHit(resp.getSearchHits(), "");
}

/**
 * 列印searchHit內容。
 * @param searchHits searchHits
 * @param prefix Nested結構輸出時,增加首碼以列印層次資訊。
 */
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
    for (SearchHit searchHit : searchHits) {
        if (searchHit.getScore() != null) {
            System.out.printf("%s Score: %s\n", prefix, searchHit.getScore());
        }

        if (searchHit.getOffset() != null) {
            System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
        }

        if (searchHit.getRow() != null) {
            System.out.printf("%s Row: %s\n", prefix, searchHit.getRow().toString());
        }

        // 列印各欄位高亮分區結果。
        if (searchHit.getHighlightResultItem() != null) {
            System.out.printf("%s Highlight: \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 Path: %s\n", prefix, searchInnerHit.getPath());
            System.out.printf("%s InnerHit: \n", prefix);
            printSearchHit(searchInnerHit.getSubSearchHits(), prefix + "    ");
        }

        System.out.println();
    }
}

計費說明

在資料查詢時使用查詢高亮功能不影響現有計費規則。

使用多元索引查詢資料時會消耗讀輸送量。更多資訊,請參見多元索引計量計費

常見問題

相關文檔