之所以加上lucene来建立搜索引擎,是因为其轻便简单以及快速。Lucene作为开源社区很好的建立搜索引擎的框架也给我们(Java程序员)提供了很友好的方式。这次介绍的也是简单的整合,对于Lucene的一些复杂特性还请大家仔细阅读文档以及书籍或求助Google以及源码。
其实这篇博客早就要写了,只是最近遇到了非常纠结的事情,那就是要考一门我完全不会的课——计量经济学。都是模型,公式,觉得数学和经济学真的是一家人,而我和它们毫无缘分。今天公益劳动实验室的老师说搞技术的工作累,费心费脑,其实觉得也到差不多各行各业,都要承受压力,都要有自己的突破。。。God,跑题……
下面的示例是建立在前面几篇文章的基础上的。原来的项目代码可以在前几篇下载得到,就免去看那些罗嗦了。还是一步一步开始。
1)在数据库中建立内容字段。原来的User表中加入一个note字段就OK。因为我们要对这个字段的存储内容进行索引。有人说有数据库我可以直接搜索数据库啊,模糊查询是吧,效率不高吧,做一次IO和做一次数据库操作,还是模糊查询……当然先不考虑这么多,我们只是先借用DB的内容。到时候搜索的时候就完全操作文件了,数据库就不知道我们做了什么……
2)调整POJO,VO结构加入note属性。
3)建立索引。每次搜索不是全文搜索,我们要对需要被搜索的内容先建立索引,然后搜索会通过索引来查询内容。搜索的算法决定了效率。为了简便,就在JUNIT中试一下吧。不过首先我们要有个存储索引文件的路径以及一个分析器,分析器有很多种,这里选用按照词库检索的方式的分析器。当然搜索的时候也要用同样的分析器。这个后面说。准备代码如下:
@SuppressWarnings("unused")
private final String INDEXPATH = "g:\\userindex";
@SuppressWarnings("unused")
private Analyzer analyzer = new MMAnalyzer();
UserDao service;
上面的UserDao可以参看前几章,是需要通过Spring注入进来滴。然后看看我们的建立索引的代码:
@Test
public void createIndex() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
service = (UserDao) ctx.getBean("userDao");
List<User> list = service.getAllUsers();
ctx.destroy();
try
{
Directory directory = FSDirectory.getDirectory(INDEXPATH);
IndexWriter indexWriter = new IndexWriter(directory, analyzer ,true, IndexWriter.MaxFieldLength.LIMITED);
long begin = new Date().getTime();
for(User u: list)
{
Document doc = new Document();
String username = u.getUsername() == null ? "" : u.getUsername().trim();
String note = u.getNote() == null ? "" : u.getNote();
String company = u.getCompany() == null ? "" : u.getCompany();
doc.add(new Field("username", username, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
doc.add(new Field("note", note, Field.Store.COMPRESS, Field.Index.ANALYZED, Field.TermVector.NO));
doc.add(new Field("company", company, Field.Store.YES,Field.Index.NOT_ANALYZED,Field.TermVector.YES));
indexWriter.addDocument(doc);
}
long end = new Date().getTime();
System.out.println(">>> 1.存入索引完毕.. 共花费:" + (end - begin) +"毫秒...");
//优化,合并
indexWriter.optimize();
indexWriter.close();
}catch(Exception e){
e.printStackTrace();
}
}
4)写搜索方法。搜索方法我们返回User对象,当然是内存中的对象,我们没有填充所有的字段,取回对象只是为了在前段方便获取(因为我们用的AMF协议是建立在HTTP基础上通过序列化与反序列化传输对象的方式来进行远程访问的)。为了不造成困扰在此说明。先看下代码,代码放在了UserService类中,在前段可以直接调用,当然也是拜托Spring帮助我们来管理切面逻辑的类。方法代码如下:
public List<User> getUsersByQuery(String query) {
try {
List<User> qlist = new ArrayList<User>();
String fieldName1 = "username";
String fieldName2 = "note";
IndexSearcher indexSearcher = new IndexSearcher(INDEXPATH);
// QueryParser parser = new QueryParser(fieldName, analyzer); //单字
// key 搜索
// Query queryOBJ = parser.parse(query);
// System.out.println(">>> 2.开始读取索引... ... 通过关键字:【 " + query + " 】");
// long begin = new Date().getTime();
// 下面的是进行username,note两个范围内进行收索.
BooleanClause.Occur[] clauses = { BooleanClause.Occur.SHOULD,
BooleanClause.Occur.SHOULD };
Query queryOBJ = MultiFieldQueryParser.parse(query, new String[] {
"username","note"}, clauses, new MMAnalyzer());// parser.parse(query);
Filter filter = null;
// ################# 搜索相似度最高的记录 ###################
TopDocs topDocs = indexSearcher.search(queryOBJ, filter, 1000);
// TopDocs topDocs = indexSearcher.search(queryOBJ , 10000);
System.out.println("*** 共匹配:" + topDocs.totalHits + "个 ***");
User user = null;
// 输出结果--按分数计算
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
Document targetDoc = indexSearcher.doc(scoreDoc.doc);
user = new User();
// 设置高亮显示格式
// SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(
// "<font color='red'><strong>", "</strong></font>");
SimpleHTMLFormatter ff=new SimpleHTMLFormatter("<",">");
// /* 语法高亮显示设置 */
Highlighter highlighter = new Highlighter(ff,new QueryScorer(queryOBJ));
highlighter.setTextFragmenter(new SimpleFragmenter(100));
// 设置高亮 设置 username 字段
String username = targetDoc.get("username");
String note=targetDoc.get("note");
TokenStream titleTokenStream = analyzer.tokenStream(fieldName1,
new StringReader(username));
String highLightName = highlighter.getBestFragment(
titleTokenStream, username);
TokenStream noteTokenStream = analyzer.tokenStream(fieldName2,
new StringReader(note));
String highLightNote = highlighter.getBestFragment(
noteTokenStream, note);
//
if (highLightName == null)
highLightName = username;
if(highLightNote == null)
highLightNote = note;
user.setUsername(highLightName);
user.setNote(highLightNote);
qlist.add(user);
}
// long end = new Date().getTime();
// System.out.println(">>> 3.搜索完毕... ... 共花费:" + (end - begin)
// + "毫秒...");
indexSearcher.close();
return qlist;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
具体的lucene API就不多做解释了。因为我们用Flex做前端所以高亮器就没有设置。对于jsp还是可以应用的,所以代码注释掉了。我们可以看到MultiFieldQueryParser构造器中传入了我们建立索引时候的MMAnalyzer分析器,如前所说,他们是要一样的。就像序列化与反序列化,他们要遵循同样的规则一样。要不搜索的时候那抱歉了,我(Query)只认识MMAnalyzer分词后的索引啦。
5)前端调用。这个和前面没什么差别了。还是要RPC对象。spritis.mxml文件的RPC配置RemoteObject只要添加一个方法如下:
<mx:method name="getUsersByQuery" result="getUsersByQuery_resultHandler(event)">
<mx:arguments>
<arg1> {query.text}</arg1>
</mx:arguments>
</mx:method>
同样AS代码对于result事件的响应代码如下:
private function getUsersByQuery_resultHandler(event:ResultEvent):void
{
users = event.result as ArrayCollection;
}
接下来mxml语言发挥作用,直接调用UserService的搜索方法就好啦:
<mx:HBox fontSize="13">
<mx:Button label="Search Users:" click="user.getUsersByQuery(query.text)"/>
<mx:TextInput id="query" width="100"/>
</mx:HBox>
注意到了click事件响应的东西是神马了吗,就是我们的远程服务器端方法名,传入参数是我们用户在TextInput 控件中输入的东西。
6)运行,测试。下面的工作就是启动Tomcat,这只可爱的小猫咪,然后在搜索的输入框输入“麻花”二字,毫无悬念地,我们会在DataGrid控件中看到检索出的东西,只是作为内存中的User对象输出,而非数据库中的啦。简单看一下运行后的结果图吧,比较粗糙,情有审美眼光的童鞋谅解……我最怕写前端了。
可以看到关键字麻花被括起来了,那是高亮器,简易版本的。因为麻花是一个词典中的词,所以被搜索出来了,如果输入“麻”就没有结果了,因为我们采用的是MM词典分词。当然lucene有很多种分词器,也可以写自己的分析器,过滤器(像百度之类的),还可以写自己的结果排序规则(像百度广告在前面显示)。这里不详述了,只做简单介绍。
写到这里我还是很迷茫,因为明天要考计量经济学,我很佩服研究出那些模型的老外。看来还是兴趣为先驱,坚持是硬道理。现在听到了SHE的《爱就对了》,其实敲代码和恋爱都是一样的也许,都要承受一定的痛苦期,坚持,专心,过程中也会有磕磕绊绊,但是每次都克服过来,都会有很好的结果的。好吧,敲就对了……
最后,老规矩不变,给所有可爱的猿类们一个轻松的小笑话(这个笑话有点长请大家坚持,,,):
某日,老师在课堂上想考考学生们的智商,就问一个男孩: “树上有十只鸟,开枪打死一只,还剩几只?”
男孩反问:“是无声的枪,还是其他没有声音的枪么?”
“不是.”
“枪声有多大?”
“80~100分贝.”
“那就是说会震的耳朵疼?”
“是.”
“在这个城市里打鸟犯不犯法?”
‘不犯.”
“您确定那只鸟真的被打死啦?”
“确定.”老师已经不耐烦了,”拜托,你告诉我还剩几只就行了,OK?”
“OK.鸟里有没有聋子?”
“没有.”
“有没有鸟智力有问题,呆傻到听到枪响不知道飞的?”
“没有,智商都在200以上!”
“有没有关在笼子里的?”
“没有.”
“边上还有没有其他的树,树上还有没有其他鸟?”
“没有.” “方圆十里呢?” “就这么一棵树!”
“有没有残疾或饿的飞不动的鸟?”
“没有,都身体倍棒.”
“算不算怀孕肚子里的小鸟?”
“都是公的.”
“都不可能怀孕?”
“………,决不可能.”
“打鸟的人眼里有没有花?保证是十只?”
“没有花,就十只.” 老师脑门上的汗已经流下来了,
下课铃响起,但男孩仍继续问:“有没有傻的不怕死的?”
“都怕死.”
“有没有因为情侣被打中,自己留下来的?”
“笨蛋,之前不是说都是公的嘛!”
“同志可不可以啊!”
“………….,性取向都很正常!”
“会不会一枪打死两只?”
“不会.”
“一枪打死三只呢?”
“不会.”
“四只呢?”
“更不会!”
“五只呢?”
“绝对不会!!!”
“那六只总有可能吧?”
“除非你他妈的是猪生的才有可能!一枪只能打死一只!”
“…好吧,那么所有的鸟都可以自由活动么?”
“完全可以.”
“它们受到惊吓起飞时会不会惊慌失措而互相撞上?”
“不会,每只鸟都装有卫星导航系统,而且可以自动飞行.”
“恩,如果您的回答没有骗人,”学生满怀信心的回答,“打死的鸟要是挂在树上没掉下来,那么就剩一只,如果掉下来,就一只不剩.”
老师推推眼镜,强忍着要昏倒的感觉,颤抖地说道:“你可以去当程序员了……”
- 大小: 135 KB
分享到:
相关推荐
标题中的“iBATIS&Spring合奏(一)--DAO”指的是在Java开发中,将iBATIS和Spring框架结合使用来实现数据访问层(DAO)的一种技术整合。iBATIS是一个优秀的持久层框架,它允许开发者将SQL语句直接写在配置文件中,提供...
在本篇博文中,我们将探讨如何将iBATIS与Spring框架进行整合,以实现更高效、灵活的前端开发。在“iBATIS&Spring合奏(二)--Flex前端融合”中,博主Yunshen0909分享了关于如何在Java Web应用中结合使用这两种技术,...
spring,struts,hibernate,ibatis,框架源码 各种ibatis框架应用源码,你会从中得到意想不到的效果! apache开源组织开发的开源项目源码,其优良的代码风格和高质量的源码是学习者难得的学习资料!
《MyBatis-Spring整合详解及1.0.2版本剖析》 MyBatis-Spring是MyBatis和Spring框架的集成库,旨在简化在Spring应用中使用MyBatis的过程,实现两者的无缝连接。本篇文章将深入探讨MyBatis-Spring的核心功能,以及...
ibatis-3-core-3.0.0.242.jar.zipibatis-3-core-3.0.0.242.jar.zipibatis-3-core-3.0.0.242.jar.zipibatis-3-core-3.0.0.242.jar.zipibatis-3-core-3.0.0.242.jar.zip
ibatis-3-core-3.0.0.242.zip ibatis-3-core-3.0.0.242.zip ibatis-3-core-3.0.0.242.zip ibatis-3-core-3.0.0.242.zip
ibatis-3-core-3.0.0.200
iBatis和Spring整合 iBatis和Spring整合
### ibatis与Spring框架整合详解 #### 一、ibatis简介 ibatis是一个开源的、基于Java的持久层框架,它提供了SQL映射的方式来进行数据库访问。与Hibernate等其他ORM框架相比,ibatis更加轻量级,对于那些只需要简单...
flex 整合 spring+struts2+ibatis - 乐的日志 - 网易博客.htm flex 整合 spring+struts2+ibatis - 乐的日志 - 网易博客.htm
iBATIS-SqlMaps-2-Tutorial_cniBATIS-SqlMaps-2-Tutorial_cn.pdf.pdfiBATIS-SqlMaps-2-Tutorial_cn.pdfiBATIS-SqlMaps-2-Tutorial_cn.pdf
Struts 2 与 Spring 的整合提供了更强大的功能,例如利用 Spring 的 DI 来管理 Struts 2 的动作类,以及事务管理。 **IBatis 框架** IBatis 是一个持久层框架,它将 SQL 查询与 Java 代码分离,允许开发者编写 SQL...
亲测可用,资源下载到磁盘,然后打开myeclipse 路径为:Windows ---> Perferences --> MyEclipse -->Servers -->Tomcat -->...-Drebel.ibatis-plugin--------热部署ibatis相关的jar
myeclipse 插件热部署 jrebel6.5 亲测可用,资源下载到磁盘,然后打开myeclipse 路径为:Windows ---> Perferences --> MyEclipse -->...-Drebel.ibatis-plugin--------热部署ibatis相关的jar
Ibatis基本配置---[环境搭建
在Java Web开发中,Spring和iBatis是两个非常重要的框架。Spring是一个全面的后端开发框架,提供了依赖注入、AOP(面向切面编程)、事务管理等特性,而iBatis则是一个优秀的持久层框架,它将SQL语句与Java代码分离,...
jbpm4.4 ibatis-spring 整合
Spring 3.2 与 iBatis 的整合是Java企业级开发中常见的一种技术组合,它结合了Spring的依赖注入和事务管理能力以及iBatis的SQL映射框架的灵活性。这种整合允许开发者将业务逻辑与数据访问层解耦,提高了代码的可维护...
总结起来,"ibatis-3-core-3.0.0.227.z"压缩包提供的内容涵盖了iBatis的核心库、源码、授权信息和元数据,是学习和使用iBatis不可或缺的资源。通过对这些内容的深入理解和实践,开发者可以更好地掌握数据库操作的...
"Ibatis 与 Spring3 整合"这一主题,涉及到的是两个知名Java框架——Ibatis(一个轻量级的持久层框架)和Spring(一个全面的企业级应用框架)的协同工作。下面我们将深入探讨这一整合过程中的关键知识点。 Ibatis ...