搜索引擎框架学习文档Word文件下载.docx
《搜索引擎框架学习文档Word文件下载.docx》由会员分享,可在线阅读,更多相关《搜索引擎框架学习文档Word文件下载.docx(48页珍藏版)》请在冰点文库上搜索。
Goole搜索
普通树
表格
锁定、列拖动、列宽调整、排序、分页、下载、打印
2.2使用模式
普通树
数据提交
中间数据取数
数据展示
表格
数据提交(选中)
数据显示
分页
2设计
2.1设计方案一
2.1.1实现方法
OTPajax标签的dataset与strutsform相互转换。
扩展struts的控制器RequestProcessor,如果是ajax标签的请求(怎么判断?
),执行如下步骤:
a)、在创建form后,将AjaxContext中的dataset映射到form的相应属性。
1、DataSet全部映射到Form(StrutsForm作为DataSet的实现),页面Page对象记录页面中用到的Property,Ajax请求时,控制返回的对象只有这些Property
b)、执行struts的action。
c)、将form中的新数据映射到AjaxContext的dataset中。
d)、response将dataset输出成json字符串到前台。
e)、ajax不需要页面跳转,所以action配置时不需要配置forward,或才将forward置为null。
原Ajax流程:
Ajax与struts整合流程:
2.1.2优点
a)、Ajax标签几乎不用修改
b)、web可以异步提交也可走正常的struts交易流程
c)、已有strtus系统,只要修改要用ajax标签的jsp
d)、Ajax组件,异步取数也可以走struts的action
a)、原来struts系统form中的字段较多,在前台界面可能要定义过多的dataset;
(dataset添加一个类型form,为form类型时,将此dataset中的属性与form的属性一致,或者将dataset对应的javabean为form类型时,将dataset的属性映射到form的属性)
b)、前台存在dataset,后台dataset又是透明的,dataset在后台算是多于的;
c)、Ajax提交方式都以异步方式,如果要使用ajax标签,已经有Struts的jsp页面只能重新开发,不能修改。
(可修改表单项相关标签,支持struts)。
2.2设计方案二
2.2.1实现方法
修改OTPAjax标签,让表单项从form的属性中获取初始值。
各组件从form中获取初始数据。
提交表单采用同步方式到struts交易,组件获取非业务数据还可采用异步方式。
a)、修改OTPAjax标签的表单项,添加属性property,指定对应form中的属性值。
页面载入时,根据form初始化表单项的值。
/*标签初始方法*/
publicintdoStartTag()throwsJspTagException{
ponent=newComboxStruts();
try{
Stringname=this.getName();
Stringproperty=this.getProperty();
Objectvalue=TagUtils.getInstance().lookup(pageContext,name,property,null);
this.setValue((String)value);
this.setRawValue((String)value);
this.setName(property);
}catch(Exceptione){
e.printStackTrace();
}
returnEVAL_BODY_INCLUDE;
}
b)、组件标签,从form中获取初始数据,将数据拼成js的dataset输入到前端。
页面渲染后,组件绑定的dataset都有相应的初始数据。
c)、同步提交表单,使用strutsform,form中组件可以使用。
使用正常的strutsform提交方式。
<
html:
formaction="
/HelloWorld.do"
focus="
userName"
>
<
core:
comboxstrutscodetype="
typeCode"
name="
ComboxDemoForm"
florderSelect="
true"
value="
type1"
property="
userType"
/>
submitproperty="
submit"
Submit"
/>
reset/>
/html:
form>
d)、Ajax标签组件异步取非业务数据,使用AjaxCommand取得。
2.2.2优点
a)、现在struts系统的jsp页面,可以直接使用ajax标签,不需要重新开发。
b)、表单同步提交,还是正常的struts流程。
2.2.3缺点
a)、表单项相关的标签需要重新修改。
修改量较大。
b)、一次载完数据的组件,从form中获取初始值。
但异步树、grid,还是需要异步取数。
一个页面中同步和异步都有,有些混乱。
c)、两种后台交易,struts交易和ajaxcommand交易同时存在。
3.0发展规划
长天科技集团
2009.7
1.全文检索的原理3
2.lucene4
2.1.lucene介绍4
2.2.Lucene的索引机制6
2.3.Lucene的查询和存储8
2.4.Lucene的工作流程9
3.Solr11
4.nutch12
4.1.Nutch介绍12
4.2.Nutch与Lucene14
4.3.架构14
5.Compass15
5.1.compass的特性15
5.1.1.简化O/R映射(ORM)的集成15
5.1.2.可搜索数据网格功能16
5.1.3.将Compass与Solr、Nutch和基础Lucene进行对比16
5.1.4.WhatSpringSideDone16
5.1.5.DataChangeMirror功能17
5.1.6.Compass下简化的索引建立过程17
6.中文分词21
6.1.什么是中文分词21
6.2.计算所汉语词法分析系统ICTCLAS21
6.3.海量智能分词研究版22
6.3.1.je_analysis22
1.全文检索的原理
全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一
个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。
这个过程类似于通过字典中的检索字表查字的过程。
全文检索的方法主要分为按字检索和按词检索两种。
按字检索是指对于文章中的每一个字都建立索引,检索时将词分解为字的组合。
对于各种不同的语言而言,字有不同的含义,比如英文中字与词实际上是合一的,而中文中字与词有很大分别。
按词检索指对文章中的词,即语义单位建立索引,检索时按词检索,并且可以处理同义项等。
英文等西方文字由于按照空白切分词,因此实现上与按字处理类似,添加同义处理也很容易。
中文等东方文字则需要切分字词,以达到按词索引的目的,关于这方面的问题,是当前全文检索技术尤其是中文全文检索技术中的难点,在此不做详述。
全文检索系统是按照全文检索理论建立起来的用于提供全文检索服务的软件系统。
一般来说,全文检索需要具备建立索引和提供查询的基本功能,此外现代的全文检索系统还需要具有方便的用户接口、面向WWW的开发接口、二次应用开发接口等等。
功能上,全文检索系统核心具有建立索引、处理查询返回结果集、增加索引、优化索引结构等等功能,外围则由各种不同应用具有的功能组成。
结构上,全文检索系统核心具有索引引擎、查询引擎、文本分析引擎、对外接口等等,加上各种外围应用系统等等共同构成了全文检索系统。
图3-1展示了上述全文检索系统的结构与功能。
在上图中,我们看到:
全文检索系统中最为关键的部分是全文检索引擎,各种应用程序都需要建立在这个引擎之上。
一个全文检索应用的优异程度,根本上由全文检索引擎来决定。
因此提升全文检索引擎的效率即是我们提升全文检索应用的根本。
另一个方面,一个优异的全文检索引擎,在做到效率优化的同时,还需要具有开放的体系结构,以方便程序员对整个系统进行优化改造,或者是添加原有系统没有的功能。
比如在当今多语言处理的环境下,有时需要给全文检索系统添加处理某种语言或者文本格式的功能,比如在英文系统中添加中文处理功能,在纯文本系统中添加XML或者HTML格式的文本处理功能,系统的开放性和扩充性就十分的重要。
2.lucene
lucene介绍
Lucene是apache软件基金会[4]jakarta项目组的一个子项目,是一个开放源代码[5]的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
Lucene的原作者是DougCutting,他是一位资深全文索引/检索专家,曾经是V-Twin搜索引擎[6]的主要开发者,后在Excite[7]担任高级系统架构设计师,目前从事于一些Internet底层架构的研究。
早先发布在作者自己的
Lucene是一个高性能、可伸缩的信息搜索(IR)库。
它使你可以为你的应用程序添加索引和搜索能力。
Lucene是用java实现的成熟的、免费的开源项目,是著名的ApacheJakarta大家庭的一员,并且基于在Apache软件许可[ASF,License]。
同样,Lucene是当前与近几年内非常流行的免费的Java信息搜索(IR)库。
Lucene作为一个全文检索引擎,其具有如下突出的优点:
(1)索引文件格式独立于应用平台。
Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
(2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。
然后通过与原有索引的合并,达到优化的目的。
(3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
(4)设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
(5)已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(FuzzySearch[11])、分组查询等等。
面对已经存在的商业全文检索引擎,Lucene也具有相当的优势。
首先,它的开发源代码发行方式(遵守ApacheSoftwareLicense[12]),在此基础上程序员不仅仅可以充分的利用Lucene所提供的强大功能,而且可以深入细致的学习到全文检索引擎制作技术和面相对象编程的实践,进而在此基础上根据应用的实际情况编写出更好的更适合当前应用的全文检索引擎。
在这一点上,商业软件的灵活性远远不及Lucene。
其次,Lucene秉承了开放源代码一贯的架构优良的优势,设计了一个合理而极具扩充能力的面向对象架构,程序员可以在Lucene的基础上扩充各种功能,比如扩充中文处理能力,从文本扩充到HTML、PDF[13]等等文本格式的处理,编写这些扩展的功能不仅仅不复杂,而且由于Lucene恰当合理的对系统设备做了程序上的抽象,扩展的功能也能轻易的达到跨平台的能力。
最后,转移到apache软件基金会后,借助于apache软件基金会的网络平台,程序员可以方便的和开发者、其它程序员交流,促成资源的共享,甚至直接获得已经编写完备的扩充功能。
最后,虽然Lucene使用Java语言写成,但是开放源代码社区的程序员正在不懈的将之使用各种传统语言实现(例如.netframework[14]),在遵守Lucene索引文件格式的基础上,使得Lucene能够运行在各种各样的平台上,系统管理员可以根据当前的平台适合的语言来合理的选择。
Lucene的索引机制
Lucene是apache软件基金会jakarta项目组的一个子项目,是一个开
放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构[6]。
该结构及相应的生成算法如下:
0)设有两篇文章1和2
文章1的内容为:
TomlivesinGuangzhou,IliveinGuangzhoutoo.文章2的内容为:
HeoncelivedinShanghai.
1)lucene是基于关键词索引和查询的,首先取得这两篇文章的关键词
a.现在有的是文章内容,即一个字符串,先要找出字符串中的所有单词,即分词。
英文单词由于用空格分隔,比较好处理。
中文单词间是连在一起的需要特殊的分词处理。
b.文章中的”in”,“once”“too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”e.文章中的标点符号通常不表示某种概念,也可以过滤掉
在lucene中以上措施由Analyzer类完成经过上面处理后文章1的所有关键词为:
[tom][live][guangzhou][i][live][guangzhou]文章2的所有关键词为:
[he][live][shanghai]
2)有了关键词后,可以建立倒排索引了。
上面的对应关系是:
“文章号”对“文章中所有关键词”。
倒排索引把这个关系倒过来,变成:
“关键词”对“拥有该关键词的所有文章号”。
文章1,2经过倒排后变成
关键词文章号
guangzhou1
he2
i1
live1,2
shanghai2
tom1
Lucene的索引还增加了有两种位置:
a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);
b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快)。
加上“出现频率”和“出现位置”信息后,索引结构变为:
关键词文章号[出现频率]出现位置
guangzhou1[2]3,6
he2[1]1
i1[1]4
live1[2],2[1]2,5,2
shanghai2[1]3
tom1[1]1
以live这行为例我说明一下该结构:
live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?
我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第2个关键字。
以上就是lucene索引结构中最核心的部分。
注意关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。
实现时lucene将上面三列分别作为词典文件(TermDictionary)、频率文件(frequencies)、位置文件(positions)保存。
其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。
为了减小索引文件的大小,Lucene对索引还使用了压缩技术。
首先,对词典文件中的关键词进行了压缩,关键词压缩为<
前缀长度,后缀>
,例如:
当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<
3,语>
。
其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。
例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,压缩后保存7(只用一个字节)。
Lucene的查询和存储
在Lucene中,如果需要使用搜索,需要使用Searcher类,这是一个抽象类,它有2个子类:
IndexSearcher和MultiSearcher.IndexSearcher是对一个索引进行搜索,如果你需要对多个索引进行搜索,可以使用MultiSearcher。
使用Search类,必然要有搜索的组合条件,搜索的条件可以组合的很复杂,相关的类有BooleanQuery,FilteredQuery,MultiTermQuery,PhrasePrefixQuery,PhraseQuery,PrefixQuery,RangeQuery,SpanQuery,TermQuery等等,从而可以组合出很复杂的条件用于查询.另外QueryParser可以根据用户输入的字符串和设定的解析器和字段设置等,可以自动产生新的组合条件用于查询,例如用户输入"
johnANDblack"
QueryParser可以自己分析出用户是需要查询字段中同时包含"
john"
和"
black"
的结果[6].
其次在Lucene中有时候根据具体的用户需求,有些记录对于一些用户是不可见的,此时就要使用过滤器来防止不合法的用户看到不应该看到的记录.过滤器同时也可以根据一些具体的条件来过滤掉一些用户不想看到的记录.如果需要实现自己的filter,只要参考QueryFilter,DateFilter实现Filter即可.
有时候,可能需要根据某个字段进行排序,例如按照时间排序.当然更多的时候是按照搜索结果的符合度进行排序,lucene默认的排序就是按照符合度来进行排序的.根据Lucene中的Sort实现。
Hits是lucene的搜索结果集类,通过类Search类搜索到的结果将保存在Hits中,通过相应的方法可以获得结果。
Lucene的工作流程
1使用IndexWriter,在指定的目录建立索引的文件。
2将需要检索的数据转换位Document的Filed对象,然后将Document用IndexWriter添加索引的文件中[6]。
3处理索引信息,关闭IndexWriter流。
4创建搜索的Query。
5给IndexSearcher指定索引文件的路径后,用Query检索后返回Hits对象作为结果。
样例代码:
//samplecode,索引对象
publicclassPersonInfo{
publicStringfirstName="
"
;
publicStringlastName="
publicStringIDNumber="
}
//Lucene的添加和更新索引
publicclassLuceneSearcher{
publicvoidaddPersionInfo(PersonInfoperson){
Documentdoc=newDocument();
doc.add(Field.Keyword("
FirstName"
person.getFirstName()));
IDNumber"
person.getIDNumber()));
LastName"
person.getLastName()));
doc.add(Field.Text("
content"
try{
//删除旧的相同的索引
this.remove(person.getIDNumber());
writer=newIndexWriter(directory,newStandardAnalyzer(),false);
writer.addDocument(doc);
writer.optimize();
writer.close();
catch(IOExceptionioe){
ioe.printStackTrace();
//删除旧的索引,idNumber作为Person的PK,建立term后删除
publicvoidremove(StringidNumber){
IndexReaderreader=IndexReader.open(directory);
Termterm=newTerm("
idNumber);
reader.delete(term);
reader.close();