分享

关于Lucene 3.0升级到Lucene 4.x 记录


问题导读

1.如何实现构建RAMDirectory,将索引放入内存中?
2.自定义分词:3.0 ,4.x有什么不同?
3. 4.x 如何实现构建多索引目录?






 最近,需要对项目进行lucene版本升级。而原来项目时基于lucene 3.0的,很古老的一个版本的了。在老版本中中,我们主要用了几个lucene的东西:

  1、查询lucene多目录索引。

  2、构建RAMDirectory,把索引放到内存中,以提高检索效率。

  3、构建Lucene自定义分词。

  4、修改Lucene默认的打分算法。

   下面,将代码改造前和改造后做一对比:

    1. 搜索多索引目录

   3.0 构建多索引目录: 


  1. // 初始化全国索引
  2.     private boolean InitGlobal(String strRootPath) {
  3.         try {
  4.             IndexSearcher[] searchers = new IndexSearcher[2];
  5.             
  6.             MultiSearcher globalSearcher = null;
  7.             if (Configution.IsMMap.equalsIgnoreCase("true")) {
  8.                 searchers[0] = new IndexSearcher(new RAMDirectory(FSDirectory
  9.                         .open(new File(strRootPath + "/" + GLABOL_INDEX))));
  10.                 searchers[1] = new IndexSearcher(new RAMDirectory(FSDirectory
  11.                         .open(new File(strRootPath + "/" + BUS_INDEX))));
  12. //                searchers[2] = new IndexSearcher(new RAMDirectory(FSDirectory
  13. //                        .open(new File(strRootPath + "/" + LU_INDEX))));
  14.                 globalSearcher =  new MultiSearcher(searchers);
  15.             } else {
  16.                 searchers[0] = new IndexSearcher(FSDirectory.open(new File(
  17.                         strRootPath + "/" + GLABOL_INDEX)));
  18.                 searchers[1] = new IndexSearcher(FSDirectory.open(new File(
  19.                         strRootPath + "/" + BUS_INDEX)));
  20. //                searchers[2] = new IndexSearcher(FSDirectory.open(new File(
  21. //                        strRootPath + "/" + LU_INDEX)));
  22.                
  23.                 globalSearcher =  new MultiSearcher(searchers);
  24.             }
  25.             System.out.println("finish Global");
  26.             m_mapIndexName2Searcher.put("0", globalSearcher);
  27.             m_mapAdmin2IndexName.put("0", "0");
  28.             return true;
  29.         } catch (Exception e) {
  30.             e.printStackTrace();
  31.             SearchLog.SearchLog.error("全国索引初始化异常");
  32.             return false;
  33.         }
  34.     }
复制代码


Ok,使用MultiSearcher,这是lucene低版本搜索多索引的解决方案。但是在高版本,MutiSearcher这个类本身都删除了,折腾我很长时间。可见以版本帝著称的Lucene代码设计不是太好。整个lucene代码,接口使用很少,大多是类和抽象类。

       4.x 构建多索引目录: 


  1. // 初始化全国索引
  2. private boolean InitGlobal(String strRootPath) {
  3.     try {
  4.          
  5.         IndexSearcher globalSearcher = null;
  6.         if (Configution.IsMMap.equalsIgnoreCase("true")) {
  7.             
  8.             IndexReader irGlobal = DirectoryReader.open(new RAMDirectory(FSDirectory
  9.                     .open(new File(strRootPath + "/" + GLABOL_INDEX)),new IOContext()));
  10.             
  11.             IndexReader irBus = DirectoryReader.open(new RAMDirectory(FSDirectory
  12.                     .open(new File(strRootPath + "/" + BUS_INDEX)),new IOContext()));
  13.             
  14.             MultiReader mr = new MultiReader(irGlobal,irBus);
  15.             
  16.             globalSearcher =  new IndexSearcher(mr);//new MultiSearcher(searchers);
  17.         } else {
  18.             IndexReader irGlobal = DirectoryReader.open(FSDirectory
  19.                     .open(new File(strRootPath + "/" + GLABOL_INDEX)));
  20.             
  21.             IndexReader irBus = DirectoryReader.open(FSDirectory
  22.                     .open(new File(strRootPath + "/" + BUS_INDEX)));
  23.             
  24.             MultiReader mr = new MultiReader(irGlobal,irBus);
  25.             globalSearcher =   new IndexSearcher(mr);//new MultiSearcher(searchers);
  26.         }
  27.         System.out.println("finish Global");
  28.         m_mapIndexName2Searcher.put("0", globalSearcher);
  29.         m_mapAdmin2IndexName.put("0", "0");
  30.         return true;
  31.     } catch (Exception e) {
  32.         e.printStackTrace();
  33.         SearchLog.SearchLog.error("全国索引初始化异常");
  34.         return false;
  35.     }
  36. }
复制代码


 ok 改造后,直接用IndexSearcher替代MultiSearcher,通过传入MultiReader来检索多个索引目录。

  2、构建RAMDirectory,将索引放入内存中。

    3.0 构建内存索引目录:


  1.   searchers[0] = new IndexSearcher(new RAMDirectory(FSDirectory
  2.                         .open(new File(strRootPath + "/" + GLABOL_INDEX))));
  3.                 searchers[1] = new IndexSearcher(new RAMDirectory(FSDirectory
  4.                         .open(new File(strRootPath + "/" + BUS_INDEX))));
复制代码


 直接将Diretory作为RAMDirectory的构造函数,注意这个动作有坑,如果数据量大,你要等很久的!

    4.x 构建内存索引目录:

  1. IndexReader irGlobal = DirectoryReader.open(new RAMDirectory(FSDirectory
  2.                         .open(new File(strRootPath + "/" + GLABOL_INDEX)),new IOContext()));
  3.                
  4.                 IndexReader irBus = DirectoryReader.open(new RAMDirectory(FSDirectory
  5.                         .open(new File(strRootPath + "/" + BUS_INDEX)),new IOContext()));
  6.                
  7.                 MultiReader mr = new MultiReader(irGlobal,irBus);
复制代码


在4.x中,安装3.0构造方法是不行的,还需要传入一个IOContext对象,汗~~~~~~~~~~~~~~~~

 3、自定义分词:

    3.0 自定义分词:

  1. public class SingleAnalyzer extends Analyzer {
  2.     /**
  3.      * @param args
  4.      */
  5.    
  6.         public TokenStream tokenStream(String fieldName, Reader reader){
  7.             TokenStream result = null;
  8.             if(fieldName.equals("name"))
  9.             {
  10.                 result = new SingleTokenizer(reader);
  11.             }
  12.             if(fieldName.equals("totalcity"))
  13.             {
  14.                 result = new IKTokenizer(reader, false);
  15.             }
  16.         
  17. //        result = new StandardFilter(result);
  18. //        result = new LowerCaseFilter(result);
  19.     //    result = new StopFilter(result, stopSet);
  20.         return result;
  21.         }
  22.    
  23.     public static void main(String[] args) {
  24.         // TODO Auto-generated method stub
  25.     }
  26. }
复制代码


 重写tokenStream方法即可,很简单。

    4.x自定义分词:


  1. public class SingleAnalyzer extends Analyzer {
  2.     /**
  3.      * @param args
  4.      */
  5.    
  6. //        public TokenStream tokenStream(String fieldName, Reader reader){
  7. //            TokenStream result = null;
  8. //            if(fieldName.equals("name"))
  9. //            {
  10. //                result = new SingleTokenizer(reader);
  11. //            }
  12. //            if(fieldName.equals("totalcity"))
  13. //            {
  14. //                result = new IKTokenizer(reader, false);
  15. //            }
  16. //        
  17. ////        result = new StandardFilter(result);
  18. ////        result = new LowerCaseFilter(result);
  19. //    //    result = new StopFilter(result, stopSet);
  20. //        return result;
  21. //        }
  22.     @Override
  23.     protected TokenStreamComponents createComponents(String fieldName,
  24.             Reader reader) {
  25.         // TODO Auto-generated method stub
  26. //         final Tokenizer source = new ChineseTokenizer(reader);
  27. //          return new TokenStreamComponents(source, new ChineseFilter(source));
  28.         Tokenizer source = null;
  29.         if(fieldName.equals("name")){
  30.             source = new SingleTokenizer(reader);
  31.         }else if(fieldName.equals("totalcity")){
  32.             source = new IKTokenizer(reader, false);
  33.         }
  34.         return new TokenStreamComponents(source, source);
  35.     }
  36. }
复制代码


OK,在4.x中你需要重写createComponents方法。

  4、打分算法:

    3.x和4.x打分算法变化不大,但是命名空间发生了变化,汗~~~~~~~~~~~~

           3.x 命名空间:引入:import org.apache.lucene.search.DefaultSimilarity,命名空间在:org.apache.lucene.search

           4.x命名空间:引入:import org.apache.lucene.search.similarities.*,命名空间在:org.apache.lucene.search.similarities。

  5、查询表达式:主要体现在TermRangeQuery上,3.x版本的一个参数是string类型,但是在4.x版本变成了包了string一层的BytesRef,还有其他很多细节变化

    3.x TermRangerQuery: 


  1. String left = Long
  2.                     .toString((long) (rcBound.m_dLeft * COORDINATE_SCALE_FACTOR));
  3.             String right = Long
  4.                     .toString((long) (rcBound.m_dRight * COORDINATE_SCALE_FACTOR));
  5.             String top = Long
  6.                     .toString((long) (rcBound.m_dTop * COORDINATE_SCALE_FACTOR));
  7.             String bottom = Long
  8.                     .toString((long) (rcBound.m_dBottom * COORDINATE_SCALE_FACTOR));
  9.             
  10.             
  11.             TermRangeQuery query1 = new TermRangeQuery("lon", left, right,
  12.                     true, true);
  13.             TermRangeQuery query2 = new TermRangeQuery("lat", bottom, top,
  14.                     true, true);
  15.             searchQuery.add(query1, BooleanClause.Occur.MUST);
  16.             searchQuery.add(query2, BooleanClause.Occur.MUST);
复制代码


   4.x TermRangerQuery:  

  1. String left = Long
  2.                     .toString((long) (rcBound.m_dLeft * COORDINATE_SCALE_FACTOR));
  3.             String right = Long
  4.                     .toString((long) (rcBound.m_dRight * COORDINATE_SCALE_FACTOR));
  5.             String top = Long
  6.                     .toString((long) (rcBound.m_dTop * COORDINATE_SCALE_FACTOR));
  7.             String bottom = Long
  8.                     .toString((long) (rcBound.m_dBottom * COORDINATE_SCALE_FACTOR));
  9.             
  10.             
  11.             BytesRef brLeft = new BytesRef(left);
  12.             BytesRef brRight = new BytesRef(right);
  13.             BytesRef brBottom = new BytesRef(bottom);
  14.             BytesRef brTop = new BytesRef(top);
  15.             TermRangeQuery query1 = new TermRangeQuery("lon",
  16.                     brLeft, brRight, true, true);
  17.             TermRangeQuery query2 = new TermRangeQuery("lat",
  18.                     brBottom, brTop, true, true);
  19.             searchQuery.add(query1, BooleanClause.Occur.MUST);
  20.             searchQuery.add(query2, BooleanClause.Occur.MUST);
复制代码
 6、关闭IndexSearcher

    3.x 关闭IndexSearcher直接调用close方法即可:

  1. public void UnInit() {
  2.         if (!m_bIsInit)
  3.             return;
  4.         Iterator iter = m_mapIndexName2Searcher.keySet().iterator();
  5.         while (iter.hasNext()) {
  6.             String key = (String) iter.next();
  7.             MultiSearcher val = (MultiSearcher) m_mapIndexName2Searcher
  8.                     .get(key);
  9.             try {
  10.    
  11.                 val.close();//关闭IndexSearcher
  12.             } catch (IOException e) {
  13.                 e.printStackTrace();
  14.                 SearchLog.SearchLog.error("分级索引关闭异常");
  15.             }
  16.         }
  17.         m_mapIndexName2Searcher.clear();
  18.         m_mapAdmin2IndexName.clear();
  19.         m_mapIndexName2Searcher = null;
  20.         m_mapAdmin2IndexName = null;
  21.         m_bIsInit = false;
  22.     }
复制代码
 4.x 关闭IndexSearcher 没有直接close的方法,需要getIndexReader 然后调用IndexReader的close方法:
  1. public void UnInit() {
  2.         if (!m_bIsInit)
  3.             return;
  4.         Iterator iter = m_mapIndexName2Searcher.keySet().iterator();
  5.         while (iter.hasNext()) {
  6.             String key = (String) iter.next();
  7.             IndexSearcher val = (IndexSearcher) m_mapIndexName2Searcher
  8.                     .get(key);
  9.             try {
  10.                 val.getIndexReader().close();//关闭IndexSearcher
  11.             } catch (IOException e) {
  12.                 e.printStackTrace();
  13.                 SearchLog.SearchLog.error("分级索引关闭异常");
  14.             }
  15.         }
  16.         m_mapIndexName2Searcher.clear();
  17.         m_mapAdmin2IndexName.clear();
  18.         m_mapIndexName2Searcher = null;
  19.         m_mapAdmin2IndexName = null;
  20.         m_bIsInit = false;
  21.     }
复制代码


 总之,lucene版本变化很大,如果升级很多方法发送变化,您需要细致观察,多试试,才能升级。升级完成后,最好进行一次功能测试,有些功能可能发生变化甚至错误。升级Lucene不是一件好差事~~~~~~~~~



文章转载请注明出处:http://www.cnblogs.com/likehua/p/4387700.html


没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条