赞
踩
扩展:信息检索技术
概念介绍
全文检索是一种将文件中所有文本与检索项匹配的文字资料检索方法。全文检索系统是按照全文检索理论建立起来的用于提供全文检索服务的软件系统。
全文检索主要对非结构化数据的数据检索。
结构化数据和非结构化数据
结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
非结构化数据:指不定长或无固定格式的数据,如邮件,word文档,网页等。
当然有的地方还会提到第三种,半结构化数据,如XML,HTML等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
注:非结构化数据另外一种叫法叫:全文数据。
数据搜索按照数据的分类,搜索也分为两种:
对结构化数据的搜索:如对数据库的搜索,用SQL语句。再如对元数据的搜索,如利用 windows搜索对文件名,类型,修改时间进行搜索等。
对非结构化数据的搜索:如利用windows的搜索也可以搜索文件内容,Linux下的grep命令,再如用Google和百度可以搜索大量内容数据。
我们重点来探讨对非结构化数据的搜索。
顺序扫描法
所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。比如:利用windows的搜索也可以搜索文件内容,如果做全盘文件的检索,速度会相当的慢,因为硬盘上的数据很大。Linux下的grep命令也是这一种方式。
大家可能觉得这种方法比较原始,但对于小数据量的文件,这种方法还是最直接,最方便的。但是对于大量的文件,这种方法就很慢了。
有人可能会说,对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?
这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
索引与全文检索
比如字典,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。
所以,字典的拼音表和部首检字表就相当于字典的索引,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。
下面这幅图来自《Lucene in action》,但却不仅仅描述了Lucene的检索过程,而是描述了全文检索的一般过程。
全文检索原理
全文检索大体分两个过程,创建索引(Indexing)和搜索索引(Search)。
索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。
正向索引已知文件,欲检索数据,这是建立:文件——数据的映射,称为正向索引,比如下图:
反向索引在大多数的应用中,我们想做的是搜索某个数据都出现在了哪些文件里或网页里
这是已知数据,欲检索文件,这是建立:数据——文件的映射,称为反向索引,又称倒排索引。
假如我们有100篇文章,想查看一下lucene,hadoop,solr 在哪些文章中出现过,如下图:
左边保存的是一系列字符数据,称为词典。每个字符串都指向包含此字符串的文档( Document ) 链表,此文档链表称为倒排表(Posting List)。
比如我们要寻找既包含字符串“lucene”又包含字符串“solr”的文档,我们只需要以下几步:
注意:全文检索的确加快了搜索的速度,但是多了索引的过程,两者加起来不一定比顺序扫描快多少。尤其是在数据量小的时候更是如此。并且对一个很大量的数据创建索引也是一个很慢的过程。
然而两者还是有区别的,顺序扫描是每次都要扫描,而创建索引的过程仅仅需要一次,以后便是一劳永逸的了,每次搜索,创建索引的过程不必经过,仅仅搜索创建好的索引就可以了。这也是全文搜索相对于顺序扫描的优势之一:一次索引,多次使用。
如何创建索引全文检索的索引创建过程一般有以下几步:
1.第一步:一些要索引的原文档(Document)。
为了方便说明索引创建过程,这里特意用两个文件为例:
文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.
2.第二步:将原文档传给分词组件(Tokenizer)。分词组件(Tokenizer)会做以下几件事情(此过程称为Tokenize):
所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建索引时,这种词会被去掉而减少索引的大小。
英语中挺词(Stop word)如:“the”,“a”,“this”等。对于每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合。经过分词(Tokenizer)后得到的结果称为词元(Token)。在我们的例子中,便得到以下词元(Token):
“Students”,“allowed”,“go”,“their”,“friends”,“allowed”,
“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,
“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。
3.第三步:将得到的词元(Token)传给语言处理组件(Linguistic Processor)。
语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处
理。
对于英语,语言处理组件(Linguistic Processor)一般做以下几点:
补充:语言处理组件(linguistic processor)的结果称为词(Term)。
在我们的例子中,经过语言处理,得到的词(Term)如下:
“student”,“allow”,“go”,“their”,“friend”,“allow”,“drink”,
“beer”,“my”,“friend”,“jerry”,“go”,“school”,“see”,“his”,
“student”,“find”,“them”,“drink”,“allow”。
也正是因为有语言处理的步骤,才能使搜索drove,而drive也能被搜索出来。
4.第四步:将得到的词(Term)传给索引组件(Indexer)。索引组件(Indexer)主要做以下几件事情:
4.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 |
4.2 对字典按字母顺序进行排序。
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 |
4.3 合并相同的词(Term)成为文档倒排(Posting List)链表。
在此表中,有几个定义:
Document Frequency 即文档频次,表示总共有多少文件包含此词(Term)。 Frequency 即词频率,表示此文件中包含了几个此词(Term)。
所以对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),从而词(Term)后面的文档链表总共有两项,第一项表示包含“allow”的第一篇文档,即1号文档,此文档中, “allow”出现了2次,第二项表示包含“allow”的第二个文档,是2号文档,此文档中, “allow”出现了1次。到此为止,索引已经创建好了,我们可以通过它很快的找到我们想要的文档。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。