小編最近在做到一個檢索相關的需求,要求按照一個欄位的每個字母或者數位進行檢索,如果是不設定分詞規則的話,英文是按照單詞來進行分詞的。
小編以7.6.0版本做的功能哈,大家可以根據自己的版本去官網看看,應該區別不大
例子:
C6153PE-冬日戀歌
,要可以通過任何一個數位和字母進行檢索到,並且不區分大小寫。c
,6
,c6
等等!
今天官網上有一些例子,覺得和實戰還是有點區別,小編這裡通過了測試抓緊來記錄一下,希望幫助後來人哈!
我們進入官網找到我們需要的策略:
Elasticsearch策略官網
N-gram 分詞器
每當遇到指定字元列表中的一個時,ngram標記器首先將文字分解為單詞,然後發出 指定長度的每個單詞的N-gram。
N-gram 就像一個在單詞上移動的滑動視窗——一個指定長度的連續字元序列
。它們對於查詢不使用空格或複合詞長的語言很有用。
我們去kibana
進行測試分詞策略是否符合我們的要求:
POST _analyze
{
"tokenizer": "ngram",
"text": "C6153PE-冬日戀歌"
}
分詞分得細,會導致檢索的效率降低,但是需求如此,沒辦法,最重要的是小編這裡的資料量只有1w,其實換了這種分詞,是無感知的!
分詞策略規則:
ngram分詞器接受以下引數:
引數 | 解釋 |
---|---|
min_gram | 以 gram 為單位的最小長度。預設為1. |
max_gram | 以 gram 為單位的最大字元長度。預設為2. |
token_chars | 應包含在令牌中的字元類,Elasticsearch 將根據不屬於指定類的字元進行拆分。預設為[](保留所有字元)詳細引數見下表 |
custom_token_chars | 應被視為令牌一部分的自定義字元。例如,將此設定為+-_將使標記器將加號、減號和下劃線符號視為標記的一部分。 |
min_gram
將和設定max_gram
為相同的值通常是有意義的。長度越小,匹配的檔案越多,但匹配的質量越低。長度越長,匹配越具體。三元組(長度3)是一個很好的起點。官方比較推薦使用3,可能是因為效率分詞粒度兩不誤吧,這裡不符合小編的,小編這裡使用是1,2,也就是預設的值
token_chars引數 | 解釋例子 |
---|---|
letter | 字母,例如a, b,ï或京 |
digit | 數位,例如3或7 |
whitespace | 空白,例如" "或"\n" |
punctuation | 標點,例如!或" |
symbol | 標記, 例如$或√ |
custom | 自定義,需要使用 custom_token_chars設定設定的自定義字元 |
custom_token_chars
:
應被視為令牌一部分的自定義字元。例如,將此設定為+-_將使標記器將加號、減號和下劃線符號視為標記的一部分。
官方是使用一個欄位進行測試的,這裡小編就直接使用公司的索引進行演示了!
這裡是官網的例子:
下面放出來小編實戰後的例子:
總結就是在settings
設定分詞策略,在mappings
中進行使用即可!!
PUT /product
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"index": {
"max_result_window": 100000000
},
# 這裡使用分詞策略
"analysis": {
"analyzer": {
"my_analyzer": {
# 這裡分詞指定下面策略的具體設定的名稱
"tokenizer": "my_tokenizer",
# 這裡忽略大小寫設定
"filter": [
"lowercase"
]
}
},
# 具體策略設定
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 1,
"max_gram": 2,
"token_chars": [
"letter",
"digit"
]
}
}
}
},
"mappings": {
"dynamic": "strict",
"properties": {
"@timestamp": {
"type": "date"
},
"@version": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"cargoNo": {
"type": "text"
},
"name": {
"type": "text"
},
"sort": {
"type": "integer"
},
"attribute13": {
"type": "text",
# 在需要的欄位指定我們寫的分詞策略
"analyzer": "my_analyzer"
},
"isDeleted": {
"type": "integer"
}
}
}
}
為了公司,小編只貼上部分條件構建規則:
SearchRequest searchRequest = new SearchRequest("product");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder bool = new BoolQueryBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.should(QueryBuilders.matchPhraseQuery("name", model))
.should(QueryBuilders.matchPhraseQuery("cargoNo", model))
.should(QueryBuilders.wildcardQuery("cargoNo", "*" + model + "*"))
// 我們分詞規則的欄位查詢
.should(QueryBuilders.matchPhraseQuery("attribute13", model));
bool.must(boolQueryBuilder);
searchSourceBuilder.query(bool);
searchRequest.source(searchSourceBuilder);
我們拿著頁面感受一下分詞帶來的效果:
效果實現,隨便一個字母都可以查詢出來,這裡只顯示名稱和一個數位,其實是使用attribute13
來進行查詢的,是因為attribute13
是名稱的第一個-
之前的截出來的。
這樣我們就完成了一些客製化化的需求,完美交差,還得是看官網啊!!一定要去看官網!搜了好多都沒有這種的教學,寫出來幫助後來人,但是詳細的還得是看官網哈!小編這裡也是把官網的一些概念寫到了部落格里!!
如果對你有幫助還請不要吝嗇你的發財小手給小編來個一鍵三連哦!謝謝大家了!!