分词和分词器(analysis and analyzers)

分词过程如下:

首先,把一段文字标记为适合在inverted index中使用的单个的terms。

然后,把terms转化为标准的格式,以方便搜索或回召。

这个工作由分词器执行,分词器就是整合了三个功能的封装:

1:字符过滤器(Character filters),首先,string是有序的通过字符过滤器。字符过滤器的工作就是在string被标记化之前对string进行整理。字符过滤器可以用来去除HTML标签,或者是把“&”转换为“and"。

2:标记生成器(Tokenizer),接下来,string就会被Tokenizer标记成单个的terms。一个简单的Tokenizer可以是根据string中的空格或标点把string分割为terms。

3:标记过滤器(Token filters),最后,每个term都要有序的通过token filters,这里可以修改terms(比如把大些转换为小写),移除terms(比如结束词像”a","and","the"),或者添加terms(比如近似词像“jump”和“leap”)。

ES提供了很多开箱即用的character filter,tokenizers和token filters。这些能联合创建自定义的用于不同目的分词器。我们将会在Custom analyzers中消息讨论自定义的分词器。

 

built-in analyzers

ES已经提供了一定数量的直接可以使用的打包好的分词器。下面列举出一些重要的,然后解释他们不同的表现行为,我们要用下面的语句作为演示例子:

"Set the shape to semi-transparent by calling set_trans(5)"

标准分词器(Standard analyzer),这个分词器是ES默认使用的分词器,一般情况下,这个分词器是一个最好的选择,他是用语任何的语言。这个分词器使用单词的边界进行分割text,就行Unicode Consortium中定义的一样。并且还移除很多的符号,最后把所有的term转换为小写字符:

set, the, shape, to, semi, transparent, by, calling, set_trans, 5

简单的分词器(Simple analyzer),这个分词器通过任何不是字母的符号分割字符串,然后把term转换为小写:

set, the, shape, to, semi, transparent, by, calling, set, trans

空格分词器(Whitespace analyzer),这个分词器通过字符串中的空格进行分割,然后把term转化为小写:

Set, the, shape, to, semi-transparent, by, calling, set_trans(5)

语言分词器(Language analyzers),指定语言的分词器支持很多的语言,他们能把指定语言的peculiarties转换到账户中。例如,english analyzer携带了英文停顿符的集合,还有一些常用的单词如and和the这些没有实际意义的将会被移除,他能stem英文就是因为他知道英文语法的规则。使用英文分词器将会得到如下结果:

set, shape, semi, transpar, call, set_tran, 5

要注意的是"transparent","calling"和“set_trans”都已经stemmed到各自的原生形式(root form)。

 

when analyzers are used

当我们对一个document执行index操作的时候,整个document的text就会被分词到terms中,这些terms被用来创建inverted index。然而当我们对full text(_all)进行搜索时候,我们需要把请求的string通过分词器分词,确保我们搜索的terms和index存放的形式是一致的。

全文检索,我们会在稍后进行讨论,明白每个field是怎么定义的,才能做正确的事情:

1:当你对full text字段查询时,查询会申请相同的分词器对查询字符串进行分词,生成可供搜索的正确的terms的集合。

2:当你对exact value字段进行查询时,这个查询是不对请求的字符串进行分词的,而是搜索你指定的确切的值。

现在你已经明白了为什么我们在中展示的查询返回的结果了吧:

1:date字段中包含了确切的值:“2014-09-15”

2:_all字段是full text字段,因此分词过程就把这个“2014-09-15”转换为三个term:“2014”,“09”,“15”。

当我们对_all字段查询2014时候,就会匹配所有的tweets,因为所有的tweets中的full text都包含了2014:

GET /_search?q=2014              # 12 results

当我们对_all字段查询2014-09-15的时候,首先把要查询的string进行了分词,产生了一个匹配任何full text包含了2014,09或者15的查询,这个也是匹配了12个tweets,因为所有的tweets都包含了2014:

GET /_search?q=2014-09-15        # 12 results !

当我们对date字段查询2014-09-15的时候,就会查找确切的date,然后找到一个tweet:

GET /_search?q=date:2014-09-15   # 1  result

当我们对date字段查询2014的时候,就会找不到任何的document,因为没有一个document的date字段确切的包含2014:

GET /_search?q=date:2014         # 0  results !

 

testing analyzers

特别指出的是,如果你是一个ES的新学者,理解在index中实际是怎么被标记和存储的是有点困难的。为了更好的理解接下来的学习,你可以使用analyze API观察text是怎么被分词的。在请求参数中指定在查询的时候使用了分词器的名称,在请求体中指定要分词的text:

GET /_analyze?analyzer=standard
Text to analyze

返回结果中的每个元素都代表了一个单独的term:

{
   
"tokens":[
     
{
         
"token":        "text",
         
"start_offset":0,
         
"end_offset":   4,
         
"type":         "<ALPHANUM>",
         
"position":     1
     
},
     
{
         
"token":        "to",
         
"start_offset":5,
         
"end_offset":   7,
         
"type":         "<ALPHANUM>",
         
"position":     2
     
},
     
{
         
"token":        "analyze",
         
"start_offset":8,
         
"end_offset":   15,
         
"type":         "<ALPHANUM>",
         
"position":     3
     
}
   
]
}

token就是真实的存储在index中的term,position表示其中的term出现在原文的顺序。start_offset和end_offset表明了原始单词在原始字符串占据的位置,

analyzer API是了解在ES中index发生了是什么的一个很好的工具,在以后我们还会更多的了解他。

 

specifying analyzers

当ES检测到在你的document中一个新的string field的时候,就会自动把新的string配置为full text的string field,并且使用standard analyzer进行分词。

然而你不想总是这样,也许你想使用一个不同的符合你的语言的分词器,有时你就是想让一个string成为一个string filed作为一个确切的数值进行存储而不是用analyzer,就像存储一个用户ID或一个状态标记或一个tag。

为了达到这个目的,我们可以通过指定的mapping手动的配置这些field。

 

原文:http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/analysis-intro.html

posted @ 2014-06-03 15:45  QQ1350995917  Views(759)  Comments(0)    收藏  举报