天天看點

Elasticsearch進階檢索之使用單個字母數字進行分詞N-gram tokenizer(不區分大小寫)【實戰篇】

一、前言

小編最近在做到一個檢索相關的需求,要求按照一個字段的每個字母或者數字進行檢索,如果是不設定分詞規則的話,英文是按照單詞來進行分詞的。

==小編以7.6.0版本做的功能哈,大家可以根據自己的版本去官網看看,應該差別不大==

例子:

C6153PE-冬日戀歌

,要可以通過任何一個數字和字母進行檢索到,并且不區分大小寫。

c

6

c6

等等!

今天官網上有一些例子,覺得和實戰還是有點差別,小編這裡通過了測試抓緊來記錄一下,希望幫助後來人哈!

二、測試分詞政策

我們進入官網找到我們需要的政策:

Elasticsearch政策官網

N-gram 分詞器

每當遇到指定字元清單中的一個時,ngram标記器首先将文本分解為單詞,然後發出 指定長度的每個單詞的N-gram。

N-gram 就像一個在單詞上移動的滑動視窗——

一個指定長度的連續字元序列

。它們對于查詢不使用空格或複合詞長的語言很有用。

我們去

kibana

進行測試分詞政策是否符合我們的要求:

POST _analyze
{
  "tokenizer": "ngram",
  "text": "C6153PE-冬日戀歌"
}
           

分詞分得細,會導緻檢索的效率降低,但是需求如此,沒辦法,最重要的是小編這裡的資料量隻有1w,其實換了這種分詞,是無感覺的!

Elasticsearch進階檢索之使用單個字母數字進行分詞N-gram tokenizer(不區分大小寫)【實戰篇】

分詞政策規則:

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

應被視為令牌一部分的自定義字元。例如,将此設定為+-_将使标記器将加号、減号和下劃線符号視為标記的一部分。

三、在索引字段中使用

官方是使用一個字段進行測試的,這裡小編就直接使用公司的索引進行示範了!

這裡是官網的例子:

Elasticsearch進階檢索之使用單個字母數字進行分詞N-gram tokenizer(不區分大小寫)【實戰篇】

下面放出來小編實戰後的例子:

總結就是在

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"
      }
    }
  }
}

           

四、在springboot中實戰

為了公司,小編隻粘貼部分條件建構規則:

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

是名稱的第一個

-

之前的截出來的。

Elasticsearch進階檢索之使用單個字母數字進行分詞N-gram tokenizer(不區分大小寫)【實戰篇】

五、總結

這樣我們就完成了一些定制化的需求,完美交差,還得是看官網啊!!一定要去看官網!搜了好多都沒有這種的教程,寫出來幫助後來人,但是詳細的還得是看官網哈!小編這裡也是把官網的一些概念寫到了部落格裡!!

繼續閱讀