固定評分查詢

更新時間:
Copy as MD

固定評分查詢(ConstScoreQuery)將子查詢封裝為過濾條件,所有命中文檔統一返回固定相關性分數 1.0,不再按 BM25 等演算法計算評分。

前提條件

參數說明

參數

說明

TableName

資料表名稱。

IndexName

多元索引名稱。

Query

設定查詢類型為 ConstScoreQuery

Filter

內部子查詢條件,支援任意一種 Query 類型。ConstScoreQuery 僅判斷文檔是否命中該子查詢,命中即返回固定分數 1.0。

Limit

本次查詢返回的最大行數。如果僅需統計行數而不需要具體資料,可設定 Limit=0,此時不返回任何行資料。

ColumnsToGet

是否返回所有列,包含 ReturnAllColumns 兩個參數。ReturnAll 預設為 false,僅返回主鍵列;通過 Columns 可指定額外返回的列。ReturnAll 設為 true 時,返回所有列。

樣本

基本用法

使用 ConstScoreQuery 包裹 MatchQuery,對 Col_Text 列匹配關鍵詞 tablestore,所有命中文檔統一返回固定相關性分 1.0。按 score 降序排序便於驗證固定分效果。

/**
 * 通過 ConstScoreQuery 進行固定評分查詢。
 * 所有命中文檔的 score 均為 1.0,不受文本長度、詞頻等因素影響。
 */
func constScoreQuery(client *tablestore.TableStoreClient) {
	// 構造內部子查詢:MatchQuery,對 Col_Text 列匹配關鍵詞 tablestore。
	// 用 ConstScoreQuery 包裹 MatchQuery,所有命中文檔統一返回固定相關性分 1.0。
	query := &search.ConstScoreQuery{
		Filter: &search.MatchQuery{
			FieldName: "Col_Text",
			Text:      "tablestore",
		},
	}

	searchQuery := search.NewSearchQuery()
	searchQuery.SetQuery(query)
	searchQuery.SetLimit(20)
	// searchQuery.SetGetTotalCount(true) // 設定返回匹配的總行數。
	// 按 score 排序,便於驗證固定分效果。
	searchQuery.SetSort(&search.Sort{
		Sorters: []search.Sorter{
			&search.ScoreSort{Order: search.SortOrder_DESC.Enum()},
		},
	})

	searchRequest := &tablestore.SearchRequest{}
	searchRequest.SetTableName("<TABLE_NAME>")
	searchRequest.SetIndexName("<SEARCH_INDEX_NAME>")
	searchRequest.SetSearchQuery(searchQuery)

	resp, err := client.Search(searchRequest)
	if err != nil {
		fmt.Printf("%#v\n", err)
		return
	}
	fmt.Println("RowCount:", len(resp.Rows))
	// 驗證所有命中文檔的 score 均為 1.0。
	for _, row := range resp.Rows {
		jsonBody, _ := json.Marshal(row)
		fmt.Println("Row:", string(jsonBody))
	}
}

返回指定列

預設僅返回主鍵列。通過 ColumnsToGet 可指定返回所有列或自訂返回列。在基本用法的 searchRequest 構造完成後追加以下代碼。

// 通過 ColumnsToGet 控制返回列。預設僅返回主鍵列。
// 方式一:返回所有列。
searchRequest.SetColumnsToGet(&tablestore.ColumnsToGet{ReturnAll: true})
// 方式二:返回指定列。
// searchRequest.SetColumnsToGet(&tablestore.ColumnsToGet{Columns: []string{"Col_Text", "Col_Keyword"}})

resp, err := client.Search(searchRequest)
if err != nil {
	fmt.Printf("%#v\n", err)
	return
}
fmt.Println("RowCount:", len(resp.Rows))
for _, row := range resp.Rows {
	jsonBody, _ := json.Marshal(row)
	fmt.Println("Row:", string(jsonBody))
}

在 BoolQuery 中組合使用

以下樣本在 BoolQueryMustQueries 中同時使用 ConstScoreQueryMatchQueryConstScoreQuery 包裹 TermQuery,貢獻固定分數 1.0;MatchQuery 參與 BM25 評分。最終分數 = 1.0 + BM25 分數。

func constScoreInBoolQuery(client *tablestore.TableStoreClient) {
    // 子查詢一:ConstScoreQuery 包裹 TermQuery,對 status 欄位做精確過濾,貢獻固定分 1.0。
    constScoreQuery := &search.ConstScoreQuery{
        Filter: &search.TermQuery{
            FieldName: "status",
            Term:      "active",
        },
    }

    // 子查詢二:MatchQuery,對 title 欄位正常參與 BM25 評分。
    matchQuery := &search.MatchQuery{
        FieldName: "title",
        Text:      "tablestore",
    }

    // 構造 BoolQuery,MustQueries 中同時包含 ConstScoreQuery 與 MatchQuery。
    // 最終 score = ConstScoreQuery 固定分(1.0) + MatchQuery 的 BM25 分數。
    boolQuery := &search.BoolQuery{
        MustQueries: []search.Query{
            constScoreQuery,
            matchQuery,
        },
    }

    searchQuery := search.NewSearchQuery()
    searchQuery.SetQuery(boolQuery)
    searchQuery.SetLimit(20)
    // searchQuery.SetGetTotalCount(true) // 設定返回匹配的總行數。
    searchQuery.SetSort(&search.Sort{
        Sorters: []search.Sorter{
            &search.ScoreSort{Order: search.SortOrder_DESC.Enum()},
        },
    })

    searchRequest := &tablestore.SearchRequest{}
    searchRequest.SetTableName("<TABLE_NAME>")
    searchRequest.SetIndexName("<SEARCH_INDEX_NAME>")
    searchRequest.SetSearchQuery(searchQuery)

    resp, err := client.Search(searchRequest)
    if err != nil {
        fmt.Printf("%#v\n", err)
        return
    }
    fmt.Println("RowCount:", len(resp.Rows))
    for _, row := range resp.Rows {
        jsonBody, _ := json.Marshal(row)
        fmt.Println("Row:", string(jsonBody))
    }
}

與 ParallelScan 組合使用

在並發匯出情境中使用 ConstScoreQuery 作為 ScanQuery 的查詢條件,避免在匯出時計算 BM25 分數。完整並發流程請參見並發匯出資料

func constScoreInParallelScan(client *tablestore.TableStoreClient, sessionId []byte) {
	// 構造 ConstScoreQuery 包裹 MatchQuery,所有命中文檔統一返回固定相關性分 1.0。
	constScoreQuery := &search.ConstScoreQuery{
		Filter: &search.MatchQuery{
			FieldName: "Col_Text",
			Text:      "tablestore",
		},
	}

	// 構造 ScanQuery,將 ConstScoreQuery 作為查詢條件。
	scanQuery := search.NewScanQuery().
		SetQuery(constScoreQuery).
		SetLimit(2000)

	scanRequest := &tablestore.ParallelScanRequest{}
	scanRequest.SetTableName("<TABLE_NAME>")
	scanRequest.SetIndexName("<SEARCH_INDEX_NAME>")
	scanRequest.SetScanQuery(scanQuery)
	scanRequest.SetSessionId(sessionId) // 由 ComputeSplits 介面擷取,類型為 []byte,各 worker 共用同一 sessionId,用戶端按 splitsSize 隱式分發並發任務。

	scanResponse, err := client.ParallelScan(scanRequest)
	if err != nil {
		fmt.Printf("%#v\n", err)
		return
	}
	fmt.Println("RowCount:", len(scanResponse.Rows))
	for _, row := range scanResponse.Rows {
		jsonBody, _ := json.Marshal(row)
		fmt.Println("Row:", string(jsonBody))
	}
}