`
yangjizhong24
  • 浏览: 399104 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring框架下配置lucene

阅读更多

最近这的是投入不少精力在lucene身上,学到一点心得,留此文章以作纪念。一个目的是分享给大家,另一个目的是将来再用的时候再看看自己的文章能少走些路,好啦,开始正文。



lucene特点及作用文章里就不说了,网上有的是。我就简单说下个人理解,

正常 sql 查询时:name like '%继中%' 想必大家一定明白这样不会走索引的,然后就在多行数据级别查询相应时间会很慢,对吧,因为数据库在一行行扫呢。所以我们自然会想到怎样能让它走索引?

解决方案之一:lucene出来了。

其实它就是帮你把文章拆分成若干个关键词,这样以便按关键词查询时能通过关键词直接查询来锁定哪些文章匹配该关键词并快速返回。说再直白点,就是 sql语句的查询不用like ,而是 name ='继中',这样就走索引了,所以就快了而已。





下面来说正题,spring框架下配置lucene,lucene版本:3.0.3,直接上代码,通过代码我来分享下各行的作用




mvc-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-3.0.xsd"
		default-autowire="byName" >
		
		
	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="messageConverters">
			<list>
				<bean class = "org.springframework.http.converter.StringHttpMessageConverter"> 
					<property name = "supportedMediaTypes"> 
						<list><value>text/plain;charset=UTF-8</value></list>
					</property>
				</bean>
			</list>
		</property>
	</bean>
	<context:component-scan base-package="com.jizhong" />
	<mvc:annotation-driven/>
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
	
	<!-- LUCENE SEARCH CONFIG -->
	<!-- 设置字段内容长度,这里不做限定   -->
	<bean id="MAXFIELDLENGTH2" class="org.apache.lucene.index.IndexWriter.MaxFieldLength.UNLIMITED" />
	<!-- set your analyzer, to be used by the IndexWriter and QueryParser ,关于分词器,因为我们主要进行中文搜索,所以要选择好点的中文分词器,我选择了paoding-->
	<bean id="luceneAnalyzer" class="net.paoding.analysis.analyzer.PaodingAnalyzer">
	</bean> 
	
	<!-- set your Lucene directory -->
	<!-- in this case I am pulling the location from a properties file -->
	<!-- also, using the SimpleFSLockFactory ,数据文件存放位置设置-->
	<bean id="luceneDirectory" class="org.apache.lucene.store.SimpleFSDirectory" >   
		<constructor-arg>     
			<bean class="java.io.File">       
				<constructor-arg value="D:\\common\\hahaha" />     
			</bean>   
		</constructor-arg>   
	</bean> 
	
 	<!-- now you're ready to define the IndexWriter,这里创建 IndexWriter并引入相关bean-->
	<bean id="indexWriter" class="org.apache.lucene.index.IndexWriter">   
		<constructor-arg ref="luceneDirectory" />
		<constructor-arg ref="luceneAnalyzer" />
		<constructor-arg name="create" value="false" />
		<constructor-arg ref="MAXFIELDLENGTH2" />
	</bean>  
	
	<!-- define the IndexSearcher ,这里创建IndexSearcher-->
   <bean id="indexSearcher" class="org.apache.lucene.search.IndexSearcher">
      <constructor-arg ref="luceneDirectory" />
   </bean> 
 
   
</beans>

 

以上是spring配置文件中关于lucene的代码片段,看起来是不是很简单?





我们继续看代码


package com.jizhong.mmmmm.controller; 

import java.io.IOException; 
import java.io.StringReader; 

import javax.servlet.http.HttpServletRequest; 

import org.apache.log4j.Logger; 
import org.apache.lucene.analysis.Analyzer; 
import org.apache.lucene.analysis.TokenStream; 
import org.apache.lucene.analysis.tokenattributes.TermAttribute; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.document.Field.Index; 
import org.apache.lucene.document.Field.Store; 
import org.apache.lucene.document.NumericField; 
import org.apache.lucene.index.CorruptIndexException; 
import org.apache.lucene.index.IndexReader; 
import org.apache.lucene.index.IndexWriter; 
import org.apache.lucene.index.Term; 
import org.apache.lucene.queryParser.MultiFieldQueryParser; 
import org.apache.lucene.queryParser.ParseException; 
import org.apache.lucene.queryParser.QueryParser; 
import org.apache.lucene.search.BooleanClause; 
import org.apache.lucene.search.BooleanQuery; 
import org.apache.lucene.search.IndexSearcher; 
import org.apache.lucene.search.Query; 
import org.apache.lucene.search.ScoreDoc; 
import org.apache.lucene.search.Sort; 
import org.apache.lucene.search.SortField; 
import org.apache.lucene.search.TopDocs; 
import org.apache.lucene.util.Version; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.ModelMap; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

@Controller 
public class LuceneController { 

private static Logger logger = Logger.getLogger(LuceneController.class); 

@Autowired(required = false)//这里我写了required = false,需要时再引入,不写的话会报错,大家有更好解决方案请留言哈 
private Analyzer myAnalyzer; 
@Autowired(required = false) 
private IndexWriter indexWriter; 
@Autowired(required = false) 
private IndexSearcher searcher; 

@RequestMapping(value = "search.do", method = RequestMethod.GET) 
public String testsSearch(HttpServletRequest request, ModelMap modelMap) throws Exception { 
search(); 
return "test"; 
} 

@RequestMapping(value = "idSearch.do", method = RequestMethod.GET) 
public String idSearch(HttpServletRequest request, ModelMap modelMap) throws Exception { 
idSearch(); 
return "test"; 
} 

@RequestMapping(value = "moreSearch.do", method = RequestMethod.GET) 
public String moreSearch(HttpServletRequest request, ModelMap modelMap) throws Exception { 
searchMore(); 
return "test"; 
} 

@RequestMapping(value = "create.do", method = RequestMethod.GET) 
public String testsCreate(HttpServletRequest request, ModelMap modelMap) throws Exception { 
create("整形值添加"); 
// create(request.getParameter("name")); 
return "test"; 
} 

@RequestMapping(value = "delete.do", method = RequestMethod.GET) 
public String delete(HttpServletRequest request, ModelMap modelMap) throws Exception { 
delete("id", request.getParameter("id")); 
return "test"; 
} 

@RequestMapping(value = "optimize.do", method = RequestMethod.GET) 
public String optimize(HttpServletRequest request, ModelMap modelMap) throws Exception { 
indexWriter.optimize();//优化索引方法,不建议经常调用,会很耗时,隔段时间调优下即可 
return "test"; 
} 
//关于更新一个文档要注意一点,虽然它提供了updateDocument,但我觉得他是先删再加,所以大家要把所以值都写上,虽然可能只更新一个字段 
@RequestMapping(value = "update.do", method = RequestMethod.GET) 
public String update(HttpServletRequest request, ModelMap modelMap) throws Exception { 
Term term = new Term("id", "1999991"); 
Document doc = new Document(); 
doc.add(new Field("id", String.valueOf(1999991), Store.YES, Index.NOT_ANALYZED)); 
doc.add(new Field("name", 555555 + "555555" + 555555, Store.YES, Index.ANALYZED)); 
doc.add(new Field("level1", String.valueOf(555555), Store.YES, Index.NOT_ANALYZED)); 
doc.add(new Field("level2", String.valueOf(555555), Store.YES, Index.NOT_ANALYZED)); 
doc.add(new Field("level3", String.valueOf(555555), Store.YES, Index.NOT_ANALYZED)); 
doc.add(new Field("brand_id", String.valueOf(555555 + 100000), Store.YES, Index.NOT_ANALYZED)); 
indexWriter.updateDocument(term, doc); 
indexWriter.commit();//凡是涉及到索引变化的动作都要提交才能生效 
return "test"; 
} 
//delete,没啥说的哈 
private void delete(String field, String text) throws CorruptIndexException, IOException { 
Term term1 = new Term(field, text); 
indexWriter.deleteDocuments(term1); 
indexWriter.commit(); 
} 

public void create(String string) throws Exception { 
long begin = System.currentTimeMillis(); 
for (int m = 604; m < 605; m++) { 
for (int i = m * 10000; i < (m + 1) * 10000; i++) { 
Document doc = new Document(); 
// doc.add(new Field("id", String.valueOf(i), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); 
NumericField field = new NumericField("id", 6, Field.Store.YES, false); 
field.setIntValue(i); 
doc.add(field);//这里不建议这样写,无论什么格式都以字符串形式灌入数据最好,否则会因为不匹配而查不到,经验之谈哈,如下面这样: 
doc.add(new Field("name", i + string + i, Store.YES, Index.ANALYZED));//关于索引策略,建议需要模糊查询字段进行分词策略,其他则不分词 
doc.add(new Field("level1", String.valueOf(3), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); 
doc.add(new Field("level2", String.valueOf(2), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); 
doc.add(new Field("level3", String.valueOf(1), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); 
doc.add(new Field("brand_id", String.valueOf(i + 100000), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); 
doc.add(new Field("hehe", String.valueOf(i + 100000), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); 
indexWriter.addDocument(doc); 
} 
System.out.println(m); 
} 
indexWriter.commit(); 
System.out.println("create cost:" + (System.currentTimeMillis() - begin) / 1000 + "s"); 
} 

//这里的查询是说:搜索name字段关键词为“整形的”,level3字段值为1的内容,两者条件是 'and'的关系 
public void search() throws Exception { 
long begin = System.currentTimeMillis(); 
String[] queryString = { "整形", "1" };//注意字段与值要一一对应哦,同下 
String[] fields = { "name", "level3" };////注意字段与值要一一对应哦,同上 
BooleanClause.Occur[] clauses = { BooleanClause.Occur.MUST, BooleanClause.Occur.MUST };//这里就是 and 的关系,详细策略看文档哈 
Query query = MultiFieldQueryParser.parse(Version.LUCENE_30, queryString, fields, clauses, myAnalyzer); 
IndexReader readerNow = searcher.getIndexReader(); 
//这个判断很重要,就是当我们刚灌入了数据就希望查询出来,因为前者写索引时关闭了reader,所以我们现在查询时要打开它 
if (!readerNow.isCurrent()) { 
searcher = new IndexSearcher(readerNow.reopen()); 
} 
System.out.println(searcher.maxDoc()); 
Sort sort = new Sort(); 
sort.setSort(new SortField("id", SortField.INT, true)); 
TopDocs topDocs = searcher.search(query, null, 53, sort);//排序策略 
// TopDocs topDocs = searcher.search(query, 50); 
for (ScoreDoc scoreDoc : topDocs.scoreDocs) { 
Document doc = searcher.doc(scoreDoc.doc); 
System.out.println("id:" + doc.get("id")); 
System.out.println("name:" + doc.get("name")); 
System.out.println("level3:" + doc.get("level3")); 
System.out.println("new field:" + doc.get("hehe")); 
} 
System.out.println("search cost:" + (System.currentTimeMillis() - begin) / 1000 + "s"); 
} 

private void idSearch() throws ParseException, CorruptIndexException, IOException { 
long begin = System.currentTimeMillis(); 
QueryParser qp = new QueryParser(Version.LUCENE_30, "id", myAnalyzer); 

Query query = qp.parse("4040011"); 
IndexReader readerNow = searcher.getIndexReader(); 
if (!readerNow.isCurrent()) { 
searcher = new IndexSearcher(readerNow.reopen()); 
} 
TopDocs topDocs = searcher.search(query, null, 53); 
for (ScoreDoc scoreDoc : topDocs.scoreDocs) { 
Document doc = searcher.doc(scoreDoc.doc); 
System.out.println("id:" + doc.get("id")); 
System.out.println("name:" + doc.get("name")); 
System.out.println("level3:" + doc.get("level3")); 
System.out.println("new field:" + doc.get("hehe")); 
} 
System.out.println("search cost:" + (System.currentTimeMillis() - begin) / 1000 + "s"); 
} 

public void searchMore() throws Exception { 
long begin = System.currentTimeMillis(); 
String[] queryStringOne = { "kkk", "222222" }; 
String[] queryStringTwo = { "99980", "222222" }; 
String[] fields = { "name", "level2" }; 
BooleanClause.Occur[] clauses = { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD }; 
Query queryOne = MultiFieldQueryParser.parse(Version.LUCENE_30, queryStringOne, fields, clauses, myAnalyzer); 
Query queryTwo = MultiFieldQueryParser.parse(Version.LUCENE_30, queryStringTwo, fields, clauses, myAnalyzer); 
BooleanQuery booleanQuery = new BooleanQuery(); 
booleanQuery.add(queryOne, BooleanClause.Occur.MUST); 
booleanQuery.add(queryTwo, BooleanClause.Occur.MUST); 
IndexReader readerNow = searcher.getIndexReader(); 
if (!readerNow.isCurrent()) { 
searcher = new IndexSearcher(readerNow.reopen()); 
} 
System.out.println(searcher.maxDoc()); 
Sort sort = new Sort(); 
sort.setSort(new SortField("id", SortField.INT, true)); 
TopDocs topDocs = searcher.search(booleanQuery, null, 53, sort); 
// TopDocs topDocs = searcher.search(query, 50); 
for (ScoreDoc scoreDoc : topDocs.scoreDocs) { 
Document doc = searcher.doc(scoreDoc.doc); 
System.out.println("id:" + doc.get("id")); 
System.out.println("name:" + doc.get("name")); 
System.out.println("level3:" + doc.get("level3")); 
System.out.println("new field:" + doc.get("hehe")); 
} 
System.out.println("search cost:" + (System.currentTimeMillis() - begin) / 1000 + "s"); 
} 

@RequestMapping(value = "result.do", method = RequestMethod.GET) 
public void getAnalyzerResult() throws IOException { 
StringReader reader = new StringReader("爱国者mp3"); 
TokenStream ts = myAnalyzer.tokenStream("name", reader); 
ts.addAttribute(TermAttribute.class); 
while (ts.incrementToken()) { 
TermAttribute ta = ts.getAttribute(TermAttribute.class); 
System.out.println(ta.term()); 
} 
} 

} 





 

 

0
0
分享到:
评论

相关推荐

    spring-lucene简单项目

    【标题】"spring-lucene简单项目" 描述了一个基于Spring框架整合Apache Lucene的实践案例。Lucene是一个高性能、全文本搜索库,被广泛应用于各种搜索引擎的开发。在这个项目中,我们将深入探讨如何将这两者结合,以...

    Struts+Hibernate+spring+jpa+lucene+jbpm+compass配置文件

    整合这些技术时,开发者通常会创建一个综合的配置文件体系,例如Spring的配置文件可以管理所有组件的依赖和配置,通过引入Struts、Hibernate、JPA、Lucene、JBPM和Compass的相关配置。这需要对每个框架的原理有深入...

    struts2.3 spring3.2 mybatis3.2 lucene4.2搜索引擎

    Struts2.3、Spring3.2、MyBatis3.2 和 Lucene4.2 是四个在Java Web开发中非常关键的技术组件,它们分别在应用程序的架构、依赖注入、数据库操作和全文检索方面扮演着重要角色。接下来,我们将详细探讨这四个技术以及...

    springmvc集成lucene全文搜索

    3. **配置索引目录**:选择一个合适的文件夹作为Lucene的索引存储位置,可以是项目目录下的某个文件夹,也可以是服务器上的特定路径。 4. **定义索引模型**:创建一个类来表示Lucene的文档,这个类应包含所有需要被...

    struts2+ibitas+spring+lucene 整合

    Struts2、iBatis、Spring 和 Lucene 是四个在Java Web开发中广泛使用的开源框架。这个整合项目是将它们结合起来,以实现更高效、更灵活的Web应用程序开发。 Struts2 是一个基于MVC(Model-View-Controller)设计...

    spring+hibernate3+struts2+lucene

    Spring框架是Java企业级应用的核心框架,它提供了依赖注入(DI)和面向切面编程(AOP)等特性,便于管理对象的生命周期和行为,同时也简化了单元测试。在Spring中,你可以配置事务管理、数据访问接口,以及通过...

    SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis+Lucene+Redis+MAVEN)

    1. **Spring框架**:Spring作为基础容器,负责管理应用对象的生命周期和依赖注入。它通过IoC(Inversion of Control)和AOP(Aspect Oriented Programming)来解耦应用程序的各个部分。在积分系统中,Spring可以用来...

    Lucene+compass+spring+jdbc+庖丁的一个例子

    3. **Spring**: Spring 是一个广泛使用的Java企业级应用开发框架,提供了一个全面的编程和配置模型,使得开发高质量的、柔性的Java应用变得简单。在这里,Spring可能被用来管理搜索服务的bean,以及协调与其他服务...

    SpringBoot+Lucene搜索结果高亮显示Demo

    在这个SpringBoot+Lucene的Demo中,我们将深入探讨如何在Spring Boot框架下集成Lucene,并实现搜索结果的高亮显示。 首先,让我们了解Spring Boot。Spring Boot是由Pivotal团队提供的全新框架,其设计目标是简化...

    详解SpringBoot+Lucene案例介绍

    * 需要正确地配置Lucene的版本,不同的版本用法也不同,许多api都有改变。 * 需要注意索引的更新,例如使用ControlledRealTimeReopenThread来更新索引库。 本文详细介绍了如何将SpringBoot与Lucene集成,以实现站内...

    Hibernate 与 Lucene 的整合框架详解

    ### Hibernate 与 Lucene 的整合框架详解 #### 一、概述 在软件开发领域,特别是企业级应用开发中,高效的数据检索与管理是至关重要的。Hibernate 和 Lucene 分别作为对象关系映射(ORM)工具和全文搜索引擎,在...

    struts2 spring lucene search 实例

    在本项目中,你将看到如何将Lucene集成到Struts2和Spring框架中,创建一个能够进行全文检索的搜索功能。 项目的文件结构如下: - `.classpath`:这是Eclipse项目配置文件,记录了项目所依赖的库和编译设置。 - `....

    SpringMvc+Lucene全文检索

    Spring MVC是Spring框架的一部分,它是一个用于构建Web应用程序的模型-视图-控制器(MVC)架构。通过Spring MVC,开发者可以将业务逻辑、数据处理和用户界面分离开,使得代码更易于维护和扩展。在我们的全文检索项目...

    ssm+lucene

    - 配置Lucene的依赖到项目中。 - 创建索引服务,对需要搜索的数据进行索引,这可能涉及到MyBatis的Mapper来获取数据。 - 使用Lucene的Analyzer对文本进行分词处理。 - 建立倒排索引并保存到硬盘或内存中。 - ...

    lucene的小案例

    在这个“lucene的小案例”中,我们结合了其他几个框架,如iBatis、Spring和Struts2,构建了一个完整的搜索解决方案。 首先,让我们深入了解Lucene的核心概念: 1. **索引(Index)**:在Lucene中,索引是预处理...

    ssm+lucene+redis

    首先,让我们深入了解一下Spring框架。Spring是Java企业级应用开发的核心框架,提供了IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)等核心特性,使得代码更加模块化,...

    Struts2.3.8整合Hibernate4.2,Spring3.2lucene 3 6 2 SSH整合1.0版

    Struts2.3.8、Hibernate4.2和Spring3.2是Java开发中的三大主流框架,它们分别负责Web层、持久层和业务层的管理,而Lucene 3.6.2则是一个强大的全文搜索引擎库。这个整合版本称为SSH整合1.0版,旨在提供一个高效、...

    Lucene与SSH2搜索功能

    **Spring框架** 在这里主要扮演服务层的角色,它是一个全面的后端解决方案,提供了依赖注入、事务管理、AOP(面向切面编程)等功能。在搜索功能的实现中,Spring可以帮助管理Lucene的相关组件,如索引目录、搜索引擎...

    lucene全文检索教程

    最后,Lucene并非孤立存在,它可以与其他框架结合使用,例如Spring Data和Solr。Solr是基于Lucene的一个高级搜索平台,它提供了更强大的集群管理和Web界面,适合大型企业级应用。 在这个教程中,读者会学习到如何...

Global site tag (gtag.js) - Google Analytics