Lucene 更新、删除、分页操作以及IndexWriter优化
更新操作如下:
注意:通过lukeall-1.0.0.jar 查看软件,我们可以看到,更新其实是先删除在插入, 前面我们知道索引库中有两部分的内容组成,一个是索引文件,另一个是目录文件, 目前我们更新, 只是真对Document, 但是Term部分并没有同步, 所以等会需要优化索引库即可
// 把商品信息添加到索引库中
public void updateGoods(Goods goods){
// 创建一个indexWriter
IndexWriter indexWriter=null;
try {
indexWriter=new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(),MaxFieldLength.LIMITED);
/*
* 先删除文档,在追加文档
* Term: 删除文档的条件,一般来说我们都是根据主键删除
* doc:追加的新文档
* */
indexWriter.updateDocument(new Term("gid",goods.getGid().toString()),DocumentUtil.GoodsToDocument(goods));
// 提交
indexWriter.commit();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
try {
// 更新操作的时候,原来的document已经删除,但是原来term并没有同步
// 需要同步:otimize:让term与document同步
indexWriter.optimize();
indexWriter.close();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
} }
注意 :
注意更新操作和删除操作:都要进行optimize()方法优化,否则只会更新索引数据,不会更新索引目录. 以后可以把此操作放到独立的线程中定时执行
删除操作
public void deleteGoods(int gid){
// 创建一个indexWriter
IndexWriter indexWriter=null;
try {
indexWriter=new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(),MaxFieldLength.LIMITED);
indexWriter.deleteDocuments(new Term("gid",gid+""));
// 提交
indexWriter.commit();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
try {
indexWriter.optimize();
indexWriter.close();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
} }
分页查询
public List<Goods> query(String gname,int currentPage){
int size=5; // 2*5--->10条
List<Goods> goodsList=new ArrayList<Goods>();
// 创建查询工具类
IndexSearcher indexSearcher=null;
try {
QueryParser parse=new QueryParser(Version.LUCENE_30,"gname",Configuraction.getAnalyzer());
// 解析要查询的关键字:返回的是Query类型
Query query=parse.parse(gname);
indexSearcher=new IndexSearcher(Configuraction.getDirectory());
// indexSearch做查询操作: n 用户期望查询结果数,后面做分页使用
// 0 1 2 3 4 [5 6 7 8 9]
TopDocs topDocs=indexSearcher.search(query,currentPage*size);
/*
* TopDocs:
* totalHits: 实际查询到的结果数
* scoreDocs[]: 存储了所有符合条件的document 编号
* */
System.out.println("用户期待的数:" + currentPage*size);
System.out.println("索引库实际拥有结果数为:" + topDocs.totalHits);
// 存储的是document在lucenen中的逻辑编号
ScoreDoc[] docs=topDocs.scoreDocs; //[0]=0 [1]=1
System.out.println("真实拿出来了文档编号数" + docs.length);
/*
* ScoreDoc:
* doc: 文档逻辑编号
* score: 当前文档得分
*
* */
for(int i=(currentPage-1)*size;i<docs.length;i++){
//System.out.println("文档的编号:" + docs[i].doc);
//System.out.println("此文档的得分:" + docs[i].score);
// 通过文档的编号获取真正的文档
Document doc=indexSearcher.doc(docs[i].doc);
goodsList.add(DocumentUtil.DocumentToGoods(doc));
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return goodsList;
}
分页的原理分析:
Search(query,10000),和Search(query,1)都不会影响topDocs.totalHits这个结果, 这个结果是Lucene索引库命中率的次数(也就是命中的Tearm的数量)那么可能会出现 totalHits大或者currentPage * PAGE_SIZE大的情况. 所以真正截取的时候,选最小的.int endNuM = Math.min(topDocs.totalHits, currentPage * PAGE_SIZE);而且分页的话,不是从开始处,开始所以真正的代码为:for (int i = (currentPage - 1) * PAGE_SIZE; i < endNuM; i++)
IndexWriter存在的问题
IndexWriter: 则必须要用单态模式独占.因为每一个Writer都需要lock文件,IndexWriter本身是操作类,支持多线程,所以一个全局的IndexWriter即可
@Test
public void testIndexWriter()throws Exception{
IndexWriter indexWriter = new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(), MaxFieldLength.LIMITED);
IndexWriter indexWriter2 = new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(), MaxFieldLength.LIMITED);
}
异常信息如下:
org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@D:\workspace\lucene3.0\indexData\write.lock
IndexWriter优化
package cn.index; import java.io.IOException; import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.search.IndexSearcher; /*
* 把indexWriter:设置全局唯一的,项目只负责使用, 由LuceneUtil负责创建和销毁
*
* */ public class LuceneUtil { private static IndexWriter indexWriter = null;
// 每一个indexSearcher在创建的时候就给索引库拍了一个快照,后面对索引库更新的操作都不能识别
// 也类MYSQL:隔离级别3: 可重复读
private static IndexSearcher indexSearcher=null; public static IndexSearcher getIndexSearcher() {
// 判断是否有IndexSearcher如果没有则创建一个
if(indexSearcher==null){
synchronized(LuceneUtil.class){
if(indexSearcher==null){
try {
indexSearcher=new IndexSearcher(Configuraction.getDirectory());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
new RuntimeException(e);
}
}
}
}
return indexSearcher;
} public static IndexWriter getIndexWriter() {
// 获取IndexWriter的时候说明要操作索引库,此时关闭前面的indexSearch
// indexSearcher
closeIndexSearch(indexSearcher);
// 把全局变量设置为null
indexSearcher=null;
return indexWriter;
} private static void closeIndexWriter(IndexWriter indexWriter){
if(indexWriter!=null){
try {
indexWriter.optimize();
indexWriter.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
} private static void closeIndexSearch(IndexSearcher indexSearcher){
if(indexSearcher!=null){
try {
indexSearcher.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
} static {
try {
// 加载LuceneUtil执行indexWriter创建
indexWriter = new IndexWriter(Configuraction.getDirectory(),
Configuraction.getAnalyzer(), MaxFieldLength.LIMITED);
// 程序关闭的时候要释放资源
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
System.out.println("----run-----");
// 程序结束的时候关闭indexWriter
closeIndexWriter(indexWriter);
}
});
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
Lucene 更新、删除、分页操作以及IndexWriter优化的更多相关文章
- 解决lucene更新删除无效的问题
个人博客 地址:http://www.wenhaofan.com/article/20180921233809 问题描述 在使用deleteDocuments,updateDocument方法根据id ...
- lucene两个分页操作
基于lucene两个分页: lucene3.5查询方式(每次查询所有记录,然后取当中部分记录.这样的方式用的最多),lucene官方的解释:因为我们的速度足够快. 处理海量数据时.内存easy内存溢出 ...
- Android Sqlite数据库执行插入查询更新删除的操作对比
下面是在Android4.0上,利用Sqlite数据库的insert,query,update,delete函数以及execSql,rawQuery函数执行插入,查询,更新,删除操作花费时间的对比结果 ...
- lucene之排序、设置权重、优化、分布式搜索(转)
lucene之排序.设置权重.优化.分布式搜索(转) 1. 基本应用 using System;using System.Collections.Generic;using System.Text;u ...
- 前端性能优化--为什么DOM操作慢? 浅谈DOM的操作以及性能优化问题-重绘重排 为什么要减少DOM操作 为什么要减少操作DOM
前端性能优化--为什么DOM操作慢? 作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩( ...
- EasyUI整合SpringBoot,Spring Data对数据的分页操作
EasyUI的用法可以看中文官网,看插件是如何使用的 EasyUI中文官网 前端页面 <table id="dg" title="My Users" cl ...
- DOM操作的性能优化
DOM操作的真正问题在于 每次操作都会出发布局的改变.DOM树的修改和渲染. React解决了大面积的DOM操作的性能问题,实现了一个虚拟DOM,即virtual DOM,这个我们一条条讲. 所以关于 ...
- 传统servelt项目之分页操作
需求说明: • 演示最终分页效果 • 提供分页素材 • 分页的作用 • 数据量大,一页容不下 • 后台查询部分数据而不是全部数据 • 降低带宽使用,提高访问速度 • 分页的实现思路 • ...
- UniqueMergeTree:支持实时更新删除的 ClickHouse 表引擎
UniqueMergeTree 开发的业务背景 首先,我们看一下哪些场景需要用到实时更新. 我们总结了三类场景: 第一类是业务需要对它的交易类数据进行实时分析,需要把数据流同步到 ClickHouse ...
随机推荐
- Ponds----hdu5438(拓扑排序)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5438 题意:有n个池塘和m个管道:每个池塘的价值是v, 现在由于资金问题要删除池塘:但是删除的池塘 ...
- 前端 html border-right: 1px solid red;
后边框 加粗 实体线 红色 border-right: 1px solid red;
- redis实现自动输入完成(八)
1. 介绍 当我们在京东商城的搜索框,输入想要搜索的内容,比如你想要搜索"热水瓶",刚输入一个"热"字,就会出现一个下拉框,列出了很多以"热" ...
- mysql应用实例
目录: 表结构 sql练习 1.表结构 SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- T ...
- Linux文件权限分析
一.用户组概念 在linux系统中,每个用户必属于一个组,不能独立于组之外.每个文件都有所有者,所在组和其他组这三个概念. (1)所有者:一般为文件的创建者,谁创建了该文件,就成为了该文件的所有者, ...
- 深入理解Oracle调试事件:10046事件详解
10046事件是SQL_TRACE的扩展,被戏称为"吃了兴奋剂的SQL_TRACE" 有效的追踪级别: ① 0级:SQL_TRACE=FASL ...
- Python 新手常犯错误(第一部分)转载
觉得这篇文章针对python的默认参数写的不错,翻译的也不错,故转载下. 原文链接: Amir Rachum 翻译: 伯乐在线- 伯乐在线读者译文链接: http://blog.jobbole.c ...
- Dictionary 初始化数据
Dictionary<string, string> dic = new Dictionary<string, string>() { { ...
- Oracle Union Union All 对查询结果集操作
在Oracle中提供了三种类型的集合操作: 并(UNION).交(INTERSECT).差(MINUS) Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: Union Al ...
- javaScript动画2 scroll家族
offsetWidth和offsetHight (检测盒子自身宽高+padding+border) 这两个属性,他们绑定在了所有的节点元素上.获取之后,只要调用这两个属性,我们就能够获取元素节点的宽和 ...