文档章节

在项目中使用Lucene进行全文检索

SPPan
 SPPan
发布于 2017/06/02 10:20
字数 1057
阅读 25
收藏 1
点赞 0
评论 0

本文主要讲解在maven项目中使用Lucene进行全文检索的基本步骤。

一、首先需要引入依赖,使用的版本为4.7.2。

<!--核心包-->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>4.7.2</version>
</dependency>
<!--关键字高亮-->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-highlighter</artifactId>
    <version>4.7.2</version>
</dependency>
<!--分词-->
<dependency>
    <groupId>com.janeluo</groupId>
    <artifactId>ikanalyzer</artifactId>
    <version>2012_u6</version>
</dependency>

二、创建一个Javabean作为数据传输对象

public class SearcherBean {

	private String sid;
	private String title;
	private String description;
	private String content;
	private String url;
	private Date created;

	private Object data; // 保存其他信息,不是用来检索的

	public SearcherBean() {
	}

	public SearcherBean(String sid, String title, String description, String content, String url, Date created,
			Object data) {
		this.sid = sid;
		this.title = title;
		this.description = description;
		this.content = content;
		this.url = url;
		this.created = created;
		this.data = data;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Date getCreated() {
		return created;
	}

	public void setCreated(Date created) {
		this.created = created;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
	
}

三、增加索引

public void addBean() {
    IndexWriter writer = null;
    try {
        //指定文件存储路径
        Directory directory = NIOFSDirectory.open(new File("c://"));
        //创建词法分析
        Analyzer analyzer = new IKAnalyzer();
        //创建IndexWriter
        IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_47, analyzer);
        writer = new IndexWriter(directory, iwc);
        //创建文档
        Document doc = createDoc(bean);
        //保存文档
        writer.addDocument(doc);
    } catch (Exception e) {
        logger.error("add bean to lucene error", e);
    } finally {
        try {
            if (writer != null) {
               writer.close();
            }
        } catch (IOException e) {
            logger.error("close failed", e);
        }
    }
}
/**
* 创建Doc
* @param bean
* @return
*/
private Document createDoc(SearcherBean bean) {
        Document doc = new Document();
        doc.add(new StringField("id", bean.getId(), Field.Store.YES));
        doc.add(new TextField("title", bean.getTitle(), Field.Store.YES));
        doc.add(new TextField("summary", bean.getSummary(), Field.Store.YES));
        doc.add(new TextField("content", bean.getContent(), Field.Store.YES));	
        doc.add(new StringField("authorName", bean.getAuthorName(), Field.Store.YES));
        doc.add(new IntField("views", bean.getViews(), Field.Store.YES));
        doc.add(new StringField("createdAt", DateTools.dateToString(bean.getCreateAt(), DateTools.Resolution.MILLISECOND), Field.Store.YES));
        return doc;
}

四、删除索引

@Override
public void deleteBean(String beanId) {
    IndexWriter writer = null;
    try {
        IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_47, analyzer);
        writer = new IndexWriter(directory, iwc);
        writer.deleteDocuments(new Term("id", beanId));
    } catch (IOException e) {
        logger.error("delete bean to lucene error,beanId:"+beanId,e);
    } catch (InterruptedException e) {
        logger.error("delete bean to lucene error,beanId:"+beanId,e);
    } finally {
        try {
            if(writer!=null) {
                writer.close();
            }
        } catch (IOException e) {
            logger.error("close failed", e);
        }
    }
}
    
/**
 * 删除所有
 */
@Override
public void deleteAllBean() {
	IndexWriter writer = null;
	try {
		IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_47, analyzer);
		writer = new IndexWriter(directory, iwc);
		writer.deleteAll();
	} catch (IOException e) {
		logger.error("delete allBean to lucene error",e);
	} catch (InterruptedException e) {
		logger.error("delete allBean to lucene error",e);
	} finally {
		try {
			if(writer!=null) {
				writer.close();
			}
		} catch (IOException e) {
			logger.error("close failed", e);
		}
	}
}

五、检索

/**
 *  转换为SearchBean
 * @param searcher
 * @param topDocs
 * @return
 * @throws IOException
 */
private List getSearcherBeans(Query query, IndexSearcher searcher, TopDocs topDocs) throws IOException {
    List searcherBeans = new ArrayList();
    for (ScoreDoc item : topDocs.scoreDocs) {
        Document doc = searcher.doc(item.doc);
        SearcherBean searcherBean = new SearcherBean();
        searcherBean.setId(doc.get("id"));
        
        searcherBean.setTitle(setHighlighter(query, doc, "title"));
        searcherBean.setSummary(setHighlighter(query, doc, "summary"));
        searcherBean.setContent(setHighlighter(query, doc, "content"));
        
        searcherBean.setViews(Integer.parseInt(doc.get("views")));
        searcherBean.setAuthorName(doc.get("authorName"));
        
        try {
			searcherBean.setCreateAt(DateTools.stringToDate(doc.get("createdAt")));
		} catch (java.text.ParseException e) {
			e.printStackTrace();
		}
        searcherBeans.add(searcherBean);
    }
    return searcherBeans;
}
/**
 * 获取Query 对象
 * @param keyword
 * @param module
 * @return
 */
private Query getQuery(String keyword) {
    try {
        QueryParser queryParser1 = new QueryParser(Version.LUCENE_47, "content", analyzer);
        Query termQuery1 = queryParser1.parse(keyword);
        
        QueryParser queryParser2 = new QueryParser(Version.LUCENE_47, "title", analyzer);
        Query termQuery2 = queryParser2.parse(keyword);
        
        QueryParser queryParser3 = new QueryParser(Version.LUCENE_47, "summary", analyzer);
        Query termQuery3 = queryParser3.parse(keyword);
        
        BooleanQuery booleanClauses = new BooleanQuery();
        booleanClauses.add(new BooleanClause(termQuery1, BooleanClause.Occur.SHOULD));
        booleanClauses.add(new BooleanClause(termQuery2, BooleanClause.Occur.SHOULD));
        booleanClauses.add(new BooleanClause(termQuery3, BooleanClause.Occur.SHOULD));
        
        booleanClauses.setMinimumNumberShouldMatch(1);
        return booleanClauses;
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return null;
}
/**
 * 通过关键字搜索分页
 * 
 * @param keyword 关键字
 */
@Override
public Page search(String keyword) {
    try {
        IndexReader aIndexReader = DirectoryReader.open(directory);
        IndexSearcher searcher = null;
        searcher = new IndexSearcher(aIndexReader);
        Query query = getQuery(keyword);
        TopDocs topDocs = searcher.search(query, 50);
        List searcherBeans = getSearcherBeans(query, searcher, topDocs);
        Page searcherBeanPage = new Page<>(searcherBeans, 1, 10, 100, 1000);
        return searcherBeanPage;
    } catch (Exception e) {
    }
    return null;
}
/**
 * 分页检索
 * @param pageNum 当前页
 * 
 * @param pageSize 每页条数
 * 
 * @param queryString 关键字
 * 
 */
@Override
public Page search(int pageNum, int pageSize, String queryString) {
    IndexReader aIndexReader = null;
    try {
        aIndexReader = DirectoryReader.open(directory);
        IndexSearcher searcher = null;
        searcher = new IndexSearcher(aIndexReader);
        Query query = getQuery(queryString);
        ScoreDoc lastScoreDoc = getLastScoreDoc(pageNum, pageSize, query, searcher);
        TopDocs topDocs = searcher.searchAfter(lastScoreDoc, query, pageSize);
        List searcherBeans = getSearcherBeans(query, searcher, topDocs);
        int totalRow = searchTotalRecord(searcher, query);
        int totalPages;
        if ((totalRow % pageSize) == 0) {
            totalPages = totalRow / pageSize;
        } else {
            totalPages = totalRow / pageSize + 1;
        }
        Page searcherBeanPage = new Page<>(searcherBeans, pageNum, pageSize, totalPages, totalRow);
        return searcherBeanPage;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
/**
 * 根据页码和分页大小获取上一次最后一个ScoreDoc
 *
 * @param pageIndex
 * @param pageSize
 * @param query
 * @param indexSearcher
 * @return
 * @throws IOException
 */
private ScoreDoc getLastScoreDoc(int pageIndex, int pageSize, Query query, IndexSearcher indexSearcher) throws IOException {
    if (pageIndex == 1) return null;//如果是第一页返回空
    int num = pageSize * (pageIndex - 1);//获取上一页的数量
    TopDocs tds = indexSearcher.search(query, num);
    return tds.scoreDocs[num - 1];
}
/**
 * @param query
 * @return
 * @throws IOException
 * @Title: searchTotalRecord
 * @Description: 获取符合条件的总记录数
 */
public int searchTotalRecord(IndexSearcher searcher, Query query) throws IOException {
    TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
    if (topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) {
        return 0;
    }
    ScoreDoc[] docs = topDocs.scoreDocs;
    return docs.length;
}

设置关键字高亮

/**
 * 高亮设置
 * @param query
 * @param doc
 * @param field
 * @return
 */
private String setHighlighter(Query query,Document doc,String field){
    try {
        SimpleHTMLFormatter simpleHtmlFormatter = new SimpleHTMLFormatter("", "");
        Highlighter highlighter = new Highlighter(simpleHtmlFormatter,new QueryScorer(query));
        String fieldValue = doc.get(field);
        String highlighterStr = highlighter.getBestFragment(analyzer,field,fieldValue);
        return highlighterStr == null ? fieldValue:highlighterStr;
    } catch (Exception e) {
    	e.printStackTrace();
    }
    return null;
}

© 著作权归作者所有

共有 人打赏支持
SPPan
粉丝 10
博文 29
码字总数 15103
作品 0
成都
程序员
Spring Boot 中使用 Java API 调用 lucene

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引...

PengLei ⋅ 2017/11/08 ⋅ 0

高手问答第 179 期 —— 全文检索技术分享:从 Lucene 到 Elasticsearch

OSCHINA 本期高手问答(11 月 29 日 - 12 月 5 日)我们请来了@napoay 姚攀为大家解答关于全文检索技术的问题。 姚攀,中国科学院大学硕士,热爱撰写技术博客、翻译文档。研究生期间因选修信工...

局长 ⋅ 2017/11/28 ⋅ 71

Hibernate Search 4.1.0.Beta1 发布

Hibernate Search version 4.1.0.Beta1 发布了,该版本最大的改变就是:HSEARCH-1034 ,可通过可编程 API 使用 Infinispan Query。另外还包括 MassIndexer 改进,性能提升等。 Hibernate Se...

红薯 ⋅ 2012/02/07 ⋅ 0

Hibernate Search 5.0.0 RC1 发布

Hibernate Search 5.0.0 RC1 发布,此版本默认情况下使用 Lucene 的 NumericField 数值字段(s)。更多更新内容请看发行说明。 Hibernate Search的作用是对数据库中的数据进行检索的。它是hib...

oschina ⋅ 2014/12/10 ⋅ 12

我心中的核心组件(可插拔的AOP)~第十四回 全文检索架构~终于设计了一个自己满意的Lucene架构

我架构的以lucene为技术的全文检索分为lucene检索模块,索引文件生成器和WEB检索测试三个部分组成 结构如下: lucene模块它由通过检索项和几个具体检索业务子项目组成 通过功能项目结构为: ...

mcy247 ⋅ 2017/12/06 ⋅ 0

lucene学习笔记一(初始lucene)

lucene简介: 摘自百科:Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了...

吕兵阳 ⋅ 2015/10/03 ⋅ 4

基于Lucene的全文检索框架--snoics-retrieval

基于Lucene的全文检索框架 一、 介绍 基于Lucene的全文检索框架,提供快速方便的索引创建及查询方式,并提供扩展功能对框架进行扩展。 二、 使用指南 1、 环境要求 Java1.5+ Lucene 3.0.x+ 2...

匿名 ⋅ 2010/08/19 ⋅ 0

Solr简单介绍

简介 Solr是一个高性能,采用Java5开发,Solr基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提...

邵鸿鑫 ⋅ 2016/06/29 ⋅ 0

Hibernate Search 5.0.0.Beta2 发布

Hibernate Search 5.0.0.Beta2 发布,此版本现已提供在 JBoss Maven Repository,或者使用 GAV org.hibernate:hibernate-search:5.0.0.Beta2 来安装升级,也可以从 SourceForge 中获得。完整...

oschina ⋅ 2014/11/14 ⋅ 4

Hibernate Search 4.4.0.Alpha2 发布

Hibernate Search 4.4.0.Alpha2 发布了,包含一些小的 bug 修复,对代码进行优化以及更新一些依赖包和小的性能提升。详情请看 changelog on JIRA. Hibernate Search的作用是对数据库中的数据...

红薯 ⋅ 2013/09/19 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

从零开始搭建Risc-v Rocket环境---(1)

为了搭建Rocke环境,我买了一个2T的移动硬盘,安装的ubuntu-16.04 LTS版。没有java8,gcc是5.4.0 joe@joe-Inspiron-7460:~$ java -version程序 'java' 已包含在下列软件包中: * default-...

whoisliang ⋅ 22分钟前 ⋅ 0

大数据学习路线(自己制定的,从零开始学习大数据)

大数据已经火了很久了,一直想了解它学习它结果没时间,过年后终于有时间了,了解了一些资料,结合我自己的情况,初步整理了一个学习路线,有问题的希望大神指点。 学习路线 Linux(shell,高并...

董黎明 ⋅ 27分钟前 ⋅ 0

systemd编写服务

一、开机启动 对于那些支持 Systemd 的软件,安装的时候,会自动在/usr/lib/systemd/system目录添加一个配置文件。 如果你想让该软件开机启动,就执行下面的命令(以httpd.service为例)。 ...

勇敢的飞石 ⋅ 30分钟前 ⋅ 0

mysql 基本sql

CREATE TABLE `BBB_build_info` ( `community_id` varchar(50) NOT NULL COMMENT '小区ID', `layer` int(11) NOT NULL COMMENT '地址层数', `id` int(11) NOT NULL COMMENT '地址id', `full_......

zaolonglei ⋅ 38分钟前 ⋅ 0

安装chrome的vue插件

参看文档:https://www.cnblogs.com/yulingjia/p/7904138.html

xiaoge2016 ⋅ 41分钟前 ⋅ 0

用SQL命令查看Mysql数据库大小

要想知道每个数据库的大小的话,步骤如下: 1、进入information_schema 数据库(存放了其他的数据库的信息) use information_schema; 2、查询所有数据的大小: select concat(round(sum(da...

源哥L ⋅ 今天 ⋅ 0

两个小实验简单介绍@Scope("prototype")

实验一 首先有如下代码(其中@RestController的作用相当于@Controller+@Responsebody,可忽略) @RestController//@Scope("prototype")public class TestController { @RequestMap...

kalnkaya ⋅ 今天 ⋅ 0

php-fpm的pool&php-fpm慢执行日志&open_basedir&php-fpm进程管理

12.21 php-fpm的pool pool是PHP-fpm的资源池,如果多个站点共用一个pool,则可能造成资源池中的资源耗尽,最终访问网站时出现502。 为了解决上述问题,我们可以配置多个pool,不同的站点使用...

影夜Linux ⋅ 今天 ⋅ 0

微服务 WildFly Swarm 管理

Expose Application Metrics and Information 要公开关于我们的微服务的有用信息,我们需要做的就是将监视器模块添加到我们的pom.xml中: 这将使在管理和监视功能得到实现。从监控角度来看,...

woshixin ⋅ 今天 ⋅ 0

java连接 mongo伪集群部署遇到的坑

部署mongo伪集群 #创建mongo数据存放文件地址mkdir -p /usr/local/config1/datamkdir -p /usr/local/config2/data mkdir -p /usr/local/config3/data mkdir -p /usr/local/config1/l......

努力爬坑人 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部