zoukankan      html  css  js  c++  java
  • Lucene 更新、删除、分页操作以及IndexWriter优化

    更新操作如下:

    注意:通过lukeall-1.0.0.jar 查看软件,我们可以看到,更新其实是先删除在插入, 前面我们知道索引库中有两部分的内容组成,一个是索引文件,另一个是目录文件, 目前我们更新, 只是真对Document, 但是Term部分并没有同步, 所以等会需要优化索引库即可

     1 // 把商品信息添加到索引库中
     2     public void updateGoods(Goods goods){
     3         // 创建一个indexWriter
     4         IndexWriter indexWriter=null;
     5         try {
     6             indexWriter=new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(),MaxFieldLength.LIMITED);
     7             /*
     8              * 先删除文档,在追加文档
     9              * Term: 删除文档的条件,一般来说我们都是根据主键删除
    10              * doc:追加的新文档
    11              * */
    12             indexWriter.updateDocument(new Term("gid",goods.getGid().toString()),DocumentUtil.GoodsToDocument(goods));
    13             // 提交
    14             indexWriter.commit();
    15         } catch (IOException e) {
    16             e.printStackTrace();
    17             throw new RuntimeException(e);
    18         }finally{
    19             try {
    20                 // 更新操作的时候,原来的document已经删除,但是原来term并没有同步
    21                 // 需要同步:otimize:让term与document同步
    22                 indexWriter.optimize();
    23                 indexWriter.close();
    24             } catch (Exception e) {
    25                 e.printStackTrace();
    26                 throw new RuntimeException(e);
    27             }
    28         }
    29 
    30     }

    注意 :

    注意更新操作和删除操作:都要进行optimize()方法优化,否则只会更新索引数据,不会更新索引目录. 以后可以把此操作放到独立的线程中定时执行

    删除操作

     1     public void deleteGoods(int gid){
     2         // 创建一个indexWriter
     3         IndexWriter indexWriter=null;
     4         try {
     5             indexWriter=new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(),MaxFieldLength.LIMITED);
     6             indexWriter.deleteDocuments(new Term("gid",gid+""));
     7             // 提交
     8             indexWriter.commit();
     9         } catch (IOException e) {
    10             e.printStackTrace();
    11             throw new RuntimeException(e);
    12         }finally{
    13             try {
    14                 indexWriter.optimize();
    15                 indexWriter.close();
    16             } catch (Exception e) {
    17                 e.printStackTrace();
    18                 throw new RuntimeException(e);
    19             }
    20         }
    21 
    22     }

    分页查询

     1 public List<Goods> query(String gname,int currentPage){
     2         int size=5;  // 2*5--->10条
     3         List<Goods> goodsList=new ArrayList<Goods>();
     4         // 创建查询工具类
     5         IndexSearcher indexSearcher=null;
     6         try {
     7             QueryParser parse=new QueryParser(Version.LUCENE_30,"gname",Configuraction.getAnalyzer());
     8             // 解析要查询的关键字:返回的是Query类型
     9             Query query=parse.parse(gname);
    10             indexSearcher=new IndexSearcher(Configuraction.getDirectory());
    11             // indexSearch做查询操作: n 用户期望查询结果数,后面做分页使用
    12             // 0 1 2 3 4 [5 6 7 8 9]
    13             TopDocs topDocs=indexSearcher.search(query,currentPage*size);
    14             /*
    15              * TopDocs:
    16              *     totalHits: 实际查询到的结果数
    17              *     scoreDocs[]: 存储了所有符合条件的document 编号
    18              * */
    19             System.out.println("用户期待的数:" + currentPage*size);
    20             System.out.println("索引库实际拥有结果数为:" + topDocs.totalHits);
    21             // 存储的是document在lucenen中的逻辑编号
    22             ScoreDoc[] docs=topDocs.scoreDocs;  //[0]=0 [1]=1
    23             System.out.println("真实拿出来了文档编号数" + docs.length);
    24             /*
    25              * ScoreDoc:
    26              *     doc: 文档逻辑编号
    27              *     score: 当前文档得分
    28              *
    29              * */
    30             for(int i=(currentPage-1)*size;i<docs.length;i++){
    31                 //System.out.println("文档的编号:" + docs[i].doc);
    32                 //System.out.println("此文档的得分:" + docs[i].score);
    33                 // 通过文档的编号获取真正的文档
    34                 Document doc=indexSearcher.doc(docs[i].doc);
    35                 goodsList.add(DocumentUtil.DocumentToGoods(doc));
    36             }
    37         } catch (Exception e) {
    38             e.printStackTrace();
    39             throw new RuntimeException(e);
    40         }
    41         return goodsList;
    42     }

    分页的原理分析:

    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即可

    1 @Test
    2 public void testIndexWriter()throws Exception{
    3         IndexWriter    indexWriter = new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(), MaxFieldLength.LIMITED);
    4         IndexWriter    indexWriter2 = new IndexWriter(Configuraction.getDirectory(),Configuraction.getAnalyzer(), MaxFieldLength.LIMITED);
    5     }

    异常信息如下:

     1 org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@D:workspacelucene3.0indexDatawrite.lock 

    IndexWriter优化

     1 package cn.index;
     2 
     3 import java.io.IOException;
     4 
     5 import org.apache.lucene.index.CorruptIndexException;
     6 import org.apache.lucene.index.IndexWriter;
     7 import org.apache.lucene.index.IndexWriter.MaxFieldLength;
     8 import org.apache.lucene.search.IndexSearcher;
     9 
    10 /*
    11  * 把indexWriter:设置全局唯一的,项目只负责使用, 由LuceneUtil负责创建和销毁
    12  *
    13  * */
    14 
    15 public class LuceneUtil {
    16 
    17     private static IndexWriter indexWriter = null;
    18     // 每一个indexSearcher在创建的时候就给索引库拍了一个快照,后面对索引库更新的操作都不能识别
    19     // 也类MYSQL:隔离级别3: 可重复读
    20     private static IndexSearcher indexSearcher=null;
    21 
    22     public static IndexSearcher getIndexSearcher() {
    23         // 判断是否有IndexSearcher如果没有则创建一个
    24         if(indexSearcher==null){
    25             synchronized(LuceneUtil.class){
    26                 if(indexSearcher==null){
    27                     try {
    28                         indexSearcher=new IndexSearcher(Configuraction.getDirectory());
    29                     } catch (Exception e) {
    30                         // TODO Auto-generated catch block
    31                         e.printStackTrace();
    32                         new RuntimeException(e);
    33                     }
    34                 }
    35             }
    36         }
    37         return indexSearcher;
    38     }
    39 
    40     public static IndexWriter getIndexWriter() {
    41         // 获取IndexWriter的时候说明要操作索引库,此时关闭前面的indexSearch
    42         // indexSearcher
    43         closeIndexSearch(indexSearcher);
    44         // 把全局变量设置为null
    45         indexSearcher=null;
    46         return indexWriter;
    47     }
    48 
    49     private static void closeIndexWriter(IndexWriter indexWriter){
    50         if(indexWriter!=null){
    51             try {
    52                 indexWriter.optimize();
    53                 indexWriter.close();
    54             } catch (IOException e) {
    55                 e.printStackTrace();
    56                 throw new RuntimeException(e);
    57             }
    58         }
    59     }
    60 
    61     private static void closeIndexSearch(IndexSearcher indexSearcher){
    62         if(indexSearcher!=null){
    63             try {
    64                 indexSearcher.close();
    65             } catch (IOException e) {
    66                 e.printStackTrace();
    67                 throw new RuntimeException(e);
    68             }
    69         }
    70     }
    71 
    72     static {
    73         try {
    74             // 加载LuceneUtil执行indexWriter创建
    75             indexWriter = new IndexWriter(Configuraction.getDirectory(),
    76                     Configuraction.getAnalyzer(), MaxFieldLength.LIMITED);
    77             // 程序关闭的时候要释放资源
    78             Runtime.getRuntime().addShutdownHook(new Thread(){
    79                 public void run(){
    80                     System.out.println("----run-----");
    81                     // 程序结束的时候关闭indexWriter
    82                     closeIndexWriter(indexWriter);
    83                 }
    84             });
    85         } catch (Exception e) {
    86             e.printStackTrace();
    87             throw new RuntimeException(e);
    88         }
    89     }
    90 }

     

  • 相关阅读:
    HTML5 模板推荐
    OpenCV初探
    微信开放框架-UCToo
    ProFTPD 初探
    移动开发者服务平台-友盟
    线程原理理解
    JVM参数及性能调优
    GC——垃圾回收
    JVM内存模型
    php常用 随机数
  • 原文地址:https://www.cnblogs.com/wh1520577322/p/10096520.html
Copyright © 2011-2022 走看看