??xml version="1.0" encoding="utf-8" standalone="yes"?>
作者:forfuture1978 (from CSDN)
我们都知道,Lucene是一个开放源代码 的全文检索引擎工具包。那么全文检索到底是什么? q要从我们生zM的数据说赗?/span>
我们生活中的数据M分ؓ两种Q?span style="color: #0000ff">l构化数?/strong> ?span style="color: #0000ff">非结构化数据 ?/p>
当然有的地方q会提到W三U,半结构化数据Q如XMLQHTML{,当根据需要可按结构化数据来处理,也可抽取出纯文本按非l构化数据来处理?/p>
非结构化数据又一U叫法叫全文数据?/strong>
按照数据的分c,搜烦也分ZU: 寚wl构化数据也卛_全文数据的搜索主要有两种ҎQ?/p>
一U是序扫描?/strong> (Serial Scanning) Q?/strong> 所谓顺序扫描,比如要找内容包含某一个字W串的文Ӟ是一个文一个文的看,对于每一个文档,从头看到,如果此文包含此字符Ԍ则此文为我们要扄文gQ接着看下一个文Ӟ直到扫描完所有的文g。如利用windows的搜索也可以搜烦文g内容Q只是相当的慢。如果你有一?0G盘Q如果想在上面找C个内容包含某字符串的文gQ不׃几个时Q怕是做不到。Linux下的grep命o也是q一U方式。大家可能觉得这U方法比较原始,但对于小数据量的文gQ这U方法还是最直接Q最方便的。但是对于大量的文gQ这U方法就很慢了?/p>
有h可能会说Q对非结构化数据序扫描很慢Q对l构化数据的搜烦却相对较快(׃l构化数据有一定的l构可以采取一定的搜烦法加快速度Q,那么把我们的非结构化数据惛_法弄得有一定结构不p了吗Q?/p>
q种x很天Ӟ却构成了全文索的基本思\Q也卛_非结构化数据中的一部分信息提取出来Q重新组l,使其变得有一定结构,然后Ҏ有一定结构的数据q行搜烦Q从而达到搜索相对较快的目的?/p>
q部分从非结构化数据中提取出的然后重新组l的信息Q我们称?strong>索引 q种说法比较抽象QD几个例子很Ҏ明白Q比如字典,字典的拼韌和部首检字表q当于字典的烦引,Ҏ一个字的解释是非结构化的,如果字典没有韌表和部首字表Q在茫茫辞v中找一个字只能序扫描。然而字的某些信息可以提取出来进行结构化处理Q比如读韻I比较结构化Q分声母和韵母,分别只有几种可以一一列DQ于是将读音拿出来按一定的序排列Q每一读音都指向此字的详l解释的|。我们搜索时按结构化的拼x到读韻I然后按其指向的页敎ͼ便可扑ֈ我们的非l构化数据——也卛_字的解释?/p>
q种先徏立烦引,再对索引q行搜烦的过E就叫全文检?Full-text Search) ?/strong>
下面q幅图来自《Lucene in action》,但却不仅仅描qCLucene的检索过E,而是描述了全文检索的一般过E?img height="479" alt="" src="http://dl.javaeye.com/upload/picture/pic/55997/9512a770-0784-3231-9da5-608a46014b2d.png" width="544" /> 全文索大体分两个q程Q?span style="color: #0000ff">索引创徏 (Indexing) ?span style="color: #0000ff">搜烦索引 (Search) ?/p>
于是全文索就存在三个重要问题Q?/p>
1. 索引里面I竟存些什么?(Index) 2. 如何创徏索引Q?Indexing) 3. 如何对烦引进行搜索?(Search) 下面我们序Ҏ个个问题q行研究?/p>
一?/span> 索引里面I竟存些什么?(Index) 首先我们来看Z么顺序扫描的速度慢: 其实是由于我们想要搜索的信息和非l构化数据中所存储的信息不一致造成的?/p>
非结构化数据中所存储的信息是每个文g包含哪些字符Ԍ也即已知文gQ欲求字W串相对ҎQ也x从文件到字符串的映射。而我们想搜烦的信息是哪些文g包含此字W串Q也卛_知字W串Q欲求文Ӟ也即从字W串到文件的映射。两者恰恰相反。于是如果烦引总能够保存从字符串到文g的映,则会大大提高搜烦速度?/p>
׃从字W串到文件的映射是文件到字符串映的反向q程Q于是保存这U信息的索引UCؓ反向索引 ?/p>
反向索引的所保存的信息一般如下: 假设我的文集合里面?00文档,Z方便表示Q我们ؓ文~号??00Q得C面的l构 左边保存的是一pd字符ԌUCؓ词典 ?/span> 每个字符串都指向包含此字W串的文?Document)链表Q此文链表UCؓ倒排?/strong> (Posting List) ?/p>
有了索引Q便使保存的信息和要搜烦的信息一_可以大大加快搜烦的速度?/p>
比如_我们要寻找既包含字符?#8220;lucene”又包含字W串“solr”的文,我们只需要以下几步: 1. 取出包含字符?#8220;lucene”的文链表?/p>
2. 取出包含字符?#8220;solr”的文档链表?/p>
3. 通过合ƈ链表Q找出既包含“lucene”又包?#8220;solr”的文件?img height="55" alt="" src="http://hxraid.javaeye.com/upload/picture/pic/56001/7e04a727-6cdb-3434-a260-023bc163b497.jpg" width="544" /> 看到q个地方Q有人可能会_全文索的加快了搜烦的速度Q但是多了烦引的q程Q两者加h不一定比序扫描快多。的,加上索引的过E,全文索不一定比序扫描快,其是在数据量小的时候更是如此。而对一个很大量的数据创建烦引也是一个很慢的q程?/p>
然而两者还是有区别的,序扫描是每ơ都要扫描,而创建烦引的q程仅仅需要一ơ,以后便是一x逸的了,每次搜烦Q创建烦引的q程不必l过Q仅仅搜索创建好的烦引就可以了?/p>
q也是全文搜索相对于序扫描的优势之一Q一ơ烦引,多次使用?/strong> 二?/span> 如何创徏索引Q?Indexing) 全文索的索引创徏q程一般有以下几步Q?/p>
1、一些要索引的原始文?Document) Z方便说明索引创徏q程Q这里特意用两个文gZQ?/p>
文g一QStudents should be allowed to go out with their friends, but not allowed to drink beer. 文g二:My friend Jerry went to school to see his students but found them drunk which is not allowed. 2、将原始文传给分词lg(Tokenizer) 分词lg(Tokenizer)会做以下几g事情( 此过E称为Tokenize) Q?/strong> 1. 文档分成一个一个单独的单词?/strong> 2. 去除标点W号?/strong> 3. 去除停用?Stop word) ?/strong> 所?strong>停用?Stop word)
p中挺?Stop word)如:“the”,“a”Q?#8220;this”{?/p>
对于每一U语a的分词组?Tokenizer)Q都有一个停?stop word)集合?/p>
l过分词(Tokenizer) 后得到的l果UCؓ词元(Token) ?/strong>
在我们的例子中,便得C下词?Token)Q?/p>
“Students”Q?#8220;allowed”Q?#8220;go”Q?#8220;their”Q?#8220;friends”Q?#8220;allowed”Q?#8220;drink”Q?#8220;beer”Q?#8220;My”Q?#8220;friend”Q?#8220;Jerry”Q?#8220;went”Q?#8220;school”Q?#8220;see”Q?#8220;his”Q?#8220;students”Q?#8220;found”Q?#8220;them”Q?#8220;drunk”Q?#8220;allowed”?/p>
3、将得到的词?Token)传给语言处理lg(Linguistic Processor)
语言处理lg(linguistic processor)主要是对得到的词?Token)做一些同语言相关的处理?/p>
对于pQ语a处理lg(Linguistic Processor) 一般做以下几点Q?/strong>
1. 变ؓ写(Lowercase) ?/strong>
2. 单词羃减ؓ词根形式Q如“cars ”?#8220;car ”{。这U操作称为:stemming ?/strong>
3. 单词{变ؓ词根形式Q如“drove ”?#8220;drive ”{。这U操作称为:lemmatization ?/strong>
Stemming ?lemmatization的异同:
语言处理lg(linguistic processor)的结果称(Term) ?/strong>
在我们的例子中,l过语言处理Q得到的?Term)如下Q?/p>
“student”Q?#8220;allow”Q?#8220;go”Q?#8220;their”Q?#8220;friend”Q?#8220;allow”Q?#8220;drink”Q?#8220;beer”Q?#8220;my”Q?#8220;friend”Q?#8220;jerry”Q?#8220;go”Q?#8220;school”Q?#8220;see”Q?#8220;his”Q?#8220;student”Q?#8220;find”Q?#8220;them”Q?#8220;drink”Q?#8220;allow”?/p>
也正是因为有语言处理的步骤,才能使搜索droveQ而drive也能被搜索出来?/p>
4、将得到的词(Term)传给索引lg(Indexer)
索引lg主要是ؓ了得C面这个图Q?img alt="" src="http://hxraid.javaeye.com/upload/picture/pic/56003/7ca0f9b1-e82a-35c1-a97e-e40c2d4a70c9.jpg" />
在此表中Q有几个定义Q?/p>
所以对?Term) “allow”来讲Qd有两文包含此?Term)Q从而词(Term)后面的文档链表d有两,W一表C包?#8220;allow”的第一文,?1h,此文中Q?#8220;allow”出现?ơ,W二表C包?#8220;allow”的第二个文Q是2h档,此文中Q?#8220;allow”出现?ơ?/p>
到此为止Q烦引已l创建好了,我们可以通过它很快的扑ֈ我们惌的文?/p>
而且在此q程中,我们惊喜地发玎ͼ搜烦“drive”Q?#8220;driving”Q?#8220;drove”Q?#8220;driven”也能够被搜到。因为在我们的烦引中Q?#8220;driving”Q?#8220;drove”Q?#8220;driven”都会l过语言处理而变?#8220;drive”Q在搜烦Ӟ如果您输?#8220;driving”Q输入的查询语句同样l过我们q里的一C步,从而变为查?#8220;drive”Q从而可以搜索到惌的文?/p>
三?/span> 如何对烦引进行搜索?(Search)
到这里似乎我们可以宣?#8220;我们扑ֈ惌的文档了”?/p>
然而事情ƈ没有l束Q找C仅仅是全文检索的一个方面。不是吗Q如果仅仅只有一个或十个文包含我们查询的字W串Q我们的找C。然而如果结果有一千个Q甚x千上万个呢?那个又是您最惌的文件呢Q?/p>
打开Google吧,比如说您惛_微Y找䆾工作Q于是您输入“Microsoft job”Q您却发现d?2600000个结果返回。好大的数字呀Q突然发现找不到是一个问题,扑ֈ的太多也是一个问题。在如此多的l果中,如何最相关的放在最前面呢?
当然Google做的很不错,您一下就扑ֈ了jobs at Microsoft。想象一下,如果前几个全部是“Microsoft does a good job at software industry…”是多么可怕的事情呀?/p>
如何像Google一P在成千上万的搜烦l果中,扑ֈ和查询语句最相关的呢Q?/span>
如何判断搜烦出的文和查询语句的相关性呢Q?/span>
q要回到我们W三个问题:如何对烦引进行搜索?
搜烦主要分ؓ以下几步Q?/p>
1、用于输入查询语?/span>
查询语句同我们普通的语言一P也是有一定语法的?/p>
不同的查询语句有不同的语法,如SQL语句有一定的语法?/p>
查询语句的语法根据全文检索系l的实现而不同。最基本的有比如QAND, OR, NOT{?/p>
举个例子Q用戯入语句:lucene AND learned NOT hadoop?/p>
说明用户x一个包含lucene和learned然而不包括hadoop的文档?/p>
2、对查询语句q行词法分析Q语法分析及语言处理
׃查询语句有语法,因而也要进行语法分析,语法分析及语a处理?/p>
词法分析主要用来识别单词和关键字?/strong>
如上qC子中Q经q词法分析,得到单词有luceneQlearnedQhadoop, 关键字有AND, NOT?/p>
如果在词法分析中发现不合法的关键字,则会出现错误。如lucene AMD learnedQ其中由于AND拼错Q导致AMD作ؓ一个普通的单词参与查询?/p>
语法分析主要是根据查询语句的语法规则来Ş成一语法树?/strong>
如果发现查询语句不满法规则,则会报错。如lucene NOT AND learnedQ则会出错?/p>
语言处理同烦引过E中的语a处理几乎相同?/strong>
如learned变成learn{?/p>
3、搜索烦引,得到W合语法树的文
此步骤有分几步Q?/p>
首先Q在反向索引表中Q分别找出包含luceneQlearnQhadoop的文链表?strong>
其次Q对包含luceneQlearn的链表进行合q操作,得到既包含lucene又包含learn的文链表?strong>
然后Q将此链表与hadoop的文链表进行差操作Q去除包含hadoop的文,从而得到既包含lucene又包含learn而且不包含hadoop的文链表?strong>
最后,此文链表就是我们要扄文?
4、根据得到的文和查询语句的相关性,对结果进行排序?/span>
虽然在上一步,我们得到了想要的文档Q然而对于查询结果应该按照与查询语句的相x进行排序,相兌越靠前?/p>
如何计算文档和查询语句的相关性呢Q?/span>
不如我们把查询语句看作一片短的文档Q对文与文之间的相关?relevance)q行打分(scoring)Q分数高的相x好Q就应该排在前面?/p>
那么又怎么Ҏ之间的关系q行打分呢?
首先Q一个文有很多?Term)l成 Q?/span> 如search, lucene, full-text, this, a, what{?/p>
其次对于文档之间的关p,不同的Term重要性不?/strong> Q?/span> 比如对于本篇文档Qsearch, Lucene, full-textq寚w要一些,this, a , what可能相对不重要一些。所以如果两文都包含search, LuceneQfulltextQ这两篇文的相x好一些,然而就一文包含this, a, whatQ另一文不包含this, a, whatQ也不能影响两篇文的相x?/p>
因而判断文之间的关系Q首先找出哪些词(Term)Ҏ之间的关系最重要Q如search, Lucene, fulltext。然后判断这些词(Term)之间的关pR?/p>
扑և?Term) Ҏ档的重要性的q程UCؓ计算词的权重(Term weight) 的过E?/strong> 计算词的权重(term weight)有两个参敎ͼW一个是?Term)Q第二个是文?Document)?/p>
词的权重(Term weight)表示此词(Term)在此文档中的重要E度Q越重要的词(Term)有越大的权重(Term weight)Q因而在计算文之间的相x中发挥更大的作用?/p>
判断?Term) 之间的关pM而得到文相x的q程应用一U叫做向量空间模型的法(Vector Space Model) ?/strong>
下面仔细分析一下这两个q程Q?/p>
影响一个词(Term)在一文中的重要性主要有两个因素Q?/p>
Ҏ理解吗??Term)在文档中出现的次数越多,说明此词(Term)对该文重要,?#8220;搜烦”q个词,在本文中出现的ơ数很多Q说明本文主要是讲这斚w的事的。然而在一英语文档中Qthis出现的次数更多,p明越重要吗?不是的,q是q二个因素q行调整Q第二个因素说明Q有多的文包含此?Term), 说明此词(Term)太普通,不以区分这些文,因而重要性越低?/p>
q也如我们程序员所学的技术,对于E序员本w来_q项技术掌握越p好(掌握深说明花时间看的越多,tf大Q,扑ַ作时有竞争力。然而对于所有程序员来说Q这Ҏ术懂得的越好(懂得的hdf)Q找工作有竞争力。h的h值在于不可替代性就是这个道理?/p>
道理明白了,我们来看看公式: q仅仅只term weight计算公式的简单典型实现。实现全文检索系l的Z有自q实现QLucene׃此稍有不同?/p>
我们把文看作一pd?Term)Q每一个词(Term)都有一个权?Term weight)Q不同的?Term)Ҏ自己在文中的权重来影响文档相关性的打分计算?/p>
于是我们把所有此文中词(term)的权?term weight) 看作一个向量?/p>
Document = {term1, term2, …… ,term N} Document Vector = {weight1, weight2, …… ,weight N} 同样我们把查询语句看作一个简单的文Q也用向量来表示?/p>
Query = {term1, term 2, …… , term N} Query Vector = {weight1, weight2, …… , weight N} 我们把所有搜索出的文档向量及查询向量攑ֈ一个Nl空间中Q每个词(term)是一l?/p>
我们认ؓ两个向量之间的夹角越,相关性越大?/p>
所以我们计夹角的余ug为相x的打分Q夹角越,余uD大,打分高Q相x越大?/p>
有h可能会问Q查询语句一般是很短的,包含的词(Term)是很的Q因而查询向量的l数很小Q而文很长,包含?Term)很多Q文向量维数很大。你的图中两者维数怎么都是N呢? 在这里,既然要放到相同的向量I间Q自然维数是相同的,不同Ӟ取二者的qQ如果不含某个词(Term)Ӟ则权?Term Weight)??/p>
相关性打分公式如下: Ҏq个公式p出文档与查询之间的怼E度了?/p>
四、ȝ 对上q烦引创建和搜烦q程所一个ȝQ如图: 此图参照http://www.lucene.com.cn/about.htm 中文章《开放源代码的全文检索引擎Lucene?/p>
1. 索引q程Q?/strong> a 有一pd被烦引文?/strong> b) 被烦引文件经q语法分析和语言处理形成一pd?Term) ?/strong> c) l过索引创徏形成词典和反向烦引表?/strong> d) 通过索引存储烦引写入硬盘?/strong> 2. 搜烦q程Q?/strong> a) 用户输入查询语句?/strong> b) Ҏ询语句经q语法分析和语言分析得到一pd?Term) ?/strong> c) 通过语法分析得到一个查询树?/strong> d) 通过索引存储烦引读入到内存?/strong> e) 利用查询树搜索烦引,从而得到每个词(Term) 的文链表,Ҏ档链表进行交Q差Qƈ得到l果文?/strong> f) 搜索到的结果文对查询的相x进行排序?/strong> g) q回查询l果l用戗?/strong> 1. 计算权重(Term weight)的过E?/strong>
2. 判断Term之间的关pM而得到文相x的q程Q也卛_量空间模型的法(VSM)?/strong>
]]>
վ֩ģ壺
ŷ|
|
ƽԶ|
ֺ|
ƺ|
|
³|
|
ׯ|
|
|
̨|
|
ϲ|
|
ˮ|
̨ǰ|
|
|
|
|
|
ʶ|
|
|
ˮ|
|
|
üɽ|
|
ʯ|
ʻ|
Ӧ|
|
|
ɽ|
|
߱|
ȫ|
|
|