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 ...
随机推荐
- Android开发:带动画的分享效果
这几天做了个带动画的分享页面.如今把它分享出来,假设你认为实用,请直接使用,避免反复造轮子 先看下效果图 认为仅仅是看效果图不明显.那么用手机扫描以下的二维码下载安装包:
- solr 查询
1.常用查询参数说明 q - 查询字符串,必须的. fl - 指定返回那些字段内容,用逗号或空格分隔多个. start - 返回第一条记录在完整找到结果中的偏移位置,0开始,一般分页用. rows - ...
- finecms万能标签list列表使用方法
我们在用finecms建站时经常会用到调用文章列表的功能,这时我们可以用万能标签list来实现,当然还可以调用其他一些数据,下面我们就来看看list函数的相关参数和使用方法 action 支持&quo ...
- IT开发工程师的悲哀现状和可能前途
IT开发工程师的悲哀现状和可能前途 本文所指的开发工程师,仅指程序开发人员和以数字电路开发为主的电子工程师.当你选择计算机或者电子.自控等专业进入大学时,你本来还是有机会从事其它行业的,可你毕业时执迷 ...
- jQuery中on()方法用法实例
这篇文章主要介绍了jQuery中on()方法用法,实例分析了on()方法的功能.定义及在匹配元素上绑定一个或者多个事件处理函数的使用技巧,需要的朋友可以参考下 本文实例讲述了jQuery中on()方法 ...
- kubernetes清除状态为Evicted的pod
kubectl get pods | grep Evicted | awk '{print $1}' | xargs kubectl delete pod 清除脚本 #!/bin/bash for p ...
- Java将数据写进excel
Java将数据写进excel Java将数据写进excel class User { private String name ; private String password; public Use ...
- 漫谈DOM 事件流的三个阶段
一丶 流 什么是流? 比如 react 中的单项数据流,Node.js 中的流,或者本文中的 DOM 事件流,都是流的具体体现.专业地讲,流是程序输入或输出的一个连续的字节序列:通俗地讲,流是有方向的 ...
- PKU 1226 Substrings(字符串匹配+暴搜KMP模板)
原题大意:原题链接 给出n个字符串,找出一个最长的串s,使s或者s的反转字符串(只要其中一个符合就行)同时满足是这n个串的子串. 对于样例,第一组ABCD BCDFF BRCD最长的串就是CD; ...
- PKU 3318 Matrix Multiplication(随机化算法||状态压缩)
题目大意:原题链接 给定三个n*n的矩阵A,B,C,验证A*B=C是否成立. 所有解法中因为只测试一组数据,因此没有使用memset清零 Hint中给的傻乎乎的TLE版本: #include<c ...