`
lijingyao8206
  • 浏览: 219291 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

iBATIS&Spring合奏(五)--整合lucene搜索表字段内容

阅读更多
     之所以加上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
分享到:
评论
2 楼 lijingyao8206 2010-12-27  
wuzhen 写道
不错,这年头能静心钻研技术的太少了……女孩子就更少了,像楼主致敬

    不算钻研啦~只是在学校时间比较多的时候学点东西~呵呵~
1 楼 wuzhen 2010-12-27  
不错,这年头能静心钻研技术的太少了……女孩子就更少了,像楼主致敬

相关推荐

    iBATIS&Spring合奏(一)--DAO

    标题中的“iBATIS&Spring合奏(一)--DAO”指的是在Java开发中,将iBATIS和Spring框架结合使用来实现数据访问层(DAO)的一种技术整合。iBATIS是一个优秀的持久层框架,它允许开发者将SQL语句直接写在配置文件中,提供...

    iBATIS&Spring合奏(二)--Flex前端融合

    在本篇博文中,我们将探讨如何将iBATIS与Spring框架进行整合,以实现更高效、灵活的前端开发。在“iBATIS&Spring合奏(二)--Flex前端融合”中,博主Yunshen0909分享了关于如何在Java Web应用中结合使用这两种技术,...

    apache开源项目源码ibatis-3-core-src-3.0.0.227(ibatis框架java源程序)

    spring,struts,hibernate,ibatis,框架源码 各种ibatis框架应用源码,你会从中得到意想不到的效果! apache开源组织开发的开源项目源码,其优良的代码风格和高质量的源码是学习者难得的学习资料!

    mybaits-spring(ibatis-spring)-1.0.2-bundle

    《MyBatis-Spring整合详解及1.0.2版本剖析》 MyBatis-Spring是MyBatis和Spring框架的集成库,旨在简化在Spring应用中使用MyBatis的过程,实现两者的无缝连接。本篇文章将深入探讨MyBatis-Spring的核心功能,以及...

    ibatis-3-core-3.0.0.242.jar.zip

    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.242.zip

    ibatis-3-core-3.0.0.200

    ibatis-3-core-3.0.0.200

    iBatis和Spring整合

    iBatis和Spring整合 iBatis和Spring整合

    ibatis与spring整合

    ### ibatis与Spring框架整合详解 #### 一、ibatis简介 ibatis是一个开源的、基于Java的持久层框架,它提供了SQL映射的方式来进行数据库访问。与Hibernate等其他ORM框架相比,ibatis更加轻量级,对于那些只需要简单...

    flex 整合 spring+struts2+ibatis - 乐的日志 - 网易博客.htm

    flex 整合 spring+struts2+ibatis - 乐的日志 - 网易博客.htm flex 整合 spring+struts2+ibatis - 乐的日志 - 网易博客.htm

    iBATIS-SqlMaps-2-Tutorial_cn.pdf

    iBATIS-SqlMaps-2-Tutorial_cniBATIS-SqlMaps-2-Tutorial_cn.pdf.pdfiBATIS-SqlMaps-2-Tutorial_cn.pdfiBATIS-SqlMaps-2-Tutorial_cn.pdf

    Spring-Struts-IBatis-AOP-Transaction

    Struts 2 与 Spring 的整合提供了更强大的功能,例如利用 Spring 的 DI 来管理 Struts 2 的动作类,以及事务管理。 **IBatis 框架** IBatis 是一个持久层框架,它将 SQL 查询与 Java 代码分离,允许开发者编写 SQL...

    myeclipse热部署jrebel6.5.0

    亲测可用,资源下载到磁盘,然后打开myeclipse 路径为:Windows ---&gt; Perferences --&gt; MyEclipse --&gt;Servers --&gt;Tomcat --&gt;...-Drebel.ibatis-plugin--------热部署ibatis相关的jar

    myeclipse 插件热部署 jrebel6.5

    myeclipse 插件热部署 jrebel6.5 亲测可用,资源下载到磁盘,然后打开myeclipse 路径为:Windows ---&gt; Perferences --&gt; MyEclipse --&gt;...-Drebel.ibatis-plugin--------热部署ibatis相关的jar

    Ibatis基本配置---[环境搭建

    Ibatis基本配置---[环境搭建

    spring ibatis整合所需jar包

    在Java Web开发中,Spring和iBatis是两个非常重要的框架。Spring是一个全面的后端开发框架,提供了依赖注入、AOP(面向切面编程)、事务管理等特性,而iBatis则是一个优秀的持久层框架,它将SQL语句与Java代码分离,...

    jbpm4.4 ibatis-spring 整合

    jbpm4.4 ibatis-spring 整合

    spring3.2与Ibatis整合

    Spring 3.2 与 iBatis 的整合是Java企业级开发中常见的一种技术组合,它结合了Spring的依赖注入和事务管理能力以及iBatis的SQL映射框架的灵活性。这种整合允许开发者将业务逻辑与数据访问层解耦,提高了代码的可维护...

    ibatis-3-core-3.0.0.227.z

    总结起来,"ibatis-3-core-3.0.0.227.z"压缩包提供的内容涵盖了iBatis的核心库、源码、授权信息和元数据,是学习和使用iBatis不可或缺的资源。通过对这些内容的深入理解和实践,开发者可以更好地掌握数据库操作的...

    ibatis 与spring3整合

    "Ibatis 与 Spring3 整合"这一主题,涉及到的是两个知名Java框架——Ibatis(一个轻量级的持久层框架)和Spring(一个全面的企业级应用框架)的协同工作。下面我们将深入探讨这一整合过程中的关键知识点。 Ibatis ...

Global site tag (gtag.js) - Google Analytics