`
link99oracle
  • 浏览: 3394 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类

使用lucene进行数据库全文检索(新增排序功能)

阅读更多
这几天在做全文检索 花了我好大力气啊 尼玛啊各种异常!!
经过我不懈努力终于搞出来了。。。  

废话不多说 附源码
新手第一次发帖,勿喷。。。
源代码如下
实体类Content
@Entity
@Table(name = "TB_CONTENT", schema = "PROEDU")
public class Content implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -7615375010821887584L;
	
	private long id;		//id
	private Date createDate;//创建时间
	private String title;//标题
	private String keyWords;//关键字
	private Date publishedDate;//发布日期
	private Date invalidDate;//失效日期
	private String content;//内容
	private String source;//来源
	private long groupId;//内容分类
	private String authorCode;//作者
	private String verifierCode;//审核人
	private int status;//状态
	private int count;//访问次数
      //getter&&setter神马的最讨厌了
}


数据库操作这里就不写了。。。
我数据从数据库读出来一个list集合


IFullSearch接口
public interface IFullSearch {
	

	/**
	 * @return int 总记录数
	 */
	public int getCount();
	/**
	 * @param key 检索关键字
	 * @param contents 检索集合,从数据库里面查询全部或者部分出来
	 * @param searchDir 索引路径
	 * @param pageIndex 页数
	 * @param pageCount 每页显示条数
	 * @param content 精确检索条件,根据content对应中的部分字段
            * 进行全 文检索
	 * @param order 排序方式
	 * @return 检索结果集
	 * @throws Exception
	 */
	public List<Content> getResult(String key, List<Content> contents,String searchDir,int pageIndex, int pageCount,Content content,String order) throws Exception;

}

IFullSearch实现类FullSearch
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
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.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.stereotype.Service;
import org.wltea.analyzer.lucene.IKAnalyzer;

import com.bluedon.emis.common.usermanage.service.IFullSearch;
import com.bluedon.emis.common.usermanage.vo.Content;
/**
 * @author wenb
 * @version 1.0 全文检索
 */
@Service("IFullSearch")
public class FullSearch implements IFullSearch {
	private int count;// 检索总记录数

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return count;
	}
	@Override
	public List<Content> getResult(String key, List<Content> contents,
			String searchDir, int pageIndex, int pageCount, Content content,String order)
			throws Exception {
		this.createIndex(contents, searchDir);
		Query query = null;
		if (key == null||"".equals(key)) {
			query = getQuery(content);
		} else {
			query = getQuery(key);
		}
		File indexFile = new File(searchDir);
		IndexSearcher searcher = new IndexSearcher(
				DirectoryReader.open(FSDirectory.open(indexFile)));
		List<Content> list = getList(query, pageIndex, pageCount, searcher,
				contents.size(), order);
		// List<Content> list = search(key, searchDir, pageIndex, pageCount,
		// contents.size());
		return list != null && list.size() > 0 ? list : null;
	}


在该实现类中我加入了以下方法,来创建索引,全文检索,觉得不符合规范的可以自己新建一个类。。
/**
	 * 创建索引
	 * 
	 * @param 检索集合
	 * @param 索引路径
	 * @throws Exception
	 */
	private void createIndex(List<Content> list, String searchDir)
			throws Exception {
		// if(this.isIndexExisted(searchDir)){
		// return;
		// }
		Directory directory = null;
		IndexWriter indexWriter = null;
		File indexFile = new File(searchDir);//索引文件
		directory = FSDirectory.open(indexFile); //索引目录
		Analyzer analyzer = new IKAnalyzer();//分词器
		IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_42,
				analyzer);//索引配置
		
		iwc.setOpenMode(OpenMode.CREATE);
		indexWriter = new IndexWriter(directory, iwc);
		//为相应字段建立索引
		for (Content content : list) {
			Document doc = new Document();
			Field cont = new TextField("content", content.getContent(),
					Field.Store.YES);
			doc.add(cont);
			Field title = new TextField("title", content.getTitle(),
					Field.Store.YES);
			doc.add(title);
			Field keyWords = new TextField("keyWords", content.getKeyWords(),
					Field.Store.YES);
			doc.add(keyWords);
			Field source = new TextField("source", content.getSource(),
					Field.Store.YES);
			doc.add(source);
			Field id = new TextField("id", content.getId() + "",
					Field.Store.YES);
			doc.add(id);
			Field publishDate = new TextField("publishDate",
					content.getPublishedDate().getTime() + "", Field.Store.YES);
			doc.add(publishDate);

			indexWriter.addDocument(doc);
		}
		indexWriter.commit();
		indexWriter.close();
	}
	
	/**
	 * 获取Query对象
	 * 
	 * @param key
	 * @return 关键字查找对象
	 * @throws Exception
	 */
	private Query getQuery(String key) throws Exception {
		String[] fields = { "content", "title", "keyWords", "source", "id" };//索引的Field字段数组
		Analyzer analyzer = new IKAnalyzer();
		
		 //生成Query对象    
		QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_42,
				fields, analyzer);
		Query query = queryParser.parse(key);
		return query;
	}

	/**
	 * 
	 * 获取索引结果数据及对结果排序
	 * 
	 * @param query
	 *            查询对象
	 * @param searcher
	 *            索引
	 * @param order 排序条件
	 * @param size
	 *            查询数量
	 * @return ScoreDoc[]
	 * @throws Exception
	 */
	private ScoreDoc[] getScoreDoc(Query query, IndexSearcher searcher, int size,String order)
			throws Exception {
		Sort sort = new Sort();//创建排序
		ScoreDoc[] hits= null;//索引结果数组
		//默认排序,即相关度排序
		if(order==null||"def".equals(order)||"".equals(order)){ 
			hits= searcher.search(query, null,size).scoreDocs;
		}
		
		//按时间倒序
		if("desc".equals(order)){
			//排序条件设置,第一参数为索引字段,第二个为排序类型,第三个为排序方式true相当于数据库desc,false相当于数据库asc
			
			SortField sortField =new SortField("publishDate",SortField.Type.LONG,  true); 
			sort.setSort(sortField);
			hits=searcher.search(query, null, size, sort).scoreDocs;
		}
		//按时间升序
		if("asc".equals(order)){
			SortField sortField =new SortField("publishDate",SortField.Type.LONG,  false);
			sort.setSort(sortField);
			hits=searcher.search(query, null, size, sort).scoreDocs;
		}
		
		
		//ScoreDoc[] hits = searcher.search(query, null, size).scoreDocs;
		count = hits.length;
		return hits;
	}

	/**
	 * 将查询结果还原成对象集合
	 * 
	 * @param query
	 *            查询对象
	 * @param pageIndex
	 *            页数
	 * @param pageCount
	 *            每页条数
	 * @param searcher
	 *            索引
	 * @param size
	 *            查询数量
	 * @return 结果集
	 * @throws Exception
	 */
	private List<Content> getList(Query query, int pageIndex, int pageCount,
			IndexSearcher searcher, int size,String order) throws Exception {
		List<Content> list = new ArrayList<Content>();
		ScoreDoc[] hits = getScoreDoc(query, searcher, size, order); //得到搜索结果
		Content content = null;
		//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		int start = (pageIndex - 1) * pageCount;
		int end = pageIndex * pageCount < count ? pageIndex * pageCount : count;
		for (int i = start; i < end; i++) {
			Document doc = searcher.doc(hits[i].doc);
			content = new Content();
			content.setId(Long.parseLong(doc.get("id")));
			String con = doc.get("content");
			String title = doc.get("title");
			String source = doc.get("source");
			String keyWords = doc.get("keyWords");
			content.setKeyWords(highLighter(query, "keyWords", keyWords));
			content.setContent(highLighter(query, "content", con));
			content.setTitle(highLighter(query, "title", title));
			content.setSource(highLighter(query, "source", source));
			//content.setPublishedDate(sdf.parse(doc.get("publishDate")));
			content.setPublishedDate(new Date(Long.parseLong(doc.get("publishDate"))));
			list.add(content);
		}
		return list;
	}

	/**
	 * 获取精确查找对象query
	 * 
	 * @param content
	 *            精确查询条件
	 * @return 精确查找对象
	 * @throws Exception
	 */
	private Query getQuery(Content content) throws Exception {
		//组合查询
		BooleanQuery booleanQuery = new BooleanQuery();
		Analyzer analyzer = new IKAnalyzer();
		if (content.getContent()!=null&&!"".equals(content.getContent())){
			QueryParser queryParser = new QueryParser(Version.LUCENE_42,
					"content", analyzer);
			//将查询条件添加到booleanQuery中, Occur.MUST表示条件必须,多个条件组合 相当于and
			booleanQuery.add(queryParser.parse(content.getContent()), Occur.MUST);
		}
		if (content.getTitle()!=null&&!"".equals(content.getTitle())) {
			QueryParser queryParser = new QueryParser(Version.LUCENE_42,
					"title", analyzer);
			booleanQuery.add(queryParser.parse(content.getTitle()), Occur.MUST);
		}
		if (content.getKeyWords()!=null&&!"".equals(content.getKeyWords())) {
			QueryParser queryParser = new QueryParser(Version.LUCENE_42,
					"keyWords", analyzer);
			booleanQuery.add(queryParser.parse(content.getKeyWords()), Occur.MUST);
		}
		if (content.getSource()!=null&&!"".equals(content.getSource())) {
			QueryParser queryParser = new QueryParser(Version.LUCENE_42,
					"source", analyzer);
			booleanQuery.add(queryParser.parse(content.getSource()), Occur.MUST);
		}
		return booleanQuery;
	}

	/**
	 * 高亮显示
	 * 
	 * @param query
	 *            查询对象
	 * @param fieldName
	 *            索引字段
	 * @param cont
	 *            索引内容
	 * @return 索引高亮处理结果
	 * @throws Exception
	 */
	private String highLighter(Query query, String fieldName, String cont)
			throws Exception {
		SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(
				"<font color='red' style='background: yellow;'><strong>",
				"</strong></font>");
		Highlighter highlighter = new Highlighter(simpleHTMLFormatter,
				new QueryScorer(query));
		Analyzer analyzer = new IKAnalyzer();
		String[] str = highlighter.getBestFragments(analyzer, fieldName, cont,
				cont.length());

		return str == null || str.length <= 0 ? cont : str[0];
	}

	


代码就这些了  有不懂可以留言。。。。。有可以优化的,也请留言。。。。。
分享到:
评论
1 楼 link99oracle 2013-05-06  
木有人在么?   

相关推荐

    lucene-3.0.0

    Apache Lucene 是一个开源的全文检索库,由Java编写,为开发者提供了强大的文本搜索功能。作为一款高度可扩展的搜索引擎框架,Lucene 3.0.0 版本在当时代表着其最新的技术成果。本文将深入探讨这一版本中的关键特性...

    lucene-5.3.1源代码

    《深入剖析Lucene 5.3.1:构建全文检索引擎》 Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发并维护。作为Java平台上的一个开源项目,它为开发者提供了强大的文本搜索功能,使得在应用程序中实现复杂的...

    lucene-4.7.0.zip

    2. 新增功能:引入了新的分析器,如PerFieldAnalyzerWrapper,允许针对不同字段使用不同的分析器,增强了对多语言文档的支持。同时,提供了更强大的查询构造和过滤功能。 3. 错误修复:4.7.0版本修复了许多已知问题...

    lucene入门指南

    总之,Lucene 是一个强大的搜索引擎框架,通过理解和掌握其核心概念,开发者能够构建出高效的全文检索系统。无论是在网站、企业内部系统还是大数据应用中,Lucene 都能发挥关键作用,帮助我们从海量数据中挖掘有价值...

    一个基于lucene制作的搜索引擎源码

    Lucene是一个开源的全文检索库,由Apache软件基金会开发,主要用Java编写。它提供了文本分析、索引和搜索功能,被广泛应用于各种搜索引擎的构建。在这个基于Lucene的搜索引擎源码中,我们可以深入理解如何利用Lucene...

    [搜索链接]java(结合lucene)版的公交搜索系统_javaso.zip

    【描述】:这个系统的核心功能是通过Lucene的强大索引和查询能力,对公交线路数据库进行高效的文本搜索。用户可以输入关键词,如公交线路号、站点名称或相关路线,系统将返回匹配的结果。Java作为后端开发语言,提供...

    ElasticSearch入门

    Elasticsearch(简称 ES)是一种基于 Lucene 的开源分布式搜索引擎,它提供了全文检索、分析、实时等高级功能。作为NoSQL数据库的一种,Elasticsearch以其高效、灵活和可扩展性在大数据时代备受青睐,广泛应用于日志...

    ElasticSearch.pdf

    ### ElasticSearch知识点总结 ...通过以上内容,我们可以看到Elasticsearch不仅具备强大的全文检索功能,还能满足大规模数据的存储需求,同时提供了丰富的API接口和工具支持,适用于各种应用场景。

    最新版windows solr-8.5.2.zip

    Solr是Apache软件基金会开发的一款高性能、基于Java的全文搜索引擎服务器。它被设计用来处理大量数据,提供快速的搜索响应,并且支持分布式搜索和云计算。最新版的Windows Solr 8.5.2是一个专为在Windows操作系统上...

    黑马面试宝典知识点复习

    - **原理**:基于Lucene的全文检索服务。 - **搜索结果排名**:可以通过配置文件设置不同的评分策略。 - **IK分词器**:一种中文分词工具,用于提高中文搜索效果。 ### 电商项目面试问题 - **项目背景介绍**:项目...

    Web2.0社区平台源码

    SpaceBuilder采用世界领先的技术体系架构、优异的缓存技术、基于Lucene的全文检索技术,可以承载千万级的数据,并提供良好的安全性及用户体验,表现层采用asp.net mvc及jQuery开发,是迄今为止基于asp.net技术领域最...

    J2EE spring mvc mybatis bootstrap HTML5 后台框架 控制台 mysql版本_spring3.0

    17.新增Lucene全文检索 18.Base64传输图片 19.图片加水印(图片水印,文字水印) 20.生成 or 解析 二维码 21.HTML5 + JAVAEE WebSocket 通信技术 22.批量异步上传图片,可预览,有进度条,支持拖拽上传(百度...

    J2EE spring mvc mybatis bootstrap HTML5 后台框架 控制台 oracle版本_spring3.0

    17.新增Lucene全文检索 18.Base64传输图片 19.图片加水印(图片水印,文字水印) 20.生成 or 解析 二维码 21.HTML5 + JAVAEE WebSocket 通信技术 22.批量异步上传图片,可预览,有进度条,支持拖拽上传(百度...

Global site tag (gtag.js) - Google Analytics