Elasticsearch:分詞器中的 token 過濾器使用示例

語言: CN / TW / HK

分詞器在 Elasticsearch 的使用中非常重要。分詞器中的過濾器可以幫我們對最終的分詞進行處理,從而使得我們得到的最終分詞會影響存儲的大小和搜索的方式。在今天的文章中,我來分享一下一些常用的分詞器中的 token 過濾器。更多有關 token 過濾器的內容可以在 Elastic 的官方文檔查詢。有關更多關於 analyzer 的閲讀,請參考我之前的文章 “ Elasticsearch: analyzer ”。

如上圖所示,在分詞器的構成中,它可以含有 0或多個 char filters, 有且只有一個 tokenizer, 0或多個 token filters。 

安裝

在今天的展示中,我們需要安裝中文最為流行的 IK 分詞器。詳細的安裝步驟請參考文章 “ Elasticsearch:IK 中文分詞器 ”。

Apostrophe token filter

去掉撇號後的所有字符,包括撇號本身。這個在英文中比較常見。比如,我們寫如下的句子:

This is Tom's clothes.
複製代碼

在上面,我們可以看到有一個 ’ 符號。在實際的分詞中,我們希望去掉 ' 符號後面的所有字符。我們可以使用如下的例子來進行展示:

1.  GET /_analyze
2.  {
3.    "tokenizer" : "standard",
4.    "filter" : ["apostrophe"],
5.    "text" : "Istanbul'a veya Istanbul'dan"
6.  }


複製代碼

上面的 filter 產生如下的結果:

1.  {
2.    "tokens": [3.      {4.        "token": "Istanbul",5.        "start_offset": 0,6.        "end_offset": 10,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "veya",12.        "start_offset": 11,13.        "end_offset": 15,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "Istanbul",19.        "start_offset": 16,20.        "end_offset": 28,21.        "type": "<ALPHANUM>",22.        "position": 223.      }24.    ]
25.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

在實際的使用中,我們可以使用如下的例子來進行展示:

1.  PUT test
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "type": "custom",
8.            "tokenizer": "standard",
9.            "filter": [
10.              "apostrophe",
11.              "lowercase"
12.              ]
13.          }
14.        }
15.      }
16.    },
17.    "mappings": {
18.      "properties": {
19.        "text": {
20.          "type": "text",
21.          "analyzer": "my_analyzer"
22.        }
23.      }
24.    }
25.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

在上面,我們定義了一個叫做 test 的索引,並且它的 text 字段使用 my_analyzer。在沒有特定指定 search_analyzer 的情況下,分詞和搜索將使用同樣的一個分詞器:my_analyzer。我們使用如下的一個命令來寫入一個文檔:

1.  PUT test/_doc/1
2.  {
3.    "text": "Istanbul'a veya Istanbul'dan"
4.  }


複製代碼

那麼我們可以使用如下的一個搜索來搜索該文檔:

1.  GET test/_search
2.  {
3.    "query": {
4.      "match": {
5.        "text": "Istanbul"
6.      }
7.    }
8.  }


複製代碼

上面的搜索結果為:

1.  {
2.    "tokens": [3.      {4.        "token": "Istanbul",5.        "start_offset": 0,6.        "end_offset": 10,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "veya",12.        "start_offset": 11,13.        "end_offset": 15,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "Istanbul",19.        "start_offset": 16,20.        "end_offset": 28,21.        "type": "<ALPHANUM>",22.        "position": 223.      }24.    ]
25.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

ASCII folding token filter

將不在 Basic Latin Unicode 塊中的字母、數字和符號字符(前 127 個 ASCII 字符)轉換為它們的 ASCII 等效字符(如果存在)。 例如,過濾器將 à 更改為 a。

以下 analyze API 請求使用 asciifolding 過濾器刪除 açaí à la carte 中的變音符號:

1.  GET /_analyze
2.  {
3.    "tokenizer" : "standard",
4.    "filter" : ["asciifolding"],
5.    "text" : "açaí à la carte"
6.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [3.      {4.        "token": "acai",5.        "start_offset": 0,6.        "end_offset": 4,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "a",12.        "start_offset": 5,13.        "end_offset": 6,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "la",19.        "start_offset": 7,20.        "end_offset": 9,21.        "type": "<ALPHANUM>",22.        "position": 223.      },24.      {25.        "token": "carte",26.        "start_offset": 10,27.        "end_offset": 15,28.        "type": "<ALPHANUM>",29.        "position": 330.      }31.    ]
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

Classic token filter

對經典分詞器生成的術語執行可選的後處理。

此過濾器從單詞末尾刪除英語所有格 ('s) 並從首字母縮略詞中刪除點。 它使用 Lucene 的ClassicFilter。例如:

1.  GET /_analyze
2.  {
3.    "tokenizer" : "classic",
4.    "filter" : ["classic"],
5.    "text" : "The 2 Q.U.I.C.K. Brown-Foxes jumped over the lazy dog's bone."
6.  }


複製代碼

上面將返回:

1.  {
2.    "tokens": [3.      {4.        "token": "The",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "2",12.        "start_offset": 4,13.        "end_offset": 5,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "QUICK",19.        "start_offset": 6,20.        "end_offset": 16,21.        "type": "<ACRONYM>",22.        "position": 223.      },24.      {25.        "token": "Brown",26.        "start_offset": 17,27.        "end_offset": 22,28.        "type": "<ALPHANUM>",29.        "position": 330.      },31.      {32.        "token": "Foxes",33.        "start_offset": 23,34.        "end_offset": 28,35.        "type": "<ALPHANUM>",36.        "position": 437.      },38.      {39.        "token": "jumped",40.        "start_offset": 29,41.        "end_offset": 35,42.        "type": "<ALPHANUM>",43.        "position": 544.      },45.      {46.        "token": "over",47.        "start_offset": 36,48.        "end_offset": 40,49.        "type": "<ALPHANUM>",50.        "position": 651.      },52.      {53.        "token": "the",54.        "start_offset": 41,55.        "end_offset": 44,56.        "type": "<ALPHANUM>",57.        "position": 758.      },59.      {60.        "token": "lazy",61.        "start_offset": 45,62.        "end_offset": 49,63.        "type": "<ALPHANUM>",64.        "position": 865.      },66.      {67.        "token": "dog",68.        "start_offset": 50,69.        "end_offset": 55,70.        "type": "<APOSTROPHE>",71.        "position": 972.      },73.      {74.        "token": "bone",75.        "start_offset": 56,76.        "end_offset": 60,77.        "type": "<ALPHANUM>",78.        "position": 1079.      }80.    ]
81.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

顯然,在 Q.U.I.CK. 中的點都被刪除了,同時 dog's  中的 ‘s 被去掉了。

Conditional token filter

將一組 token 過濾器應用於與提供的謂詞腳本中的條件匹配的標記。此過濾器使用 Lucene 的 ConditionalTokenFilter。

以下analyze API 請求使用條件過濾器來匹配 THE QUICK BROWN FOX 中少於 5 個字符的標記。 然後它將 lowercase 過濾器應用於那些匹配的標記,將它們轉換為小寫。

1.  GET /_analyze
2.  {
3.    "tokenizer": "standard",
4.    "filter": [
5.      {
6.        "type": "condition",
7.        "filter": [ "lowercase" ],
8.        "script": {
9.          "source": "token.getTerm().length() < 5"
10.        }
11.      }
12.    ],
13.    "text": "THE QUICK BROWN FOX"
14.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [3.      {4.        "token": "the",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "QUICK",12.        "start_offset": 4,13.        "end_offset": 9,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "BROWN",19.        "start_offset": 10,20.        "end_offset": 15,21.        "type": "<ALPHANUM>",22.        "position": 223.      },24.      {25.        "token": "fox",26.        "start_offset": 16,27.        "end_offset": 19,28.        "type": "<ALPHANUM>",29.        "position": 330.      }31.    ]
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

請注意上面的 script 指的是painless script。在上面,我們看到雖然有 lowercase 過濾器,但是它僅僅作用於 token 的長度小於 5 的 token 上面。從輸出中,我們可以看到,BROWN 及 QUICK 並沒有變為小寫,原因是他們的長度是5,不滿足條件。

自定義並添加到分詞器

要自定義 conditional 過濾器,請將其複製以創建新的自定義標記過濾器的基礎。 你可以使用其可配置參數修改過濾器。

例如,以下創建索引 API 請求使用自定義 conditional 過濾器來配置新的自定義分詞器。 自定義條件過濾器匹配流中的第一個 token。 然後它使用反向過濾器反轉匹配的 token。

1.  PUT /palindrome_list
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "whitespace_reverse_first_token": {
7.            "tokenizer": "whitespace",
8.            "filter": [ "reverse_first_token" ]
9.          }
10.        },
11.        "filter": {
12.          "reverse_first_token": {
13.            "type": "condition",
14.            "filter": [ "reverse" ],
15.            "script": {
16.              "source": "token.getPosition() === 0"
17.            }
18.          }
19.        }
20.      }
21.    }
22.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

Fingerprint token filter

從 token 流中排序和刪除重複的 token,然後將流連接成單個輸出 token。例如,此過濾器將 [ the, fox, was, very, very, quick ] 標記流更改如下:

  1. 將 token 按字母順序排序為 [ fox, quick, the, very, very, was ]
  2. 刪除 very token 的重複實例。
  3. 將 token 流連接到輸出單個 token:[fox quick the very was]

此過濾器使用 Lucene 的FingerprintFilter。例如:

以下analyze API 請求使用指紋過濾器為文本  zebra jumps over resting resting dog 創建單個輸出 token:

1.  GET _analyze
2.  {
3.    "tokenizer" : "whitespace",
4.    "filter" : ["fingerprint"],
5.    "text" : "zebra jumps over resting resting dog"
6.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [
3.      {
4.        "token": "dog jumps over resting zebra",
5.        "start_offset": 0,
6.        "end_offset": 36,
7.        "type": "fingerprint",
8.        "position": 0
9.      }
10.    ]
11.  }


複製代碼

請注意的是它返回 有一個 token。

Reverse token filter

反轉流中的每個 token。 例如,你可以使用反向過濾器將 cat 更改為 tac。反轉 token 對於基於後綴的搜索很有用,例如查找以 -ion 結尾的單詞或按擴展名搜索文件名。請參閲我之前的文章 “ Elasticsearch:正確使用 regexp 搜索 ”。這個過濾器使用 Lucene 的ReverseStringFilter。

以下 analyze API 請求使用反向過濾器來反轉 quick fox jumps 中的每個 token:

1.  GET _analyze
2.  {
3.    "tokenizer" : "standard",
4.    "filter" : ["reverse"],
5.    "text" : "quick fox jumps"
6.  }


複製代碼

上面的過濾器返回:

1.  {
2.    "tokens": [3.      {4.        "token": "kciuq",5.        "start_offset": 0,6.        "end_offset": 5,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "xof",12.        "start_offset": 6,13.        "end_offset": 9,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "spmuj",19.        "start_offset": 10,20.        "end_offset": 15,21.        "type": "<ALPHANUM>",22.        "position": 223.      }24.    ]
25.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

就如第一個例子中顯示的那樣,我們可以使用如下的例子來定義並使用這個 filter:

1.  PUT reverse_example
2.  {
3.    "settings" : {
4.      "analysis" : {
5.        "analyzer" : {
6.          "whitespace_reverse" : {
7.            "tokenizer" : "whitespace",
8.            "filter" : ["reverse"]
9.          }
10.        }
11.      }
12.    },
13.    "mappings": {
14.      "properties": {
15.        "text": {
16.          "type": "text",
17.          "analyzer": "whitespace_reverse"
18.        }
19.      }
20.    }
21.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

我們可以使用如下的命令來寫入一個文檔:

1.  PUT reverse_example/_doc/1
2.  {
3.    "text": "I like the speed of this network"
4.  }


複製代碼

我們可以使用如下的方法來進行搜索:

1.  GET reverse_example/_search
2.  {
3.    "query": {
4.      "regexp": {
5.        "text": "krow.*"
6.      }
7.    }
8.  }


複製代碼

特別需要指出的是:當我們使用通配符在前面進行搜索時搜索比較慢。這個時候,我們可以選擇 reverse 過濾器來進行反轉。

Unique token filter

從流中刪除重複的 token。 例如,你可以使用 unique 過濾器將 the lazy lazy dog 更改為 the lazy dog。如果 only_on_same_position 參數設置為 true,則unique 過濾器僅刪除同一位置的重複標記。

注意:當 only_on_same_position 為 true 時,unique 過濾器的工作方式與remove_duplicates 過濾器相同。

我們使用如下的例子來進行展示:

1.  GET _analyze
2.  {
3.    "tokenizer" : "whitespace",
4.    "filter" : ["unique"],
5.    "text" : "the quick fox jumps the lazy fox"
6.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [3.      {4.        "token": "the",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "word",8.        "position": 09.      },10.      {11.        "token": "quick",12.        "start_offset": 4,13.        "end_offset": 9,14.        "type": "word",15.        "position": 116.      },17.      {18.        "token": "fox",19.        "start_offset": 10,20.        "end_offset": 13,21.        "type": "word",22.        "position": 223.      },24.      {25.        "token": "jumps",26.        "start_offset": 14,27.        "end_offset": 19,28.        "type": "word",29.        "position": 330.      },31.      {32.        "token": "lazy",33.        "start_offset": 24,34.        "end_offset": 28,35.        "type": "word",36.        "position": 437.      }38.    ]
39.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

顯然上面的返回中,只有一個 fox,而在原文檔中有兩個 fox。我們可以通過如下的方式來添加這個過濾器到 analyzer 中:

1.  PUT custom_unique_example
2.  {
3.    "settings" : {
4.      "analysis" : {
5.        "analyzer" : {
6.          "standard_truncate" : {
7.          "tokenizer" : "standard",
8.          "filter" : ["unique"]
9.          }
10.        }
11.      }
12.    }
13.  }


複製代碼

我們可以通過如下的方式來定製這個過濾器:

1.  PUT letter_unique_pos_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "letter_unique_pos": {
7.            "tokenizer": "letter",
8.            "filter": [ "unique_pos" ]
9.          }
10.        },
11.        "filter": {
12.          "unique_pos": {
13.            "type": "unique",
14.            "only_on_same_position": true
15.          }
16.        }
17.      }
18.    }
19.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

在上面,我們設置 only_on_same_position 為 true。在默認的情況下,這個值為 false。

Length token filter

刪除比指定字符長度更短或更長的標記。 例如,你可以使用長度過濾器來排除短於 2 個字符的標記和長於 5 個字符的標記。此過濾器使用 Lucene 的LengthFilter。

提示:長度過濾器刪除整個 token。 如果你希望將 token 縮短到特定長度,請使用truncate 過濾器。

例如:

1.  GET _analyze
2.  {
3.    "tokenizer": "whitespace",
4.    "filter": [
5.      {
6.        "type": "length",
7.        "min": 0,
8.        "max": 4
9.      }
10.    ],
11.    "text": "the quick brown fox jumps over the lazy dog"
12.  }


複製代碼

上面的命令返回長度為 0 到 4 的 token:

1.  {
2.    "tokens": [3.      {4.        "token": "the",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "word",8.        "position": 09.      },10.      {11.        "token": "fox",12.        "start_offset": 16,13.        "end_offset": 19,14.        "type": "word",15.        "position": 316.      },17.      {18.        "token": "over",19.        "start_offset": 26,20.        "end_offset": 30,21.        "type": "word",22.        "position": 523.      },24.      {25.        "token": "the",26.        "start_offset": 31,27.        "end_offset": 34,28.        "type": "word",29.        "position": 630.      },31.      {32.        "token": "lazy",33.        "start_offset": 35,34.        "end_offset": 39,35.        "type": "word",36.        "position": 737.      },38.      {39.        "token": "dog",40.        "start_offset": 40,41.        "end_offset": 43,42.        "type": "word",43.        "position": 844.      }45.    ]
46.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

這個過濾器對中文也有很多的幫助。比如,我們只想有超過兩個字的中文 token:

1.  PUT twitter
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "tokenizer": "ik_smart",
8.            "filter": [
9.              "longer_than_2"
10.            ]
11.          }
12.        },
13.        "filter": {
14.          "longer_than_2": {
15.            "type": "length",
16.            "min": 2
17.          }
18.        }
19.      }
20.    },
21.    "mappings": {
22.      "properties": {
23.        "text": {
24.          "type": "text",
25.          "analyzer": "my_analyzer"
26.        }
27.      }
28.    }
29.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

我們使用上面的索引來進行測試:

1.  GET twitter/_analyze
2.  {
3.    "analyzer": "my_analyzer",
4.    "text": ["我愛北京天安門"]
5.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [3.      {4.        "token": "北京",5.        "start_offset": 2,6.        "end_offset": 4,7.        "type": "CN_WORD",8.        "position": 29.      },10.      {11.        "token": "天安門",12.        "start_offset": 4,13.        "end_offset": 7,14.        "type": "CN_WORD",15.        "position": 316.      }17.    ]
18.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

顯然它只返回 “北京” 及 “天安門” 這個兩個長度超過 2 的 token。我們和如下的分詞進行比較:

1.  GET _analyze
2.  {
3.    "analyzer": "ik_smart",
4.    "text": ["我愛北京天安門"]
5.  }


複製代碼
1.  {
2.    "tokens": [3.      {4.        "token": "我",5.        "start_offset": 0,6.        "end_offset": 1,7.        "type": "CN_CHAR",8.        "position": 09.      },10.      {11.        "token": "愛",12.        "start_offset": 1,13.        "end_offset": 2,14.        "type": "CN_CHAR",15.        "position": 116.      },17.      {18.        "token": "北京",19.        "start_offset": 2,20.        "end_offset": 4,21.        "type": "CN_WORD",22.        "position": 223.      },24.      {25.        "token": "天安門",26.        "start_offset": 4,27.        "end_offset": 7,28.        "type": "CN_WORD",29.        "position": 330.      }31.    ]
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

很顯然,當我們寫入如下的文檔:

1.  PUT twitter/_doc/1
2.  {
3.    "text": "我愛北京天安門"
4.  }


複製代碼

我們使用如下的命令來進行搜索:

1.  GET twitter/_search
2.  {
3.    "query": {
4.      "match": {
5.        "text": "我"
6.      }
7.    }
8.  }


複製代碼

它將不返回任何的文檔,但是如果我們使用如下的命令來進行搜索:

1.  GET twitter/_search
2.  {
3.    "query": {
4.      "match": {
5.        "text": "北京"
6.      }
7.    }
8.  }


複製代碼

它將返回我們的文檔。

Lower token filter

將 token 文本更改為小寫。 例如,你可以使用 lowercase 過濾器將 THE Lazy DoG 更改為 the lazy dog。

除了默認過濾器之外,lowercase token 過濾器還提供對 Lucene 的希臘語、愛爾蘭語和土耳其語的特定語言小寫過濾器的訪問。

例如:

1.  GET _analyze
2.  {
3.    "tokenizer" : "standard",
4.    "filter" : ["lowercase"],
5.    "text" : "THE Quick FoX JUMPs"
6.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [3.      {4.        "token": "the",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "quick",12.        "start_offset": 4,13.        "end_offset": 9,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "fox",19.        "start_offset": 10,20.        "end_offset": 13,21.        "type": "<ALPHANUM>",22.        "position": 223.      },24.      {25.        "token": "jumps",26.        "start_offset": 14,27.        "end_offset": 19,28.        "type": "<ALPHANUM>",29.        "position": 330.      }31.    ]
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

很顯然,它把上面的大寫字母都變為小寫的了。

Upercase token filter

將 token 文本更改為大寫。 例如,你可以使用大寫過濾器將 Lazy Dog 更改為 THE LAZY DOG。此過濾器使用 Lucene 的UpperCaseFilter。

以下 analyze API 請求使用默認 uppercase 過濾器將 Quick FoX JUMP 更改為大寫:

1.  GET _analyze
2.  {
3.    "tokenizer" : "standard",
4.    "filter" : ["uppercase"],
5.    "text" : "the Quick FoX JUMPs"
6.  }


複製代碼

上面的命令返回結果:

1.  {
2.    "tokens": [3.      {4.        "token": "THE",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "QUICK",12.        "start_offset": 4,13.        "end_offset": 9,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "FOX",19.        "start_offset": 10,20.        "end_offset": 13,21.        "type": "<ALPHANUM>",22.        "position": 223.      },24.      {25.        "token": "JUMPS",26.        "start_offset": 14,27.        "end_offset": 19,28.        "type": "<ALPHANUM>",29.        "position": 330.      }31.    ]
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

以下創建索引 API 請求使用 upercase 過濾器來配置新的自定義分詞器。

1.  PUT uppercase_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "whitespace_uppercase": {
7.            "tokenizer": "whitespace",
8.            "filter": [ "uppercase" ]
9.          }
10.        }
11.      }
12.    }
13.  }


複製代碼

Stop token filter

從 token 流中刪除停用詞。未自定義時,過濾器默認刪除以下英文停用詞:

a, an, and, are, as, at, be, but, by, for, if, in, into, is, it, no, not, of, on, or, such, that, the, their, then, there, these, they, this, to, was, will, with
複製代碼

除了英語之外,stop 過濾器還支持多種語言的預定義stop 詞列表。 你還可以將自己的 stop 詞指定為數組或文件。stop 過濾器使用 Lucene 的StopFilter。

例子:

下面的 analyze API 請求使用 stop 過濾器從 a quick fox jumps over the lazy dog 來刪除停用詞 a 和 the:

1.  GET /_analyze
2.  {
3.    "tokenizer": "standard",
4.    "filter": [ "stop" ],
5.    "text": "a quick fox jumps over the lazy dog"
6.  }


複製代碼

上面的命令返回結果:

1.  {
2.    "tokens": [3.      {4.        "token": "quick",5.        "start_offset": 2,6.        "end_offset": 7,7.        "type": "<ALPHANUM>",8.        "position": 19.      },10.      {11.        "token": "fox",12.        "start_offset": 8,13.        "end_offset": 11,14.        "type": "<ALPHANUM>",15.        "position": 216.      },17.      {18.        "token": "jumps",19.        "start_offset": 12,20.        "end_offset": 17,21.        "type": "<ALPHANUM>",22.        "position": 323.      },24.      {25.        "token": "over",26.        "start_offset": 18,27.        "end_offset": 22,28.        "type": "<ALPHANUM>",29.        "position": 430.      },31.      {32.        "token": "lazy",33.        "start_offset": 27,34.        "end_offset": 31,35.        "type": "<ALPHANUM>",36.        "position": 637.      },38.      {39.        "token": "dog",40.        "start_offset": 32,41.        "end_offset": 35,42.        "type": "<ALPHANUM>",43.        "position": 744.      }45.    ]
46.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

從上面的輸出結果中,我們可以看到 a 及 the 沒有出現。

如果我們想自定義 stop 過濾器,我們可以仿照如下的方法:

1.  PUT stop_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "tokenizer": "standard",
8.            "filter": [
9.              "my_stop"
10.            ]
11.          }
12.        },
13.        "filter": {
14.          "my_stop": {
15.            "type": "stop",
16.            "stopwords": [
17.              "over",
18.              "dog"
19.            ]
20.          }
21.        }
22.      }
23.    },
24.    "mappings": {
25.      "properties": {
26.        "text": {
27.          "type": "text",
28.          "analyzer": "my_analyzer"
29.        }
30.      }
31.    }
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

在上面,我們自定義了一個叫做 my_stop 的 stop 過濾器。它自己含有 over 及 dog。也就是説 over 及 dog 將不會被分詞。我們使用如下的命令來進行測試:

1.  GET stop_example/_analyze
2.  {
3.    "analyzer": "my_analyzer",
4.    "text": ["a quick fox jumps over the lazy dog"]
5.  }


複製代碼

上面的命令返回結果:

1.  {
2.    "tokens": [3.      {4.        "token": "a",5.        "start_offset": 0,6.        "end_offset": 1,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "quick",12.        "start_offset": 2,13.        "end_offset": 7,14.        "type": "<ALPHANUM>",15.        "position": 116.      },17.      {18.        "token": "fox",19.        "start_offset": 8,20.        "end_offset": 11,21.        "type": "<ALPHANUM>",22.        "position": 223.      },24.      {25.        "token": "jumps",26.        "start_offset": 12,27.        "end_offset": 17,28.        "type": "<ALPHANUM>",29.        "position": 330.      },31.      {32.        "token": "the",33.        "start_offset": 23,34.        "end_offset": 26,35.        "type": "<ALPHANUM>",36.        "position": 537.      },38.      {39.        "token": "lazy",40.        "start_offset": 27,41.        "end_offset": 31,42.        "type": "<ALPHANUM>",43.        "position": 644.      }45.    ]
46.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

從上面的結果中,我們可以看出來, dog 及 over 不見了。當然,我們也看到了 a 及 the 又同時出現了。如果我們還是想保持之前的默認的 stop 過濾器,我們可以重新設計 stop_example 索引:

1.  DELETE stop_example

3.  PUT stop_example
4.  {
5.    "settings": {
6.      "analysis": {
7.        "analyzer": {
8.          "my_analyzer": {
9.            "tokenizer": "standard",
10.            "filter": [
11.              "my_stop",
12.              "stop"
13.            ]
14.          }
15.        },
16.        "filter": {
17.          "my_stop": {
18.            "type": "stop",
19.            "stopwords": [
20.              "over",
21.              "dog"
22.            ]
23.          }
24.        }
25.      }
26.    },
27.    "mappings": {
28.      "properties": {
29.        "text": {
30.          "type": "text",
31.          "analyzer": "my_analyzer"
32.        }
33.      }
34.    }
35.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

由於 filter 可以是多個,而且它的執行順序是從上而下執行的。在上面,它先執行 my_stop,然後是 stop 過濾器。我們使用同樣的命令來進行測試:

1.  GET stop_example/_analyze
2.  {
3.    "analyzer": "my_analyzer",
4.    "text": ["a quick fox jumps over the lazy dog"]
5.  }


複製代碼

這次顯示的結果為:

1.  {
2.    "tokens": [3.      {4.        "token": "quick",5.        "start_offset": 2,6.        "end_offset": 7,7.        "type": "<ALPHANUM>",8.        "position": 19.      },10.      {11.        "token": "fox",12.        "start_offset": 8,13.        "end_offset": 11,14.        "type": "<ALPHANUM>",15.        "position": 216.      },17.      {18.        "token": "jumps",19.        "start_offset": 12,20.        "end_offset": 17,21.        "type": "<ALPHANUM>",22.        "position": 323.      },24.      {25.        "token": "lazy",26.        "start_offset": 27,27.        "end_offset": 31,28.        "type": "<ALPHANUM>",29.        "position": 630.      }31.    ]
32.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

顯然,a 和 the 不見了。

Predicate script token filter

刪除與提供的謂詞腳本不匹配的標記。 該過濾器僅支持內聯 Painless 腳本。 在分詞謂詞上下文中評估腳本。

示例:

以下 analyze API 請求使用 predicate_token_filter 過濾器僅輸出c從 the fox jumps the lazy dog 長於三個字符的 token。

1.  GET /_analyze
2.  {
3.    "tokenizer": "whitespace",
4.    "filter": [
5.      {
6.        "type": "predicate_token_filter",
7.        "script": {
8.          "source": """
9.            token.term.length() > 3
10.          """
11.        }
12.      }
13.    ],
14.    "text": "the fox jumps the lazy dog"
15.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

上面的命令返回的結果為:

1.  {
2.    "tokens": [3.      {4.        "token": "jumps",5.        "start_offset": 8,6.        "end_offset": 13,7.        "type": "word",8.        "position": 29.      },10.      {11.        "token": "lazy",12.        "start_offset": 18,13.        "end_offset": 22,14.        "type": "word",15.        "position": 416.      }17.    ]
18.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

事實上,我們可以使用這個過濾器來實現上面描述的 length 過濾器。比如:

1.  PUT predicate_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "tokenizer": "ik_smart",
8.            "filter": [
9.              "my_predicate"
10.            ]
11.          }
12.        },
13.        "filter": {
14.          "my_predicate": {
15.            "type": "predicate_token_filter",
16.            "script": {
17.              "source": """
18.                token.term.length() > 1
19.             """
20.            }
21.          }
22.        }
23.      }
24.    },
25.    "mappings": {
26.      "properties": {
27.        "text": {
28.          "type": "text",
29.          "analyzer": "my_analyzer"
30.        }
31.      }
32.    }
33.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

我們使用如下的命令來進行測試:

1.  GET predicate_example/_analyze
2.  {
3.    "analyzer": "my_analyzer",
4.    "text": ["我愛北京天安門"]
5.  }


複製代碼
1.  {
2.    "tokens": [3.      {4.        "token": "北京",5.        "start_offset": 2,6.        "end_offset": 4,7.        "type": "CN_WORD",8.        "position": 29.      },10.      {11.        "token": "天安門",12.        "start_offset": 4,13.        "end_offset": 7,14.        "type": "CN_WORD",15.        "position": 316.      }17.    ]
18.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

顯然只有長度是大於 1 的 token 才會顯示。在實際的使用中,腳本的執行速度較慢一些。如果你的腳本的長度或計算的時間較長,我們需要注意使用。

自定義並添加到分詞器

要自定義 predicate_token_filter 過濾器,複製它以創建新的自定義 token 過濾器的基礎。 你可以使用其可配置參數修改過濾器。

以下創建索引 API 請求使用自定義 predicate_token_filter 過濾器 my_script_filter 配置新的自定義分詞器。

my_script_filter 過濾器刪除除 ALPHANUM 之外的任何類型的 token。

1.  PUT /my-index-000001
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "my_analyzer": {
7.            "tokenizer": "standard",
8.            "filter": [
9.              "my_script_filter"
10.            ]
11.          }
12.        },
13.        "filter": {
14.          "my_script_filter": {
15.            "type": "predicate_token_filter",
16.            "script": {
17.              "source": """
18.                token.type.contains("ALPHANUM")
19.              """
20.            }
21.          }
22.        }
23.      }
24.    }
25.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

Trim token filter

從流中的每個 token 中刪除前導和尾隨空格。 雖然這可以更改 token 的長度,但 trim 過濾器不會更改 token 的偏移量。 trim 過濾器使用 Lucene 的TrimFilter。

例子:

要查看 trim 過濾器的工作原理,你首先需要生成一個包含空格的 token。以下 analyze API 請求使用keywordtokenizer 為“ fox ”生成 token。

1.  GET _analyze
2.  {
3.    "tokenizer" : "keyword",
4.    "text" : " fox "
5.  }


複製代碼

API 返回以下響應。 請注意,“ fox ” token 包含原始文本的空格。 請注意,儘管更改了 token 的長度,但 start_offset 和 end_offset 保持不變。

1.  {
2.    "tokens": [
3.      {
4.        "token": " fox ",
5.        "start_offset": 0,
6.        "end_offset": 5,
7.        "type": "word",
8.        "position": 0
9.      }
10.    ]
11.  }


複製代碼

要刪除空格,請將 trim 過濾器添加到之前的 analyze API 請求。

1.  GET _analyze
2.  {
3.    "tokenizer" : "keyword",
4.    "filter" : ["trim"],
5.    "text" : " fox "
6.  }


複製代碼

API 返回以下響應。 返回的 fox token 不包含任何前導或尾隨空格。

1.  {
2.    "tokens": [
3.      {
4.        "token": "fox",
5.        "start_offset": 0,
6.        "end_offset": 5,
7.        "type": "word",
8.        "position": 0
9.      }
10.    ]
11.  }


複製代碼

以下創建索引 API 請求使用 trim 過濾器來配置新的自定義分詞器。

1.  PUT trim_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "keyword_trim": {
7.            "tokenizer": "keyword",
8.            "filter": [ "trim" ]
9.          }
10.        }
11.      }
12.    }
13.  }


複製代碼

Synonym token filter

這是一個同義詞過濾器。你可以閲讀我之前的文章 “ Elasticsearch:使用同義詞 synonyms 來提高搜索效率 ”。

Truncate token filter

Truncate 超過指定字符限制的標記。 此限制默認為 10,但可以使用長度參數進行自定義。例如,你可以使用 truncate 過濾器將所有 token 縮短為 3 個字符或更少,將 jumping fox 更改為 jum fox。此過濾器使用 Lucene 的TruncateTokenFilter。

例子:

以下 analyze API 請求使用 truncate 過濾器來縮短 quinquennial extravaganza carried on 中超過 10 個字符的標記:

1.  GET _analyze
2.  {
3.    "tokenizer" : "whitespace",
4.    "filter" : ["truncate"],
5.    "text" : "the quinquennial extravaganza carried on"
6.  }


複製代碼

上面的命令返回:

1.  {
2.    "tokens": [3.      {4.        "token": "the",5.        "start_offset": 0,6.        "end_offset": 3,7.        "type": "word",8.        "position": 09.      },10.      {11.        "token": "quinquenni",12.        "start_offset": 4,13.        "end_offset": 16,14.        "type": "word",15.        "position": 116.      },17.      {18.        "token": "extravagan",19.        "start_offset": 17,20.        "end_offset": 29,21.        "type": "word",22.        "position": 223.      },24.      {25.        "token": "carried",26.        "start_offset": 30,27.        "end_offset": 37,28.        "type": "word",29.        "position": 330.      },31.      {32.        "token": "on",33.        "start_offset": 38,34.        "end_offset": 40,35.        "type": "word",36.        "position": 437.      }38.    ]
39.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

我們可以發現 token 的長度不超過 10。10 是默認的值。

添加到分詞儀

以下創建索引 API 請求使用截斷過濾器來配置新的自定義分詞器。

1.  PUT custom_truncate_example
2.  {
3.    "settings" : {
4.      "analysis" : {
5.        "analyzer" : {
6.          "standard_truncate" : {
7.          "tokenizer" : "standard",
8.          "filter" : ["truncate"]
9.          }
10.        }
11.      }
12.    }
13.  }


複製代碼

我們甚至可以針對 truncate 過濾器進行定製:

1.  PUT 5_char_words_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "lowercase_5_char": {
7.            "tokenizer": "lowercase",
8.            "filter": [ "5_char_trunc" ]
9.          }
10.        },
11.        "filter": {
12.          "5_char_trunc": {
13.            "type": "truncate",
14.            "length": 5
15.          }
16.        }
17.      }
18.    }
19.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

通過對 length 參數的定製,我們可以限制 token 的長度最多不超過 5,而不是默認的 10。

Limit token count token filter

限制輸出 token 的數量。 限制過濾器通常用於根據 token 計數限制文檔字段值的大小。默認情況下,限制過濾器僅保留流中的第一個 token。 例如,過濾器可以將 token 流 [one、two、three] 更改為 [one]。此過濾器使用 Lucene 的 LimitTokenCountFilter

示例:

1.  GET _analyze
2.  {
3.    "tokenizer": "standard",
4.      "filter": [
5.      {
6.        "type": "limit",
7.        "max_token_count": 2
8.      }
9.    ],
10.    "text": "quick fox jumps over lazy dog"
11.  }


複製代碼

上面的輸出為:

1.  {
2.    "tokens": [3.      {4.        "token": "quick",5.        "start_offset": 0,6.        "end_offset": 5,7.        "type": "<ALPHANUM>",8.        "position": 09.      },10.      {11.        "token": "fox",12.        "start_offset": 6,13.        "end_offset": 9,14.        "type": "<ALPHANUM>",15.        "position": 116.      }17.    ]
18.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

也就是取前面的兩個 token。

添加到分詞器

以下創建索引 API 請求使用 limit 過濾器來配置新的自定義分詞器。

1.  PUT limit_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "standard_one_token_limit": {
7.            "tokenizer": "standard",
8.            "filter": [ "limit" ]
9.          }
10.        }
11.      }
12.    }
13.  }


複製代碼

我們也可以定製 limit 過濾器:

1.  PUT custom_limit_example
2.  {
3.    "settings": {
4.      "analysis": {
5.        "analyzer": {
6.          "whitespace_five_token_limit": {
7.            "tokenizer": "whitespace",
8.            "filter": [ "five_token_limit" ]
9.          }
10.        },
11.        "filter": {
12.          "five_token_limit": {
13.            "type": "limit",
14.            "max_token_count": 5
15.          }
16.        }
17.      }
18.    }
19.  }

`![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
複製代碼

上面的 max_token_count 在默認的情況下為 1。我們可以通過對它的定製來限制最多的 token 輸出。

Shingle token filter

請詳細閲讀之前的文章 “ Elasticsearch: Ngrams, edge ngrams, and shingles ”。

中文相關的 filter

請詳細閲讀我之前的文章:

好了,今天的分享就到這裏。更多的過濾器,請參閲官方文檔。

參考:

【1】 Token filter reference | Elasticsearch Guide [8.4] | Elastic