ElasticSearch(五) 倒排索引与分词


title: ElasticSearch(五) 倒排索引与分词
tags: ElasticSearch
author: Clown95


倒排索引与分词

倒排索引

Elasticsearch 使用一种称为倒排索引的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。

为了更好的理解倒排索引,我们先说下《高性能MySql》这本书的目录和索引。
首先看下书的目录,它能够很方便的定位我们想要了解的知识点。

但是如果我们想要查询auto-increment keys的内容,目录上并没有出现这些具体的关键字,如果我们知道它所在的知识点也能快速的查询到,但是如果我们不知道它所在的知识点,那么我们只能一页一页的翻书来查找这个关键字,这样的效率无疑是很低。

但是如果我们有一个像下面这样的索引,我们就能很快的定位到具体的页码。

书与搜索引擎类似,我们可以抽象为:

  • 目录页对应正排索引
  • 索引页对应倒排索引

正排与倒排索引介绍

正排索引,是通过文档ID到文档内容、单词(文档的分词)

倒排索引,是通过单词获得文档ID,这些单词就是文档内容进行的分词。

对比两张图,我们可以看到 搜索引擎 这个单词,在1,3文档,那么我们是如何查询包含搜索引擎的文档的?

  1. 通过倒排索引获得搜索引擎 对应的文档ID 有 1 和 3
  2. 通过正排索引查询 1 和 3 的完整内容
  3. 返回用户最终结果

倒排索引的组成

倒排索弓|是搜索引l擎的核心,主要包含两部分:

  • 单词词典( Term Dictionary )
    单词词典是倒排索引的重要组成部分, 他记录了所有文档的单词,所以他一般都比较大 。还会记录单词到倒排列表的关联信息。

  • 倒排列表( Posting List )
    倒排列表 记录了单词对应的文档集合,由倒排索引项( Posting )组成。
    倒排索引项主要包含如下信息:

    • 文档Id ,用于获取原始信息
    • 单词频率( TF, Term Frequency) , 记录该单词在该文档中的出现次数,用于后续相关性算分
    • 位置( Position) ,记录单词在文档中的分词位置(多个) ,用于做词语搜索
    • 偏移( Offset ) ,记录单词在文档的开始和结束位置,用于做高亮显示

分词

分词是指将文本转换成一系列单词( term or token )的过程,也可以叫做文本分析。

比如说: elasticsearch是最流行的搜索引擎 这句话,我们可以分为elasticsearch流行搜索引擎, 当然这个结果仅作为参考,具体的结果取决于你选用什么样的分词器。

分词器是es中专门处理分词的组件,英文为Analyzer ,它的组成如下:

  • Character Filter -针对原始文本进行处理,比如去除html特殊标记符,特殊符号转换等
  • Tokenizer - 将原始文本按照一定规则切分为单词
  • Token Filters - 针对tokenizer处理的单词就行再加工,比如转小写、删除或新增等处理

Analyze API

es提供了一个测试分词的api接口,方便验证分词效果, 断点是使用_ analyze

  1. 可以直接指定analyzer进行测试

    POST _analyze
    {
      "analyzer": "standard",
      "text": "hello world"
    }
    

    analyzer 是我们选择的分词器 ,text 是我们要处理的内容。

    我们来看下响应信息

    {
      "tokens": [
    	{
    	  "token": "hello",
    	  "start_offset": 0,
    	  "end_offset": 5,
    	  "type": "<ALPHANUM>",
    	  "position": 0
    	},
    	{
    	  "token": "world",
    	  "start_offset": 6,
    	  "end_offset": 11,
    	  "type": "<ALPHANUM>",
    	  "position": 1
    	}
      ]
    }
    
    • token - 分词结果
    • start_offset - 起始偏移
    • end_offset - 结束偏移
    • position - 分词位置
  2. 可以直接指定索引中的字段进行测试

    这当我查询结果不是我们预期结果的时候,我们就可以使用它查看字段分词方式。

    POST movies/_analyze
    {
      "field": "title",
      "text": "监狱风云"
    }
    

    通过结果我们可以看到 es对中文分词默认是拆分为单个汉字,这就是我们搜索剧情的信息却能返回爱情的信息。

  3. 可以自定义分词器进行测试

    我们还可以自定义分词器, 自己组合Character FilterTokenizerToken Filters

    POST  _analyze
    {
      "tokenizer": "standard",
      "filter": ["lowercase"],
      "text": "Hello Wordl"
    }
    
  • tokenizer将原始文本按照一定规则切分为单词( term or token ):

    • standard 按照单词进行分割
    • letter按照非字符类进行分割
    • whitespace按照空格进行分割
    • UAX URL Email按照standard分割,但不会分割邮箱和url
    • NGram和Edge NGram连词分割
    • Path Hierarchy 按照文件路径进行切割
  • Token Filters 对于tokenizer输出的单词( term )进行增加、删除、修改等操作

    • lowercase将所有term转换为小写
    • stop删除stop words
    • NGram和Edge NGram连词分割
    • Synonym添加近义词的term

内置分词器的使用

es为我们提供了几个内置的分词器,下面我们列出了最重要的几个分析器:

  • standard 分词器:(默认的)他会将词汇单元转换成小写形式,并去除停用词和标点符号,支持中文采用的方法为单字切分
POST _analyze
{
  "analyzer": "standard",
  "text": "I Love You Chian! 我爱你中国!"
}
  • simple 分词器:首先会通过非字母字符来分割文本信息,然后将词汇单元统一为小写形式。该分析器会去掉数字类型的字符。
POST _analyze
{
  "analyzer": "simple",
  "text": "I123love456golang"
}
  • Whitespace 分词器:仅仅是去除空格,对字符没有lowcase化,不支持中文;并且不对生成的词汇单元进行其他的标准化处理。
POST _analyze
{
  "analyzer": "whitespace",
  "text": "Chian is Num one"
}
  • Pattern 分词器 : 通过正则表达式自定义分隔符,默认的规则是\W+,即非字词的符号作为分隔符。
POST _analyze
{
  "analyzer": "pattern",
  "text": "good-good^study*day*day%up"
} 
  • language 分词器:特定语言的分词器,大概有30多种,例如:arabic, armenian, basque, bengali, brazilian, bulgarian,catalan, cjk, czech, danish, dutch, english等,但是不支持中文。

中文分词

英文的分词比较好分主要是以空格为分割标准,但是中文就不一样了,中国的语言博大精深,相同的一句话根据语境的不同,可以解读出不同的意思,所以很难有一个明确的分词标准。

例如这句最经典的语句下雨天留客天留我不留,可以有五种意思:

  • 下雨,天留客;天留,我不留。
  • 下雨天,留客?天留,我不留。
  • 下雨天,留客天,留我不留?
  • 下雨天,留客天,留?我不留!
  • 下雨天,留客天,留我不?留。

我们常用的中文分词系统有:

分词会在如下两个时机使用:

  • 创建或更新文档时( Index Time) :会对相应的文档进行分词处理。索引时分词是通过配置Index Mapping中每个字段的analyzer属性实现的,不指定分词时,使用默认standard。

  • 查询时( Search Time ) ,:会对查询语句进行分词。查询的时候可以通过analyzer指定分词器,还有就是设置 index mapping的时候设置 search_analyzer实现搜索分词。

我们使用IK分词器对中文进行分词看看

POST _analyze
{
  "analyzer": "ik_smart",
  "text": "我爱你中国"
}

响应内容:

{
  "tokens": [
    {
      "token": "我爱你",
      "start_offset": 0,
      "end_offset": 3,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "中国",
      "start_offset": 3,
      "end_offset": 5,
      "type": "CN_WORD",
      "position": 1
    }
  ]
}

我们可以看到IK很聪明的为我们分词了,不像standard分词器一个字一个字的分词。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值