ElasticSearch全文检索的流程分析

全文检索的流程分析

什么是索引

有人可能会说,对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?

这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。

这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引

这种说法比较抽象,举几个例子就很容易明白,比如字典,字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和 部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以 一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到 我们的非结构化数据——也即对字的解释

​​​​​​​​​​​​​​流程总览

搜索基本的流程实现:

 

全文检索的流程分为两大流程:索引创建、搜索索引

  • 索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
  • 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。

想搞清楚全文检索,必须要搞清楚下面三个问题:

1. 索引库里面究竟存些什么?(Index)

2. 如何创建索引?(Indexing)

3. 如何对索引进行搜索?(Search)

​​​​​​​原始内容

原始内容是指要索引和搜索的内容

原始内容包括互联网上的网页、数据库中的数据、磁盘上的文件等。

​​​​​​​获得文档

也就是采集数据,从互联网上、数据库、文件系统中等获取需要搜索的原始信息,这个过程就是信息采集。

采集数据的目的是为了将原始内容存储到Document对象中

如何采集数据?

  1. 对于互联网上网页,可以使用工具将网页抓取到本地生成html文件。
  2. 数据库中的数据,可以直接连接数据库读取表中的数据。
  3. 文件系统中的某个文件,可以通过I/O操作读取文件的内容。

Internet上采集信息的软件通常称为爬虫或蜘蛛,也称为网络机器人,爬虫访问互联网上的每一个网页,将获取到的网页内容存储起来。

​​​​​​​创建文档对象

创建文档的目的是统一数据格式(Document),方便文档分析。

 

说明:

  1. 一个Document文档中包括多个域(Field),域(Field)中存储内容。

这里我们可以将数据库中一条记录当成一个Document,一列当成一个Field 

​​​​​​​分析文档(重点)

分析文档主要是对Field域进行分析,分析文档的目的是为了索引。

说明:分析文档主要通过分词组件(Tokenizer语言处理组件(Linguistic Processor完成

      1. 分词组件

分词组件工作流程(此过程称之为Tokenize

  1. Field域中的内容进行分词(不同语言有不同的分词规则)
  2. 去除标点符号。
  3. 去除停用词(stop word)。

经过分词(Tokenize)之后得到的结果成为词元(Token

所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建索引时,这种词会被去掉而减少索引的大小。

英语中停词(Stop word)如:“the”,“a”“this”等。

对于每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合

示例(Document1Field域和Document2Field域是同名的)

  • Document1Field域:
 Students should be allowed to go out with their   friends, but not allowed to drink beer.   
  • Document2Field域:
 My friend Jerry went to school to see his students but   found them drunk which is not allowed. 
  • 在我们的例子中,便得到以下词元(Token)
 “Students”“allowed”“go”“their”“friends”“allowed”“drink”“beer”“My”“friend”“Jerry”“went”“school”“see”“his”“students”“found”“them”“drunk”“allowed” 

将得到的词元(Token)传给语言处理组件(Linguistic Processor)

      1. 语言处理组件

语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处理。

对于英语,语言处理组件(Linguistic Processor)一般做以下几点:

  1. 变为小写(Lowercase)
  2. 将单词缩减为词根形式,如“cars”“car”等。这种操作称为:stemming
  3. 将单词转变为词根形式,如“drove”“drive”等。这种操作称为:lemmatization

语言处理组件(linguistic processor)的结果称为(Term)Term是索引库的最小单位。

  • 在我们的例子中,经过语言处理,得到的词(Term)如下:
 “student”“allow”“go”“their”“friend”“allow”“drink”“beer”“my”“friend”“jerry”“go”“school”“see”“his”“student”“find”“them”“drink”“allow”

也正是因为有语言处理的步骤,才能使搜索drove,而drive也能被搜索出来

索引文档

  1. 索引库创建

索引的目的是为了搜索

 

说明:将得到的词(Term)传给索引组件(Indexer),索引组件(Indexer)主要做以下几件事情:

      1. 创建Term字典

在我们的例子中字典如下:

Term

Document ID

Student

1

Allow

1

Go

1

Their

1

Friend

1

Allow

1

Drink

1

Beer

1

My

2

Friend

2

Jerry

2

Go

2

School

2

See

2

His

2

Student

2

Find

2

Them

2

Drink

2

Allow

2

      1. 排序Term字典

对字典按字母顺序进行排序

Term

Document ID

Allow

1

Allow

1

Allow

2

Beer

1

Drink

1

Drink

2

Find

2

Friend

1

Friend

2

Go

1

Go

2

His

2

Jerry

2

My

2

School

2

See

2

Student

1

Student

2

Their

1

Them

2

      1. 合并Term字典

合并相同的词(Term)成为文档倒排(Posting List)链表

在此表中,有几个定义:

  • Document Frequency 即文档频次,表示总共有多少文件包含此词(Term)
  • Frequency 即词频率,表示此文件中包含了几个此词(Term)

到此为止,索引已经创建好了。

最终的索引结构是一种倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大。

倒排索引结构是根据内容(词汇)找文档,如下图:

 

​​​​​​​创建索引流程

分词及检索的详细的流程:

一次索引,多次使用。

搜索索引流程

  1. 1:查询语句

 

      1. 2:执行搜索

第一步:对查询语句进行词法分析、语法分析及语言处理。

1、词法分析

如上述例子中,经过词法分析,得到单词有lucenelearnedhadoop, 关键字有AND, NOT

注意:关键字必须大写,否则就作为普通单词处理。

 

2、语法分析

如果发现查询语句不满足语法规则,则会报错。如lucene NOT AND learned,则会出错。

如上述例子,lucene AND learned NOT hadoop形成的语法树如下:

 

3、语言处理

learned变成learn等。

经过第二步,我们得到一棵经过语言处理的语法树。

 

第二步:搜索索引,得到符号语法树的文档。

1 首先,在反向索引表中,分别找出包含lucenelearnhadoop的文档链表。

2 其次,对包含lucenelearn的链表进行合并操作,得到既包含lucene又包含learn的文档链表。

 

 

3 然后,将此链表与hadoop的文档链表进行差操作,去除包含hadoop的文档,从而得到既包含lucene又包含learn而且不包含hadoop的文档链表。

 

4 此文档链表就是我们要找的文档。

 

第三步:根据得到的文档和查询语句的相关性,对结果进行排序。

       相关度自然打分(权重越高分越高):

              tf越高、权重越高

              df越高、权重越低

       人为影响分数:

              设置Boost值(加权值

​​​​​​​Lucene相关度排序

  1. 什么是相关度排序

相关度排序是查询结果按照与查询关键字的相关性进行排序,越相关的越靠前。比如搜索“Lucene”关键字,与该关键字最相关的文章应该排在前边。

      1. 相关度打分

Lucene对查询关键字和索引文档的相关度进行打分,得分高的就排在前边。

如何打分呢?Lucene是在用户进行检索时实时根据搜索的关键字计算出来的,分两步:

  1. 计算出词(Term)的权重
  2. 根据词的权重值,计算文档相关度得分。

什么是词的权重?

通过索引部分的学习,明确索引的最小单位是一个Term(索引词典中的一个词)。搜索也是从索引域中查询Term,再根据Term找到文档。Term对文档的重要性称为权重,影响Term权重有两个因素:

  • Term Frequency (tf)

指此Term在此文档中出现了多少次。tf 越大说明越重要

(Term)在文档中出现的次数越多,说明此词(Term)对该文档越重要,如“Lucene”这个词,在文档中出现的次数很多,说明该文档主要就是讲Lucene技术的。

  • Document Frequency (df)

指有多少文档包含此Termdf 越大说明越不重要

比如,在一篇英语文档中,this出现的次数更多,就说明越重要吗?不是的,有越多的文档包含此词(Term), 说明此词(Term)太普通,不足以区分这些文档,因而重要性越低。

      1. 设置boost值影响相关度排序

boost是一个加权值(默认加权值为1.0f),它可以影响权重的计算。在索引时对某个文档中的field设置加权值,设置越高,在搜索时匹配到这个文档就可能排在前边。

​​​​​​​LuceneField

  1. Field属性

Field是文档中的域,包括Field名和Field值两部分,一个文档可以包括多个FieldDocument只是Field的一个承载体,Field值即为要索引的内容,也是要搜索的内容。

  • 是否分词(tokenized)
    • 是:作分词处理,即将Field值进行分词,分词的目的是为了索引。

比如:商品名称、商品描述等,这些内容用户要输入关键字搜索,由于搜索的内容格式大、内容多需要分词后将语汇单元建立索引

    • 否:不作分词处理

比如:商品id、订单号、身份证号等

  • 是否索引(indexed)
    • 是:进行索引。将Field分词后的词或整个Field值进行索引,存储到索引域,索引的目的是为了搜索。

比如:商品名称、商品描述分析后进行索引,订单号、身份证号不用分词但也要索引,这些将来都要作为查询条件。

    • 否:不索引。

比如:图片路径、文件路径等,不用作为查询条件的不用索引

  • 是否存储(stored)
    • 是:将Field值存储在文档域中,存储在文档域中的Field才可以从Document中获取。

比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。

    • 否:不存储Field

比如:商品描述,内容较大不用存储。如果要向用户展示商品描述可以从系统的关系数据库中获取。

      1. Field常用类型

下边列出了开发中常用 Filed类型,注意Field的属性,根据需求选择:

Field

数据类型

Analyzed 是否分词

Indexed 是否索引

Stored 是否存储

说明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

Y或N

这个Field用来构建一个字符串Field,但是不会进行分词,会将整个串存储在索引中,比如(订单号,身份证号等) 是否存储在文档中用Store.YES或Store.NO决定

LongField(FieldName, FieldValue,Store.YES)

Long型

Y

Y

Y或N

这个Field用来构建一个Long数字型Field,进行分词和索引,比如(价格) 是否存储在文档中用Store.YES或Store.NO决定

StoredField(FieldName, FieldValue)

重载方法,支持多种类型

N

N

Y

这个Field用来构建不同类型Field 不分析,不索引,但要Field存储在文档中

TextField(FieldName, FieldValue, Store.NO) 或 TextField(FieldName, reader)

字符串 或 流

Y

Y

Y或N

如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

      1. Field设计

Field域如何设计,取决于需求,比如搜索条件有哪些?显示结果有哪些?

  • 商品id

是否分词:不用分词,因为不会根据商品id来搜索商品

是否索引:不索引,因为不需要根据商品ID进行搜索

是否存储:要存储,因为查询结果页面需要使用id这个值。

  • 商品名称:

是否分词:要分词,因为要根据商品名称的关键词搜索。

是否索引:要索引。

是否存储:要存储。

  • 商品价格:

是否分词:要分词,lucene对数字型的值只要有搜索需求的都要分词和索引,因为lucene对数字型的内容要特殊分词处理,需要分词和索引。

是否索引:要索引

是否存储:要存储

  • 商品图片地址:

是否分词:不分词

是否索引:不索引

是否存储:要存储

  • 商品描述:

是否分词:要分词

是否索引:要索引

是否存储:因为商品描述内容量大,不在查询结果页面直接显示,不存储。

常见问题:

       不存储是指不在lucene的索引域中记录,目的是为了节省lucene的索引文件空间。

如果要在详情页面显示描述,解决方案:

lucene中取出商品的id,根据商品的id查询关系数据库(MySQL)中item表得到描述信息。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xianghan收藏册

极简精品作,一分也是一份鼓励哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值