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 ...
随机推荐
- Python高级特性(3): Classes和Metaclasses(转)
原文:Python高级特性(3): Classes和Metaclasses 类和对象 类和函数一样都是Python中的对象.当一个类定义完成之后,Python将创建一个“类对象”并将其赋值给一个同名变 ...
- restfull规范
web服务交互 我们在浏览器中能看到的每个网站,都是一个web服务.那么我们在提供每个web服务的时候, 都需要前后端交互,前后端交互就一定有一些实现方案,我们通常叫web服务交互方案. 目前主流的三 ...
- mmu介绍
arm exynos4412平台mmu配置以及的简单创建. 1.mmu的全称是Memory Management Unit(内存管理单元) 2.mmu所在位置.mmu再arm核心.他不是一个外设,他是 ...
- git提交到远程虚拟机
git到自己的虚拟机中第一步:打通git(一)Linux中(ip为10.1.8.1)1.安装git如:Ubuntu中安装gitapt install git 2.Ubuntu中添加git用户sudo ...
- DIV+CSS如何让文字垂直居中?
在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...
- 线程管理coroutine
非常好用的协程库,也可以当作线程管理来用 #include "coroutine.h" #include <stdio.h> struct args { int n; ...
- Python eval() 的使用:将字符串转换为列表,元祖,字典
eval() 函数用来执行一个字符串表达式,并返回表达式的值. 语法 以下是 eval() 方法的语法: eval(expression[, globals[, locals]]) 参数 expres ...
- 在debian9上安装mongodb
MongoDB是一个免费的开源NoSQL文档数据库,在现代Web应用程序中常用.在本教程中,您将安装MongoDB,管理其服务,并可选择启用远程访问.要遵循这个...... 介绍 MongoDB是一个 ...
- Linux系统——date命令
date命令 作用:用来显示或设定系统的日期与时间. 参数 -d<字符串>:显示字符串所指的日期与时间.字符串前后必须加上双引号: -s<字符串>:根据字符串来设置日期与时间. ...
- 001-搭建spring boot项目
1.第一步.file--new--project. 2.spring initializr--project sdk--default--next 3. 4.spring boot--选择依赖项--n ...