在今天的文章中,我们来进一步了解 analyzer。 analyzer 执行将输入字符流分解为token的过程,它一般发生在两个场合:
- 在 indexing 的时候,也即在建立索引的时候
- 在 searching 的时候,也即在搜索时,分析需要搜索的词语
什么是 analysis?
分析是 Elasticsearch 在文档发送之前对文档正文执行的过程,以添加到反向索引中(inverted index)。 在将文档添加到索引之前,Elasticsearch 会为每个分析的字段执行许多步骤:
- Character filtering (字符过滤器): 使用字符过滤器转换字符
- Breaking text into tokens (把文字转化为标记): 将文本分成一组一个或多个标记
- Token filtering:使用标记过滤器转换每个标记
- Token indexing:把这些标记存于索引中
接下来我们将更详细地讨论每个步骤,但首先让我们看一下图表中总结的整个过程。 下图显示了 “share your experience with NoSql & big data technologies" 为分析的标记:share, your, experience, with, nosql, big, data,tools 及 technologies。
上面所展示的是一个由 character 过滤器,标准的 tokenizer 及 Token filter 组成的定制 analyzer。上面的这个图非常好,它很简洁地描述一个 analyzer 的基本组成部分,以及每个部分所需要表述的东西。
经过 analyzer 处理过后的文档最终以 Inverted Index 的形式保存于 Elasticsearch 中:
每当一个文档被 ingest 节点纳入,它需要经历如下的步骤,才能最终把文档写入到 Elasticsearch的 数据库中:
上面中间的那部分就叫做 analyzer,即分析器。它有三个部分组成:Char Filters, Tokenizer 及 Token Filter。它们的作用分别如下:
- Char Filter: 字符过滤器的工作是执行清除任务,例如剥离 HTML 标记,还有上面的把 “&” 转换为 “and” 字符串
- Tokenizer: 下一步是将文本拆分为称为标记的术语。 这是由 tokenizer 完成的。 可以基于任何规则(例如空格)来完成拆分。 有关 tokenizer 的更多详细信息,请访问以下URL:www.elastic.co/guide/en/el…
- Token filter: 一旦创建了 token,它们就会被传递给 token filter,这些过滤器会对 token 进行规范化。 Token filter 可以更改 token,删除术语或向 token 添加术语。
一个 analyzer 有且只有一个 tokenizer,有0个或一个以上的 char filter 及 token filter。
Elasticsearch 已经提供了比较丰富的开箱即用 analyzer。我们可以自己创建自己的 token analyzer,甚至可以利用已经有的 char filter,tokenizer 及 token filter 来重新组合成一个新的 analyzer,并可以对文档中的每一个字段分别定义自己的 analyzer。
在默认的情况下,standard analyzer 是 Elasticsearch 的缺省分析器:
- 没有 Char Filter
- 使用 standard tokonizer
- 把字符串变为小写,同时有选择地删除一些 stop words 等。默认的情况下 stop words 为 none,也即不过滤任何 stop words。
关于停用词
在信息检索中,停用词 是为节省存储空间和提高搜索效率,处理文本时自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词)。
停用词大致分为两类。一类是语言中的功能词,这些词极其普遍而无实际含义,比如“the”、“is“、“which“、“on”等。另一类是词汇词,比如'want'等,这些词应用广泛,但搜索引擎无法保证能够给出真正相关的搜索结果,难以缩小搜索范围,还会降低搜索效率。
实践中,通常把这些词从问题中过滤,从而节省索引的存储空间、提高搜索性能。
但是在实际语言环境中,停用词有时也有用的。比如,莎士比亚的名句:“To be or not to be.”所有的词都是停用词。特别当停用词和通配符(*)同时使用的时候,问题就来了:“the”、“is“、“on”还是停用词吗?
实际运用中,没有一个解决方案是100%完美的。很多时候需要我们根据实际用例作相应的调整和折中,来达到期望的结果。在这个时候,需要用80/20原则,把目标专注在提高用户体验上。
如何启动停用词
在默认的情况下,standard 分词器中的 stopwords filter 是禁用的。我们可以使用如下的方法来进行启动:
PUT my_index_with_stopwords
{
"settings": {
"analysis": {
"analyzer": {
"standard_with_stopwords":{
"type":"standard",
"stopwords":"_english_"
}
}
}
}
}
在上面,我们通过设置 stopwords 的方法启动了 stop filter。我们可以使用如下的测试命令来测试一下:
POST my_index_with_stopwords/_analyze
{
"text": "This is a wonderful experience and I think it is the best solution",
"analyzer": "standard_with_stopwords"
}
上面的命令的结果为:
{
"tokens": [
{
"token": "wonderful",
"start_offset": 10,
"end_offset": 19,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "experience",
"start_offset": 20,
"end_offset": 30,
"type": "<ALPHANUM>",
"position": 4
},
{
"token": "i",
"start_offset": 35,
"end_offset": 36,
"type": "<ALPHANUM>",
"position": 6
},
{
"token": "think",
"start_offset": 37,
"end_offset": 42,
"type": "<ALPHANUM>",
"position": 7
},
{
"token": "best",
"start_offset": 53,
"end_offset": 57,
"type": "<ALPHANUM>",
"position": 11
},
{
"token": "solution",
"start_offset": 58,
"end_offset": 66,
"type": "<ALPHANUM>",
"position": 12
}
]
}
很显然,this is the 等这些常见的词不见了。