Press "Enter" to skip to content

Elasticsearch:分词器中的 token 过滤器使用示例

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

分词器在 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 ]

 

    1. 删除 very token 的重复实例。

 

    1. 将 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

 

请详细阅读我之前的文章:

 

Elasticsearch:IK 中文分词器

 

Elasticsearch:Pinyin 分词器

 

Elasticsearch:简体繁体转换分词器 – STConvert analysis

 

好了,今天的分享就到这里。更多的过滤器,请参阅官方文档。

 

参考:

 

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

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注