文档章节

lucene4.8增删查改实例

凯文加内特
 凯文加内特
发布于 2016/03/30 14:18
字数 1514
阅读 124
收藏 2

pom依赖

<properties>
		<lucene>4.8.0</lucene>
	</properties>

<!--Lucene -->
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-core</artifactId>
			<version>${lucene}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-highlighter</artifactId>
			<version>${lucene}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-memory</artifactId>
			<version>${lucene}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-queries</artifactId>
			<version>${lucene}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-queryparser</artifactId>
			<version>${lucene}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-analyzers-common</artifactId>
			<version>${lucene}</version>
		</dependency>

Article类:

package class7;

public class Article {

	private String id;//id
	private String title;//标题
	private String author;//作者
	private String content;//内容
	private String createDate;//创建时间

	public Article(String id, String title, String author, String content, String createDate) {
		super();
		this.id = id;
		this.title = title;
		this.author = author;
		this.content = content;
		this.createDate = createDate;
	}

	public Article() {
		super();
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

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

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getContent() {
		return content;
	}

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

	public String getCreateDate() {
		return createDate;
	}

	public void setCreateDate(String createDate) {
		this.createDate = createDate;
	}

	@Override
	public String toString() {
		return "Article [id=" + id + ", title=" + title + ", author=" + author + ", content=" + content
				+ ", createDate=" + createDate + "]";
	}
	
	

}

测试类:

package class7;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
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.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
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.SortField.Type;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
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.wltea.analyzer.lucene.IKAnalyzer;

public class LuceneTest {

	/**
	 * 根据内容,构建索引
	 * @param analyzer
	 * @param directory
	 * @param items
	 * @return
	 */
	private boolean buildIndexer(Analyzer analyzer, Directory directory, List<Article> items) {
		IndexWriter iwriter = null;
		try {
			// 配置索引
			iwriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_48, analyzer));
			// 将文档信息存入索引
			Document doc[] = new Document[items.size()];
			for (int i = 0; i < items.size(); i++) {
				doc[i] = new Document();

				Article item = items.get(i);
				//获取Item的属性值,构建Field构建Document
				java.lang.reflect.Field[] fields = item.getClass().getDeclaredFields();
				for (java.lang.reflect.Field field : fields) {
					String fieldName = field.getName();
					String getMethodName = "get" + toFirstLetterUpperCase(fieldName);
					Object obj = item.getClass().getMethod(getMethodName).invoke(item);
					doc[i].add(new Field(fieldName, (String) obj, TextField.TYPE_STORED));
				}

				iwriter.addDocument(doc[i]);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				iwriter.close();
			} catch (IOException e) {
			}
		}
		return true;
	}

	/**
	 * 更新索引
	 * @param analyzer
	 * @param directory
	 * @param items
	 * @return
	 */
	private boolean updateIndexer(Analyzer analyzer, Directory directory, List<Article> items) {
		IndexWriter iwriter = null;
		try {
			// 配置索引
			iwriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_48, analyzer));
			// 根据id更新索引
			Document doc = null;
			for (int i = 0; i < items.size(); i++) {
				doc = new Document();

				Article item = items.get(i);
				java.lang.reflect.Field[] fields = item.getClass().getDeclaredFields();
				for (java.lang.reflect.Field field : fields) {
					String fieldName = field.getName();
					String getMethodName = "get" + toFirstLetterUpperCase(fieldName);
					Object obj = item.getClass().getMethod(getMethodName).invoke(item);
					doc.add(new Field(fieldName, (String) obj, TextField.TYPE_STORED));
				}
				iwriter.updateDocument(new Term("id", item.getId()), doc);

			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				iwriter.commit();
				iwriter.close();
			} catch (IOException e) {
			}
		}
		return true;
	}

	/**
	 * 删除索引
	 * @param analyzer
	 * @param directory
	 * @param items
	 * @return
	 */
	private boolean deleteIndexer(Analyzer analyzer, Directory directory, List<String> ids) {
		IndexWriter iwriter = null;
		try {
			// 配置索引
			iwriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_48, analyzer));
			// 根据id更新索引
			for (String id : ids) {
				iwriter.deleteDocuments(new Term("id", id));
			}

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				iwriter.commit();
				iwriter.close();
			} catch (IOException e) {
			}
		}
		return true;
	}

	/**
	 * 根据keyword搜索索引
	 * @param analyzer
	 * @param directory
	 * @param keyword
	 * @return
	 */
	public List<Article> searchIndexer(Analyzer analyzer, Directory directory, String keyword) {
		DirectoryReader ireader = null;
		List<Article> result = new ArrayList<Article>();
		try {
			// 设定搜索目录
			ireader = DirectoryReader.open(directory);
			IndexSearcher isearcher = new IndexSearcher(ireader);

			// 对多field进行搜索
			java.lang.reflect.Field[] fields = Article.class.getDeclaredFields();
			int length = fields.length;
			String[] multiFields = new String[length];
			for (int i = 0; i < length; i++) {
				multiFields[i] = fields[i].getName();
			}
			MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_48, multiFields, analyzer);

			// 设定具体的搜索词
			Query query = parser.parse(keyword);
			Sort sort = new Sort(new SortField("id", Type.INT, true));//true为降序排列,按照id倒序
			ScoreDoc[] hits = isearcher.search(query, null, 50, sort).scoreDocs;
			for (int i = 0; i < hits.length; i++) {
				Document hitDoc = isearcher.doc(hits[i].doc);
				Article item = new Article();
				for (String field : multiFields) {
					String setMethodName = "set" + toFirstLetterUpperCase(field);
					String str = displayHtmlHighlight(query, analyzer, field, hitDoc.get(field), 200);
					if (StringUtils.isBlank(str)) {
						item.getClass().getMethod(setMethodName, String.class).invoke(item, hitDoc.get(field));
					} else {
						item.getClass().getMethod(setMethodName, String.class).invoke(item, str);
					}
				}
				result.add(item);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				ireader.close();
				directory.close();
			} catch (IOException e) {
			}
		}
		return result;
	}

	/**
	* 获取高亮显示结果的html代码
	* @param query 查询
	* @param analyzer 分词器
	* @param fieldName 域名
	* @param fieldContent 域内容
	* @param fragmentSize 结果的长度(不含html标签长度)
	* @return 结果(一段html代码)
	* @throws IOException
	* @throws InvalidTokenOffsetsException
	*/
	static String displayHtmlHighlight(Query query, Analyzer analyzer, String fieldName, String fieldContent,
			int fragmentSize) throws IOException, InvalidTokenOffsetsException {
		//创建一个高亮器
		Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter("<font color='red'>", "</font>"),
				new QueryScorer(query));
		Fragmenter fragmenter = new SimpleFragmenter(fragmentSize);
		highlighter.setTextFragmenter(fragmenter);
		return highlighter.getBestFragment(analyzer, fieldName, fieldContent);
	}

	/**
	 * 首字母转大写
	 * @param str
	 * @return
	 */
	public static String toFirstLetterUpperCase(String str) {
		if (str == null || str.length() < 2) {
			return str;
		}
		return str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
	}

	public static void main(String[] args) throws Exception {
		LuceneTest demo = new LuceneTest();
		Analyzer analyzer = new IKAnalyzer();

		List<Article> items = new ArrayList<Article>();
		items.add(new Article("1", "中国,位于东亚,是以华夏文明为源泉", "毛毛", "中国,位于东亚,是以华夏文明为源泉、中华文化为基础并以汉族为主体民族的多民族国家,通用汉语。中国人常以龙的.",
				"" + System.currentTimeMillis()));
		items.add(new Article("2", "2015中国旅游攻略,介绍了中国旅游景点", "小刚",
				"2015中国旅游攻略,介绍了中国旅游景点、线路、美食、住宿、地图等中国旅游攻略信息,了解中国旅游等自助游攻略信息来蚂蜂窝旅游攻略网。", "" + System.currentTimeMillis()));
		items.add(new Article("3", "《中国 意大利版》精彩看点:这部拍摄于中国文革时期的纪录片", "狗狗",
				"意大利 | 207分钟 | 豆瓣评分:8.4 | 主演:Giuseppe Rinaldi |《中国 意大利版》精彩看点:这部拍摄于中国文革时期的纪录片分为三个部分。第一部分是导演在北京对一些场景的捕捉,有著名...",
				"" + System.currentTimeMillis()));
		List<Article> itemsAdd = new ArrayList<Article>();
		itemsAdd.add(new Article("4", "国足进入12强", "胡锦涛", "追加国足进入12强,感谢黄文博,感谢吴磊,感谢高洪波", "" + System.currentTimeMillis()));
		itemsAdd.add(new Article("5", "2018年俄罗斯世界杯暨", "桃桃",
				"3月29日20点15分,2018年俄罗斯世界杯暨2019年阿联酋亚洲杯联合预选赛第2阶段C组第10轮国足与卡塔尔的比赛,在陕西省体育场进行。最终,国足2-0获胜,黄博文和武磊下半场先后得分。",
				"" + System.currentTimeMillis()));
		itemsAdd.add(new Article("6", "约旦客场1-5不敌澳大利亚", "刚刚",
				"同时,约旦客场1-5不敌澳大利亚、朝鲜客场2-3不敌菲律宾,阿曼客场0-2负于伊朗,在满足这三个条件后,国足以成绩第四好的小组第二进军12强赛。",
				"" + System.currentTimeMillis()));

		List<String> listDel = new ArrayList<String>();
		for (int i = 1; i < 20; i++) {
			listDel.add(i + "");
		}

		// 索引存到内存中的目录
		//Directory directory = new RAMDirectory();
		// 索引存储到硬盘
		File file = new File("F:/lucene");
		Directory directory = FSDirectory.open(file);
		//删除索引
		demo.deleteIndexer(analyzer, directory, listDel);
		//创建索引
		demo.buildIndexer(analyzer, directory, items);
		//更新索引
		demo.updateIndexer(analyzer, directory, items);
		//追加索引
		demo.buildIndexer(analyzer, directory, itemsAdd);

		List<Article> result = demo.searchIndexer(analyzer, directory, "中国");

		for (Article item : result) {
			System.out.println(item.toString());
		}
	}
}


© 著作权归作者所有

凯文加内特
粉丝 340
博文 698
码字总数 110557
作品 0
青岛
后端工程师
私信 提问
Mybatis接口编程方式实现增删改查

前面一章Mybatis入门概述及第一个Mybatis实例实现增删改查 ,已经搭建好了eclipse,mybatis,mysql的环境,并且实现了一个简单的查询。请注意,这种方式是用SqlSession实例来直接执行已映射的S...

waj清风
2018/12/18
0
0
Nhibernate源码分析-ISession部分

ISession的实例主要用于数据的增删改查操作,本篇就详细记录Session部分的实现。 Session的继承结构: 从SessionImpl 说起,如图1继承层次 图1 ISerializable, IDeserializationCallback这两...

leoua
2016/09/26
45
0
JDBC学习系列:使用JDBC对数据库进行CRUD

一、statement对象介绍     Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。   Statement对象的execute...

HenrySun
2016/10/04
31
0
hibernate中拦截器与事件监听器的区别

关于hibrenate中拦截器与事件监听器的介绍和使用的文章可以参看这篇文章: Hibernate拦截器(Interceptor)与事件监听器(Listener) 关于在hibernate中使用拦截器实现增删改查日志记录的文章可参...

z_jordon
2015/04/22
142
0
ArrayList 和 CopyOnWriteArrayList

这篇文章的目的如下: 了解一下ArrayList和CopyOnWriteArrayList的增删改查实现原理 看看为什么说ArrayList查询快而增删慢? CopyOnWriteArrayList为什么并发安全且性能比Vector好 1. List接...

群星纪元
04/01
2
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenStack 简介和几种安装方式总结

OpenStack :是一个由NASA和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenSta...

小海bug
昨天
5
0
DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
昨天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
昨天
6
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
昨天
7
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部