更新操作如下:

注意:通过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优化的更多相关文章

  1. 解决lucene更新删除无效的问题

    个人博客 地址:http://www.wenhaofan.com/article/20180921233809 问题描述 在使用deleteDocuments,updateDocument方法根据id ...

  2. lucene两个分页操作

    基于lucene两个分页: lucene3.5查询方式(每次查询所有记录,然后取当中部分记录.这样的方式用的最多),lucene官方的解释:因为我们的速度足够快. 处理海量数据时.内存easy内存溢出 ...

  3. Android Sqlite数据库执行插入查询更新删除的操作对比

    下面是在Android4.0上,利用Sqlite数据库的insert,query,update,delete函数以及execSql,rawQuery函数执行插入,查询,更新,删除操作花费时间的对比结果 ...

  4. lucene之排序、设置权重、优化、分布式搜索(转)

    lucene之排序.设置权重.优化.分布式搜索(转) 1. 基本应用 using System;using System.Collections.Generic;using System.Text;u ...

  5. 前端性能优化--为什么DOM操作慢? 浅谈DOM的操作以及性能优化问题-重绘重排 为什么要减少DOM操作 为什么要减少操作DOM

    前端性能优化--为什么DOM操作慢?   作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩( ...

  6. EasyUI整合SpringBoot,Spring Data对数据的分页操作

    EasyUI的用法可以看中文官网,看插件是如何使用的 EasyUI中文官网 前端页面 <table id="dg" title="My Users" cl ...

  7. DOM操作的性能优化

    DOM操作的真正问题在于 每次操作都会出发布局的改变.DOM树的修改和渲染. React解决了大面积的DOM操作的性能问题,实现了一个虚拟DOM,即virtual DOM,这个我们一条条讲. 所以关于 ...

  8. 传统servelt项目之分页操作

    需求说明: • 演示最终分页效果 • 提供分页素材     • 分页的作用 • 数据量大,一页容不下 • 后台查询部分数据而不是全部数据 • 降低带宽使用,提高访问速度     • 分页的实现思路 • ...

  9. UniqueMergeTree:支持实时更新删除的 ClickHouse 表引擎

    UniqueMergeTree 开发的业务背景 首先,我们看一下哪些场景需要用到实时更新. 我们总结了三类场景: 第一类是业务需要对它的交易类数据进行实时分析,需要把数据流同步到 ClickHouse ...

随机推荐

  1. python3.6.1 安装PyQt5,以及配置QTDesigner,PyUIC

    本人主机win10 64,python版本是3.6.1 64 注意python版本一定得是3.6.1 64位的,我原来电脑是安装的32位的,浪费了好长时间 (MMP) 第一步:安装python,自己官 ...

  2. 玩转DOM遍历——用NodeIterator实现getElementById,getElementsByTagName方法

    先声明一下DOM2中NodeIterator和TreeWalker这两类型真的只是用来玩玩的,因为性能不行遍历起来超级慢,在JS中基本用不到它们,除了<高程>上有两三页对它的讲解外,谷歌的 ...

  3. 从原型链看DOM--Element类型

    Element类型用于表现XML或HTML元素,提供对元素标签名,子节点及特性的访问.原型链的继承关系为 某节点元素.__proto__->(HTML某元素Element.prototype)- ...

  4. UVA10700:Camel trading(栈和队列)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68990#problem/J 题目大意: 给一个没有加上括号的表达式且只有+ , ...

  5. Oracle记录登录失败的触发器

    前言:实现的功能主要是,oracle登录成功记录登录用户ip地址,登录失败记录登录失败ip地址 1,需要建立一个触发器记录登录成功的客户端用户的ip地址 大家都知道在v$session 中记录着客户端 ...

  6. 使用jQuery为文本框、单选框、多选框、下拉框、下拉多选框设值及返回值的处理

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  7. Android Studio Tips

    1. 可以通过ctrl+shift+a,然后输入reformat,就能看到对应的快捷键. 如果记不得快捷键了,都可以通过ctrl+shift+a来查找. 2. [Androidstudio]的坑之[@ ...

  8. Mock Server 之 moco-runner 使用指南一

    文章出处http://ju.outofmemory.cn/entry/96866 用以下命令可以启动moco-runner 服务 java -jar moco-runner-<version&g ...

  9. beego——发行部署

    开发模式 通过bee创建的项目,beego默认情况下是开发模式. 我们可以通过如下的方式改变我们的模式: beego.RunMode = "prod" 或者我们在conf/app. ...

  10. 读取Android设备的MAC地址

    读取Android设备的MAC地址   AndroidUtil.java package com.csdn.android.util; import com.csdn.android.framewor ...