Luence Solr Nutch说明

 

Luence Solr Nutch说明

 


概述

1.1  Luence

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。http://lucene.apache.org/

1.2  Solr

Solr是一个独立企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果;

1.3  Nutch

Nutch 是一个开源Java实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。

 

1.4 三者区别

Lucence与solr的区别

很多像我刚接触 Lucene 和 Solr 的人都会问这样的问题:何时用Lucene?何时用Solr?两种有什么关系?

答案很简单:如果你问自己这样的问题,那么99%的情形,你需要的是Solr!

Solr是什么?

Apache Solr是包含各类功能的围绕Lucene的HTTP包装。

诸如增加了XML/HTTP和JSON API,XML/HTTP和JSON APIs、命中率加亮、面状搜索,缓存、复制、Web管理界面等等。

其中Lucene为包而非应用。Solr为一Web应用(WAR),可部署在任一Servlet容器中,诸如Jetty、Tomcat、Resin等。

支持能力如何?

简言之,当然如此!Solr社区很活跃也很乐于助人。

Lucene可读取Solr的索引或反之?

因为Solr之中内嵌了Lucene,实际上是一回事。

在技术上没有所谓的Solr的索引,只有Solr实例创建的Lucene索引这样的事情。

何时该用Lucene

如果想在应用中嵌入全文搜索功能(如桌面程序),Luucene是更合适的选择

此类情况,更多的是个性化需求,需要访问底层的Lucene API类,Solr 只会帮倒忙,因为它是额外的间接(封装)层。

Lucence与nutch的区别

lucene提供的只是一个简单的全文检索的函数库
nutch
使用lucene的API,实现了一个完整的搜索引擎

l  三者区别

lucene是一个做搜索用的类库。
nutch
和solr都是基于lucene的,二者都是可直接运行的应用程序。
solr是lucene的服务器化,内嵌了jetty,提供REST接口,
用户可以直接post数据给solr,然后由solr进行索引。
solr不包含下载系统,用户需要负责下载,转成solr所需要的格式。
solr还提供查询接口供用户查询。
nutch可以看成一个out-of-box的搜索引擎,包含了crawler,indexer和查询接口。
但nutch更偏向于下载系统。
一般可以使用nutch做crawler,而使用solr做indexer和查询接口。

 

 

2  Luence使用说明

下载地址:http://www.apache.org/dyn/closer.cgi/lucene/java/4.4.0

2.1  Lucene原理

2.1.1  Luence搜索机制

Lucene采用反向索引(inverted index)机制。

通过实现特定API,完成文档建立索引的工作。

Luence通过特定的类,可以对索引操作。

通过特定的类,封装操作结果,供应用程序处理。

Luence创建索引及搜索如下图:

系统机构以及源码结构如下图:

Luence数据结构与DB对比,如下图:

2.2  在文件上建立索引

2.2.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.2.2  将原文档传给分词组件(Tokenizer)

分词组件(Tokenizer)会做以下几件事情(此过程称为Tokenize):

1. 将文档分成一个一个单独的单词。

2. 去除标点符号。

3. 去除停词(Stop word)

所谓停词(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”。

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

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

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

1. 变为小写(Lowercase)

2. 将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming。

3. 将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization。

 

Stemming 和 lemmatization的异同:

相同之处:Stemming和lemmatization都要使词汇成为词根形式。

两者的方式不同:

Stemming采用的是“缩减”的方式:“cars”到“car”,“driving”到“drive”。

Lemmatization采用的是“转变”的方式:“drove”到“drove”,“driving”到“drive”。

两者的算法不同:

Stemming主要是采取某种固定的算法来做这种缩减,如去除“s”,去除“ing”加“e”,将“ational”变为“ate”,将“tional”变为“tion”。

Lemmatization主要是采用保存某种字典的方式做这种转变。比如字典中有“driving”到“drive”,“drove”到“drive”,“am, is, are”到“be”的映射,做转变时,只要查字典就可以了。

Stemming和lemmatization不是互斥关系,是有交集的,有的词利用这两种方式都能达到相同的转换。

语言处理组件(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也能被搜索出来。

2.2.4  将得到的词(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

 

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

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

在此表中,有几个定义:

Document Frequency即文档频次,表示总共有多少文件包含此词(Term)

Frequency 即词频率,表示此文件中包含了几个此词(Term)

所以对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),从而词(Term)后面的文档链表总共有两项,第一项表示包含“allow”的第一篇文档,即1号文档,此文档中,“allow”出现了2次,第二项表示包含“allow”的第二个文档,是2号文档,此文档中,“allow”出现了1次。

到此为止,索引已经创建好了,我们可以通过它很快的找到我们想要的文档。

而且在此过程中,我们惊喜地发现,搜索“drive”,“driving”,“drove”,“driven”也能够被搜到。因为在我们的索引中,“driving”,“drove”,“driven”都会经过语言处理而变成“drive”,在搜索时,如果您输入“driving”,输入的查询语句同样经过我们这里的一到三步,从而变为查询“drive”,从而可以搜索到想要的文档。

 

2.3  在索引基础上搜索

2.3.1  用户输入查询语句

查询语句同我们普通的语言一样,也是有一定语法的。

不同的查询语句有不同的语法,如SQL语句就有一定的语法。

查询语句的语法根据全文检索系统的实现而不同。最基本的有比如:AND, OR, NOT等。

举个例子,用户输入语句:lucene AND learned NOT hadoop

说明用户想找一个包含lucene和learned然而不包括hadoop的文档。

2.3.2  对查询语句进行词法分析,语法分析,及语言处理

由于查询语句有语法,因而也要进行语法分析,语法分析及语言处理。

1. 词法分析主要用来识别单词和关键字。

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

如果在词法分析中发现不合法的关键字,则会出现错误。如lucene AMD learned,其中由于AND拼错,导致AMD作为一个普通的单词参与查询。

2. 语法分析主要是根据查询语句的语法规则来形成一棵语法树。

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

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

3. 语言处理同索引过程中的语言处理几乎相同。

如learned变成learn等。

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

2.3.3  搜索索引,得到符合语法树的文档

此步骤有分几小步:

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

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

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

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

2.3.4  根据得到的文档和查询语句的相关性,对结果进行排序

虽然在上一步,我们得到了想要的文档,然而对于查询结果应该按照与查询语句的相关性进行排序,越相关者越靠前。

如何计算文档和查询语句的相关性呢?

不如我们把查询语句看作一片短小的文档,对文档与文档之间的相关性(relevance)进行打分(scoring),分数高的相关性好,就应该排在前面。

那么又怎么对文档之间的关系进行打分呢?

这可不是一件容易的事情,首先我们看一看判断人之间的关系吧。

首先看一个人,往往有很多要素,如性格,信仰,爱好,衣着,高矮,胖瘦等等。

其次对于人与人之间的关系,不同的要素重要性不同,性格,信仰,爱好可能重要些,衣着,高矮,胖瘦可能就不那么重要了,所以具有相同或相似性格,信仰,爱好的人比较容易成为好的朋友,然而衣着,高矮,胖瘦不同的人,也可以成为好的朋友。

因而判断人与人之间的关系,首先要找出哪些要素对人与人之间的关系最重要,比如性格,信仰,爱好。其次要判断两个人的这些要素之间的关系,比如一个人性格开朗,另一个人性格外向,一个人信仰佛教,另一个信仰上帝,一个人爱好打篮球,另一个爱好踢足球。我们发现,两个人在性格方面都很积极,信仰方面都很善良,爱好方面都爱运动,因而两个人关系应该会很好。

 

我们再来看看公司之间的关系吧。

首先看一个公司,有很多人组成,如总经理,经理,首席技术官,普通员工,保安,门卫等。

其次对于公司与公司之间的关系,不同的人重要性不同,总经理,经理,首席技术官可能更重要一些,普通员工,保安,门卫可能较不重要一点。所以如果两个公司总经理,经理,首席技术官之间关系比较好,两个公司容易有比较好的关系。然而一位普通员工就算与另一家公司的一位普通员工有血海深仇,怕也难影响两个公司之间的关系。

因而判断公司与公司之间的关系,首先要找出哪些人对公司与公司之间的关系最重要,比如总经理,经理,首席技术官。其次要判断这些人之间的关系,不如两家公司的总经理曾经是同学,经理是老乡,首席技术官曾是创业伙伴。我们发现,两家公司无论总经理,经理,首席技术官,关系都很好,因而两家公司关系应该会很好。

 

分析了两种关系,下面看一下如何判断文档之间的关系了。

首先,一个文档有很多词(Term)组成,如search, lucene, full-text, this, a, what等。

其次对于文档之间的关系,不同的Term重要性不同,比如对于本篇文档,search, Lucene, full-text就相对重要一些,this, a , what可能相对不重要一些。所以如果两篇文档都包含search, Lucene,fulltext,这两篇文档的相关性好一些,然而就算一篇文档包含this, a, what,另一篇文档不包含this, a, what,也不能影响两篇文档的相关性。

因而判断文档之间的关系,首先找出哪些词(Term)对文档之间的关系最重要,如search, Lucene, fulltext。然后判断这些词(Term)之间的关系。

 

找出词(Term)对文档的重要性的过程称为计算词的权重(Term weight)的过程。

计算词的权重(term weight)有两个参数,第一个是词(Term),第二个是文档(Document)。

词的权重(Term weight)表示此词(Term)在此文档中的重要程度,越重要的词(Term)有越大的权重(Term weight),因而在计算文档之间的相关性中将发挥更大的作用。

判断词(Term)之间的关系从而得到文档相关性的过程应用一种叫做向量空间模型的算法(Vector Space Model)。

下面仔细分析一下这两个过程:

1.  计算权重(Term weight)的过程。

影响一个词(Term)在一篇文档中的重要性主要有两个因素:

Term Frequency (tf):即此Term在此文档中出现了多少次。tf 越大说明越重要。

Document Frequency (df):即有多少文档包含次Term。df 越大说明越不重要。

容易理解吗?词(Term)在文档中出现的次数越多,说明此词(Term)对该文档越重要,如“搜索”这个词,在本文档中出现的次数很多,说明本文档主要就是讲这方面的事的。然而在一篇英语文档中,this出现的次数更多,就说明越重要吗?不是的,这是由第二个因素进行调整,第二个因素说明,有越多的文档包含此词(Term), 说明此词(Term)太普通,不足以区分这些文档,因而重要性越低。

这也如我们程序员所学的技术,对于程序员本身来说,这项技术掌握越深越好(掌握越深说明花时间看的越多,tf越大),找工作时越有竞争力。然而对于所有程序员来说,这项技术懂得的人越少越好(懂得的人少df小),找工作越有竞争力。人的价值在于不可替代性就是这个道理。

道理明白了,我们来看看公式:

这仅仅只term weight计算公式的简单典型实现。实现全文检索系统的人会有自己的实现,Lucene就与此稍有不同。

 

2. 2. 判断Term之间的关系从而得到文档相关性的过程,也即向量空间模型的算法(VSM)

我们把文档看作一系列词(Term),每一个词(Term)都有一个权重(Term weight),不同的词(Term)根据自己在文档中的权重来影响文档相关性的打分计算。

于是我们把所有此文档中词(term)的权重(term weight) 看作一个向量。

Document = {term1, term2, …… ,term N}

Document Vector = {weight1, weight2, …… ,weight N}

同样我们把查询语句看作一个简单的文档,也用向量来表示。

Query = {term1, term 2, …… , term N}

Query Vector = {weight1, weight2, …… , weight N}

我们把所有搜索出的文档向量及查询向量放到一个N维空间中,每个词(term)是一维。

如图:

我们认为两个向量之间的夹角越小,相关性越大。

所以我们计算夹角的余弦值作为相关性的打分,夹角越小,余弦值越大,打分越高,相关性越大。

有人可能会问,查询语句一般是很短的,包含的词(Term)是很少的,因而查询向量的维数很小,而文档很长,包含词(Term)很多,文档向量维数很大。你的图中两者维数怎么都是N呢?

在这里,既然要放到相同的向量空间,自然维数是相同的,不同时,取二者的并集,如果不含某个词(Term)时,则权重(Term Weight)为0。

 

相关性打分公式如下:

举个例子,查询语句有11个Term,共有三篇文档搜索出来。其中各自的权重(Term weight),如下表格。

t1

t2

t3

t4

t5

t6

t7

t8

t9

t10

t11

D1

0

0

.477

0

.477

.176

0

0

0

.176

0

D2

0

.176

0

.477

0

0

0

0

.954

0

.176

D3

0

.176

0

0

0

.176

0

0

0

.176

.176

Q

0

0

0

0

0

.176

0

0

.477

0

.176

于是计算,三篇文档同查询语句的相关性打分分别为:

 

于是文档二相关性最高,先返回,其次是文档一,最后是文档三。

到此为止,我们可以找到我们最想要的文档了。

 

说了这么多,其实还没有进入到Lucene,而仅仅是信息检索技术(Information retrieval)中的基本理论,然而当我们看过Lucene后我们会发现,Lucene是对这种基本理论的一种基本的的实践。所以在以后分析Lucene的文章中,会常常看到以上理论在Lucene中的应用。

在进入Lucene之前,对上述索引创建和搜索过程所一个总结,如图:

此图参照http://www.lucene.com.cn/about.htm中文章《开放源代码的全文检索引擎Lucene》

1. 索引过程:

1) 有一系列被索引文件

2) 被索引文件经过语法分析和语言处理形成一系列词(Term)

3) 经过索引创建形成词典和反向索引表。

4) 通过索引存储将索引写入硬盘。

2. 搜索过程:

a) 用户输入查询语句。

b) 对查询语句经过语法分析和语言分析得到一系列词(Term)

c) 通过语法分析得到一个查询树。

d) 通过索引存储将索引读入到内存。

e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。

f) 将搜索到的结果文档对查询的相关性进行排序。

g) 返回查询结果给用户。

 

下面我们可以进入Lucene的世界了。

3  Solr使用说明

4  Nutch使用说明

 

:全文检索原理

全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。


一、索引项term
1
、索引项
英文:空格分隔的单词
中文:字,迭代二元项,中文分词
2、索引项处理
提取词干:对于英文,一般是取词干,对于中文,一般是取同义词,目的是减少索引项的数目,提高检索速度,提高查全率
中文分词:尤其对于歧义词需要处理,对于提高准确率有益
词性标注:对于某些词不做索引,比如叹词、连词、助词、标点等
停止词表:英文:the, a, and, 中文:的,了,和,


二、全文检索评价标准
精确度: Precision = 正确返回结果/所有返回结果
查全率: Recall = 正确返回结果/所有正确结果
(Precision高,Recall不一定高;反之依然)
索引膨胀率
查询速度
索引建立速度


三、全文检索基本模型
1
、倒排索引
建立索引的步骤
识别文档中的词
删除停用词
提取词干
用索引项的编号代替词干
统计词干的数量
计算权重
索引结构
hash ,b+-tree

检索过程
分析给定query
对分析后的query进行词干提取,算法与对文档的处理 相同
用索引项编号代替词干
对找到的索引项内的文档纪录进行逻辑处理和排序
返回排序后的文档集合

倒排索引的优点
快速索引(长query需要更多时间,线形增加)
灵活性: 不同类型的信息都可以存储在postings list中
如果存储了足够多的信息,则可以支持复杂的检索操作
例如:如果记录了词在文档中的准确位置,就可以支持短语检索,或模糊检索
倒排索引的缺点
很大的存储开销 50% -150% -300%
更新、插入和删除都需要很高的维护开销,倒排索引相对静态的环境(很少插入和更新)中使用比较好
处理开销随着布尔操作的增加而增长

2、签名文件
优点
Signature文件小而可控
由于文件组织简单,因此维护费用小(更新和删除)
Signatures容易生成,插入费用低
重叠编码适合多属性检索
Signature文件在倒排文件和全文扫描之间做了空间和时间的平衡
适合中等大小的数据库和查询频率较低的系统
容易进行并行处理
缺点
和倒排文件相比,搜索速度慢
去除False drops需要昂贵的开销 因为所有被匹配的signature必须通过模式匹配来确认
在signature中,很难对频率和权值信息进行编码
其它query函数,例如分离条件、同义词、通配符, 邻近(proximity)操作都很难使用
3、Pat数组
Pat数组模型将文本看成一组字符串的有序叠合,用户输入的检索字符串就不会被分解成单个字符的集合,而是直接检索字符串.

四、lucene介绍
Lucene是apache软件基金会[4] jakarta项目组的一个子项目,是一个开放源代码[5]的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。

Lucene作为一个全文检索引擎,其具有如下突出的优点:
(1)索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
(2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
(3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
(4)设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
(5)已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。

lucene的组成结构:对于外部应用来说索引模块(index)和检索模块(search)是主要的外部应用入口
org.apache.Lucene.search/ 搜索入口
org.apache.Lucene.index/ 索引入口
org.apache.Lucene.analysis/ 语言分析器
org.apache.Lucene.queryParser/ 查询分析器
org.apache.Lucene.document/ 存储结构
org.apache.Lucene.store/ 底层IO/存储结构
org.apache.Lucene.util/ 一些公用的数据结构

 

 

你可能感兴趣的:(搜索)