目的:根據商品名稱按中文和拼音分頁搜索,並且按商品名去重。這裏以Elasticsearch7.4爲例。
一、插件安裝
1、安裝ik中文分詞器
下載地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.4.0
- 進入es安裝目錄 elasticsearch/plugins/
- 新建文件夾:analysis-ik
- 將下載的壓縮包解壓到elasticsearch/plugins/analysis-ik目錄下
- 重啓es
2、安裝pinyin分詞器
下載地址:https://github.com/medcl/elasticsearch-analysis-pinyin/releases/tag/v7.4.0
- 進入es安裝目錄 elasticsearch/plugins/
- 新建文件夾:pinyin
- 將下載的壓縮包解壓到elasticsearch/plugins/pinyin目錄下
- 重啓es
二、索引結構
創建索引:
PUT /sku_index2
{
"mappings":{
"properties": {
"id": {
"type": "keyword"
},
"skuId": {
"type": "long"
},
"skuName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"ik": {
"type": "text",
"analyzer": "ik_max_word"
},
"pinyin": {
"type": "text",
"analyzer": "pinyin"
}
}
}
}
}
}
一個string
字段可以映射爲text
用於全文搜索的字段,也可以映射爲keyword
用於排序或聚合的字段。大多數數據類型通過fields
參數支持多字段。這裏設置兩個分詞器:中文和拼音,關鍵字類型是爲去重操作作準備。
新增文檔數據...(省略)
測試分詞器:
GET /sku_index2/_analyze
{
"text": "我今天超級無敵開心",
"analyzer": "ik_max_word"
}
GET /b2b_mall_sku_index2/_analyze
{
"text": "chaojikaixin",
"analyzer": "pinyin"
}
三、 代碼實現
public Page<B2bMallSkuDto> search1(String query, Integer hits, Integer start) {
if (Objects.isNull(hits)) {
hits = 10;
}
if (Objects.isNull(start)) {
start = 0;
}
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//搜索條件 //此處中文匹配得分稍高於拼音,默認boost爲1
//此處注意,當must和should共用時,should條件會失效,需要調整方法調用
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("skuName.ik", query).boost(1.2f))
.should(QueryBuilders.matchQuery("skuName.pinyin", query));
queryBuilder.withQuery(boolQueryBuilder);
//分頁 開始位置,每頁條數
queryBuilder.withPageable(PageRequest.of(start, hits));
//摺疊去重(按照skuName去重)
queryBuilder.withCollapseField("skuName.keyword");
return b2bMallRepository.search(queryBuilder.build());
}
- must :所有的語句都 必須(must) 匹配,與 AND 等價。
- must_not :所有的語句都 不能(must not) 匹配,與 NOT 等價。
- should :至少有一個語句要匹配,與 OR 等價。
Collapse性能高於top_hits + 聚合統計agg,Collapse字段必須是keyword類型
四、問題
withCollapseField()方法摺疊去重後,分頁後結果的totalCount數量指疊前數量。
參考文檔: