利用 Lucene 实现高级搜索功能.docx
- 文档编号:10553826
- 上传时间:2023-02-21
- 格式:DOCX
- 页数:25
- 大小:551.70KB
利用 Lucene 实现高级搜索功能.docx
《利用 Lucene 实现高级搜索功能.docx》由会员分享,可在线阅读,更多相关《利用 Lucene 实现高级搜索功能.docx(25页珍藏版)》请在冰豆网上搜索。
利用Lucene实现高级搜索功能
Lucene是基于Java的全文信息检索包,它目前是ApacheJakarta家族下面的一个开源项目。
在这篇文章中,我们首先来看如何利用Lucene实现高级搜索功能,然后学习如何利用Lucene来创建一个健壮的Web搜索应用程序。
在本篇文章中,你会学习到如何利用Lucene实现高级搜索功能以及如何利用Lucene来创建Web搜索应用程序。
通过这些学习,你就可以利用Lucene来创建自己的搜索应用程序。
架构概览
通常一个Web搜索引擎的架构分为前端和后端两部分,就像图一中所示。
在前端流程中,用户在搜索引擎提供的界面中输入要搜索的关键词,这里提到的用户界面一般是一个带有输入框的Web页面,然后应用程序将搜索的关键词解析成搜索引擎可以理解的形式,并在索引文件上进行搜索操作。
在排序后,搜索引擎返回搜索结果给用户。
在后端流程中,网络爬虫或者机器人从因特网上获取Web页面,然后索引子系统解析这些Web页面并存入索引文件中。
如果你想利用Lucene来创建一个Web搜索应用程序,那么它的架构也和上面所描述的类似,就如图一中所示。
Figure1.Web搜索引擎架构
利用Lucene实现高级搜索
Lucene支持多种形式的高级搜索,我们在这一部分中会进行探讨,然后我会使用Lucene的API来演示如何实现这些高级搜索功能。
布尔操作符
大多数的搜索引擎都会提供布尔操作符让用户可以组合查询,典型的布尔操作符有AND,OR,NOT。
Lucene支持5种布尔操作符,分别是AND,OR,NOT,加(+),减(-)。
接下来我会讲述每个操作符的用法。
∙OR:
如果你要搜索含有字符A或者B的文档,那么就需要使用OR操作符。
需要记住的是,如果你只是简单的用空格将两个关键词分割开,其实在搜索的时候搜索引擎会自动在两个关键词之间加上OR操作符。
例如,“JavaORLucene”和“JavaLucene”都是搜索含有Java或者含有Lucene的文档。
∙AND:
如果你需要搜索包含一个以上关键词的文档,那么就需要使用AND操作符。
例如,“JavaANDLucene”返回所有既包含Java又包含Lucene的文档。
∙NOT:
Not操作符使得包含紧跟在NOT后面的关键词的文档不会被返回。
例如,如果你想搜索所有含有Java但不含有Lucene的文档,你可以使用查询语句“JavaNOTLucene”。
但是你不能只对一个搜索词使用这个操作符,比如,查询语句“NOTJava”不会返回任何结果。
∙加号(+):
这个操作符的作用和AND差不多,但它只对紧跟着它的一个搜索词起作用。
例如,如果你想搜索一定包含Java,但不一定包含Lucene的文档,就可以使用查询语句“+JavaLucene”。
∙减号(-):
这个操作符的功能和NOT一样,查询语句“Java-Lucene”返回所有包含Java但不包含Lucene的文档。
接下来我们看一下如何利用Lucene提供的API来实现布尔查询。
清单1显示了如果利用布尔操作符进行查询的过程。
清单1:
使用布尔操作符
//Testbooleanoperator
publicvoidtestOperator(StringindexDirectory)throwsException{
Directorydir=FSDirectory.getDirectory(indexDirectory,false);
IndexSearcherindexSearcher=newIndexSearcher(dir);
String[]searchWords={"JavaANDLucene","JavaNOTLucene","JavaORLucene",
"+Java+Lucene","+Java-Lucene"};
Analyzerlanguage=newStandardAnalyzer();
Queryquery;
for(inti=0;i query=QueryParser.parse(searchWords[i],"title",language); Hitsresults=indexSearcher.search(query); System.out.println(results.length()+"searchresultsforquery"+searchWords[i]); } } 域搜索(FieldSearch) Lucene支持域搜索,你可以指定一次查询是在哪些域(Field)上进行。 例如,如果索引的文档包含两个域,Title和Content,你就可以使用查询“Title: LuceneANDContent: Java”来返回所有在Title域上包含Lucene并且在Content域上包含Java的文档。 清单2显示了如何利用Lucene的API来实现域搜索。 清单2: 实现域搜索 //Testfieldsearch publicvoidtestFieldSearch(StringindexDirectory)throwsException{ Directorydir=FSDirectory.getDirectory(indexDirectory,false); IndexSearcherindexSearcher=newIndexSearcher(dir); StringsearchWords="title: LuceneANDcontent: Java"; Analyzerlanguage=newStandardAnalyzer(); Queryquery=QueryParser.parse(searchWords,"title",language); Hitsresults=indexSearcher.search(query); System.out.println(results.length()+"searchresultsforquery"+searchWords); } 通配符搜索(WildcardSearch) Lucene支持两种通配符: 问号(? )和星号(*)。 你可以使用问号(? )来进行单字符的通配符查询,或者利用星号(*)进行多字符的通配符查询。 例如,如果你想搜索tiny或者tony,你就可以使用查询语句“t? ny”;如果你想查询Teach,Teacher和Teaching,你就可以使用查询语句“Teach*”。 清单3显示了通配符查询的过程。 清单3: 进行通配符查询 //Testwildcardsearch publicvoidtestWildcardSearch(StringindexDirectory)throwsException{ Directorydir=FSDirectory.getDirectory(indexDirectory,false); IndexSearcherindexSearcher=newIndexSearcher(dir); String[]searchWords={"tex*","tex? ","? ex*"}; Queryquery; for(inti=0;i query=newWildcardQuery(newTerm("title",searchWords[i])); Hitsresults=indexSearcher.search(query); System.out.println(results.length()+"searchresultsforquery"+searchWords[i]); } } 模糊查询 Lucene提供的模糊查询基于编辑距离算法(Editdistancealgorithm)。 你可以在搜索词的尾部加上字符~来进行模糊查询。 例如,查询语句“think~”返回所有包含和think类似的关键词的文档。 清单4显示了如果利用Lucene的API进行模糊查询的代码。 清单4: 实现模糊查询 //Testfuzzysearch publicvoidtestFuzzySearch(StringindexDirectory)throwsException{ Directorydir=FSDirectory.getDirectory(indexDirectory,false); IndexSearcherindexSearcher=newIndexSearcher(dir); String[]searchWords={"text","funny"}; Queryquery; for(inti=0;i query=newFuzzyQuery(newTerm("title",searchWords[i])); Hitsresults=indexSearcher.search(query); System.out.println(results.length()+"searchresultsforquery"+searchWords[i]); } } 范围搜索(RangeSearch) 范围搜索匹配某个域上的值在一定范围的文档。 例如,查询“age: [18TO35]”返回所有age域上的值在18到35之间的文档。 清单5显示了利用Lucene的API进行返回搜索的过程。 清单5: 测试范围搜索 //Testrangesearch publicvoidtestRangeSearch(StringindexDirectory)throwsException{ Directorydir=FSDirectory.getDirectory(indexDirectory,false); IndexSearcherindexSearcher=newIndexSearcher(dir); Termbegin=newTerm("birthDay","20000101"); Termend=newTerm("birthDay","20060606"); Queryquery=newRangeQuery(begin,end,true); Hitsresults=indexSearcher.search(query); System.out.println(results.length()+"searchresultsisreturned"); } 回页首 在Web应用程序中集成Lucene 接下来我们开发一个Web应用程序利用Lucene来检索存放在文件服务器上的HTML文档。 在开始之前,需要准备如下环境: 1.Eclipse集成开发环境 2.Tomcat5.0 3.LuceneLibrary 4.JDK1.5 这个例子使用Eclipse进行Web应用程序的开发,最终这个Web应用程序跑在Tomcat5.0上面。 在准备好开发所必需的环境之后,我们接下来进行Web应用程序的开发。 1、创建一个动态Web项目 1.在Eclipse里面,选择File>New>Project,然后再弹出的窗口中选择动态Web项目,如图二所示。 图二: 创建动态Web项目 2.在创建好动态Web项目之后,你会看到创建好的项目的结构,如图三所示,项目的名称为sample.dw.paper.lucene。 图三: 动态Web项目的结构 2.设计Web项目的架构 在我们的设计中,把该系统分成如下四个子系统: 1.用户接口: 这个子系统提供用户界面使用户可以向Web应用程序服务器提交搜索请求,然后搜索结果通过用户接口来显示出来。 我们用一个名为search.jsp的页面来实现该子系统。 2.请求管理器: 这个子系统管理从客户端发送过来的搜索请求并把搜索请求分发到搜索子系统中。 最后搜索结果从搜索子系统返回并最终发送到用户接口子系统。 我们使用一个Servlet来实现这个子系统。 3.搜索子系统: 这个子系统负责在索引文件上进行搜索并把搜索结构传递给请求管理器。 我们使用Lucene提供的API来实现该子系统。 4.索引子系统: 这个子系统用来为HTML页面来创建索引。 我们使用Lucene的API以及Lucene提供的一个HTML解析器来创建该子系统。 图4显示了我们设计的详细信息,我们将用户接口子系统放到webContent目录下面。 你会看到一个名为search.jsp的页面在这个文件夹里面。 请求管理子系统在包sample.dw.paper.lucene.servlet下面,类SearchController负责功能的实现。 搜索子系统放在包sample.dw.paper.lucene.search当中,它包含了两个类,SearchManager和SearchResultBean,第一个类用来实现搜索功能,第二个类用来描述搜索结果的结构。 索引子系统放在包sample.dw.paper.lucene.index当中。 类IndexManager负责为HTML文件创建索引。 该子系统利用包sample.dw.paper.lucene.util里面的类HTMLDocParser提供的方法getTitle和getContent来对HTML页面进行解析。 图四: 项目的架构设计 3.子系统的实现 在分析了系统的架构设计之后,我们接下来看系统实现的详细信息。 1.用户接口: 这个子系统有一个名为search.jsp的JSP文件来实现,这个JSP页面包含两个部分。 第一部分提供了一个用户接口去向Web应用程序服务器提交搜索请求,如图5所示。 注意到这里的搜索请求发送到了一个名为SearchController的Servlet上面。 Servlet的名字和具体实现的类的对应关系在web.xml里面指定。 图5: 向Web服务器提交搜索请求 这个JSP的第二部分负责显示搜索结果给用户,如图6所示: 图6: 显示搜索结果 2.请求管理器: 一个名为SearchController的servlet用来实现该子系统。 清单6给出了这个类的源代码。 清单6: 请求管理器的实现 packagesample.dw.paper.lucene.servlet; importjava.io.IOException; importjava.util.List; importjavax.servlet.RequestDispatcher; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importsample.dw.paper.lucene.search.SearchManager; /** *Thisservletisusedtodealwiththesearchrequest *andreturnthesearchresultstotheclient */ publicclassSearchControllerextendsHttpServlet{ privatestaticfinallongserialVersionUID=1L; publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse) throwsIOException,ServletException{ StringsearchWord=request.getParameter("searchWord"); SearchManagersearchManager=newSearchManager(searchWord); ListsearchResult=null; searchResult=searchManager.search(); RequestDispatcherdispatcher=request.getRequestDispatcher("search.jsp"); request.setAttribute("searchResult",searchResult); dispatcher.forward(request,response); } publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsIOException,ServletException{ doPost(request,response); } } 在清单6中,doPost方法从客户端获取搜索词并创建类SearchManager的一个实例,其中类SearchManager在搜索子系统中进行了定义。 然后,SearchManager的方法search会被调用。 最后搜索结果被返回到客户端。 3.搜索子系统: 在这个子系统中,我们定义了两个类: SearchManager和SearchResultBean。 第一个类用来实现搜索功能,第二个类是个JavaBean,用来描述搜索结果的结构。 清单7给出了类SearchManager的源代码。 清单7: 搜索功能的实现 packagesample.dw.paper.lucene.search; importjava.io.IOException; importjava.util.ArrayList; importjava.util.List; importorg.apache.lucene.analysis.Analyzer; importorg.apache.lucene.analysis.standard.StandardAnalyzer; importorg.apache.lucene.queryParser.ParseException; importorg.apache.lucene.queryParser.QueryParser; importorg.apache.lucene.search.Hits; importorg.apache.lucene.search.IndexSearcher; importorg.apache.lucene.search.Query; importsample.dw.paper.lucene.index.IndexManager; /** *Thisclassisusedtosearchthe *Luceneindexandreturnsearchresults */ publicclassSearchManager{ privateStringsearchWord; privateIndexManagerindexManager; privateAnalyzeranalyzer; publicSearchManager(StringsearchWord){ this.searchWord=searchWord; this.indexManager=newIndexManager(); this.analyzer=newStandardAnalyzer(); } /** *dosearch */ publicListsearch(){ ListsearchResult=newArrayList(); if(false==indexManager.ifIndexExist()){ try{ if(false==indexManager.createIndex()){ returnsearchResult; } }catch(IOExceptione){ e.printStackTrace(); returnsearchResult; } } IndexSearcherindexSearcher=null; try{ indexSearcher=newIndexSearcher(indexManager.getIndexDir()); }catch(IOExceptionioe){ ioe.printStackTrace(); } QueryParserqueryParser=newQueryParser("content",analyzer); Queryquery=null; try{ query=queryParser.parse(searchWord); }catch(ParseExceptione){ e.printStackTrace(); } if(null! =query>>null! =indexSearcher){ try{ Hitshits=indexSearcher.search(query); for(inti=0;i SearchResultBeanresultBean=newSearchResultBean(); resultBean.setHtmlPath(hits.doc(i).get("path")); resultBean.setHtmlTitle(hits.doc(i).get("title")); searchResult.add(resultBean); } }catch(IOExceptione
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 Lucene 实现高级搜索功能 实现 高级 搜索 功能
![提示](https://static.bdocx.com/images/bang_tan.gif)