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

  1、查询lucene多目录索引。

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

  3、构建Lucene自定义分词。

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

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

1. 搜索多索引目录

   3.0 构建多索引目录: 

     // 初始化全国索引
private boolean InitGlobal(String strRootPath) {
try { IndexSearcher[] searchers = new IndexSearcher[2]; MultiSearcher globalSearcher = null;
if (Configution.IsMMap.equalsIgnoreCase("true")) { searchers[0] = new IndexSearcher(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + GLABOL_INDEX))));
searchers[1] = new IndexSearcher(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + BUS_INDEX))));
// searchers[2] = new IndexSearcher(new RAMDirectory(FSDirectory
// .open(new File(strRootPath + "/" + LU_INDEX))));
globalSearcher = new MultiSearcher(searchers);
} else {
searchers[0] = new IndexSearcher(FSDirectory.open(new File(
strRootPath + "/" + GLABOL_INDEX)));
searchers[1] = new IndexSearcher(FSDirectory.open(new File(
strRootPath + "/" + BUS_INDEX)));
// searchers[2] = new IndexSearcher(FSDirectory.open(new File(
// strRootPath + "/" + LU_INDEX))); globalSearcher = new MultiSearcher(searchers);
}
System.out.println("finish Global"); m_mapIndexName2Searcher.put("0", globalSearcher);
m_mapAdmin2IndexName.put("0", "0"); return true; } catch (Exception e) {
e.printStackTrace();
SearchLog.SearchLog.error("全国索引初始化异常");
return false;
}
}

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

4.x 构建多索引目录: 

	// 初始化全国索引
private boolean InitGlobal(String strRootPath) {
try { IndexSearcher globalSearcher = null;
if (Configution.IsMMap.equalsIgnoreCase("true")) { IndexReader irGlobal = DirectoryReader.open(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + GLABOL_INDEX)),new IOContext())); IndexReader irBus = DirectoryReader.open(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + BUS_INDEX)),new IOContext())); MultiReader mr = new MultiReader(irGlobal,irBus); globalSearcher = new IndexSearcher(mr);//new MultiSearcher(searchers);
} else { IndexReader irGlobal = DirectoryReader.open(FSDirectory
.open(new File(strRootPath + "/" + GLABOL_INDEX))); IndexReader irBus = DirectoryReader.open(FSDirectory
.open(new File(strRootPath + "/" + BUS_INDEX))); MultiReader mr = new MultiReader(irGlobal,irBus);
globalSearcher = new IndexSearcher(mr);//new MultiSearcher(searchers);
}
System.out.println("finish Global"); m_mapIndexName2Searcher.put("0", globalSearcher);
m_mapAdmin2IndexName.put("0", "0"); return true; } catch (Exception e) {
e.printStackTrace();
SearchLog.SearchLog.error("全国索引初始化异常");
return false;
}
}

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

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

    3.0 构建内存索引目录:

                searchers[0] = new IndexSearcher(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + GLABOL_INDEX))));
searchers[1] = new IndexSearcher(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + BUS_INDEX))));

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

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

                IndexReader irGlobal = DirectoryReader.open(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + GLABOL_INDEX)),new IOContext())); IndexReader irBus = DirectoryReader.open(new RAMDirectory(FSDirectory
.open(new File(strRootPath + "/" + BUS_INDEX)),new IOContext())); MultiReader mr = new MultiReader(irGlobal,irBus);

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

 3、自定义分词:

    3.0 自定义分词:

public class SingleAnalyzer extends Analyzer {

    /**
* @param args
*/ public TokenStream tokenStream(String fieldName, Reader reader){
TokenStream result = null;
if(fieldName.equals("name"))
{
result = new SingleTokenizer(reader);
}
if(fieldName.equals("totalcity"))
{
result = new IKTokenizer(reader, false);
} // result = new StandardFilter(result);
// result = new LowerCaseFilter(result);
// result = new StopFilter(result, stopSet);
return result;
} public static void main(String[] args) {
// TODO Auto-generated method stub } }

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

    4.x自定义分词:

public class SingleAnalyzer extends Analyzer {

    /**
* @param args
*/ // public TokenStream tokenStream(String fieldName, Reader reader){
// TokenStream result = null;
// if(fieldName.equals("name"))
// {
// result = new SingleTokenizer(reader);
// }
// if(fieldName.equals("totalcity"))
// {
// result = new IKTokenizer(reader, false);
// }
//
//// result = new StandardFilter(result);
//// result = new LowerCaseFilter(result);
// // result = new StopFilter(result, stopSet);
// return result;
// } @Override
protected TokenStreamComponents createComponents(String fieldName,
Reader reader) {
// TODO Auto-generated method stub
// final Tokenizer source = new ChineseTokenizer(reader);
// return new TokenStreamComponents(source, new ChineseFilter(source));
Tokenizer source = null;
if(fieldName.equals("name")){
source = new SingleTokenizer(reader);
}else if(fieldName.equals("totalcity")){
source = new IKTokenizer(reader, false);
}
return new TokenStreamComponents(source, source);
} }

  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: 

         String left = Long
.toString((long) (rcBound.m_dLeft * COORDINATE_SCALE_FACTOR));
String right = Long
.toString((long) (rcBound.m_dRight * COORDINATE_SCALE_FACTOR));
String top = Long
.toString((long) (rcBound.m_dTop * COORDINATE_SCALE_FACTOR));
String bottom = Long
.toString((long) (rcBound.m_dBottom * COORDINATE_SCALE_FACTOR)); TermRangeQuery query1 = new TermRangeQuery("lon", left, right,
true, true);
TermRangeQuery query2 = new TermRangeQuery("lat", bottom, top,
true, true);
searchQuery.add(query1, BooleanClause.Occur.MUST);
searchQuery.add(query2, BooleanClause.Occur.MUST);

    4.x TermRangerQuery:  

String left = Long
.toString((long) (rcBound.m_dLeft * COORDINATE_SCALE_FACTOR));
String right = Long
.toString((long) (rcBound.m_dRight * COORDINATE_SCALE_FACTOR));
String top = Long
.toString((long) (rcBound.m_dTop * COORDINATE_SCALE_FACTOR));
String bottom = Long
.toString((long) (rcBound.m_dBottom * COORDINATE_SCALE_FACTOR)); BytesRef brLeft = new BytesRef(left);
BytesRef brRight = new BytesRef(right);
BytesRef brBottom = new BytesRef(bottom);
BytesRef brTop = new BytesRef(top); TermRangeQuery query1 = new TermRangeQuery("lon",
brLeft, brRight, true, true);
TermRangeQuery query2 = new TermRangeQuery("lat",
brBottom, brTop, true, true);
searchQuery.add(query1, BooleanClause.Occur.MUST);
searchQuery.add(query2, BooleanClause.Occur.MUST);

  6、关闭IndexSearcher

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

 public void UnInit() {
if (!m_bIsInit)
return; Iterator iter = m_mapIndexName2Searcher.keySet().iterator(); while (iter.hasNext()) { String key = (String) iter.next(); MultiSearcher val = (MultiSearcher) m_mapIndexName2Searcher
.get(key); try { val.close();//关闭IndexSearcher
} catch (IOException e) {
e.printStackTrace();
SearchLog.SearchLog.error("分级索引关闭异常");
}
} m_mapIndexName2Searcher.clear();
m_mapAdmin2IndexName.clear();
m_mapIndexName2Searcher = null;
m_mapAdmin2IndexName = null;
m_bIsInit = false;
}

  4.x 关闭IndexSearcher 没有直接close的方法,需要getIndexReader 然后调用IndexReader的close方法:

 public void UnInit() {
if (!m_bIsInit)
return; Iterator iter = m_mapIndexName2Searcher.keySet().iterator(); while (iter.hasNext()) { String key = (String) iter.next(); IndexSearcher val = (IndexSearcher) m_mapIndexName2Searcher
.get(key); try {
val.getIndexReader().close();//关闭IndexSearcher
} catch (IOException e) {
e.printStackTrace();
SearchLog.SearchLog.error("分级索引关闭异常");
}
} m_mapIndexName2Searcher.clear();
m_mapAdmin2IndexName.clear();
m_mapIndexName2Searcher = null;
m_mapAdmin2IndexName = null;
m_bIsInit = false;
}

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

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

    

  

关于Lucene 3.0升级到Lucene 4.x 备忘的更多相关文章

  1. Lucene学习总结之四:Lucene索引过程分析 2014-06-25 14:18 884人阅读 评论(0) 收藏

    对于Lucene的索引过程,除了将词(Term)写入倒排表并最终写入Lucene的索引文件外,还包括分词(Analyzer)和合并段(merge segments)的过程,本次不包括这两部分,将在以后 ...

  2. Lucene 6.0下使用IK分词器

    Lucene 6.0使用IK分词器需要修改修改IKAnalyzer和IKTokenizer. 使用时先新建一个MyIKTokenizer类,一个MyIkAnalyzer类: MyIKTokenizer ...

  3. Lucene 4.0 正式版发布,亮点特性中文解读[转]

    http://blog.csdn.net/accesine960/article/details/8066877 2012年10月12日,Lucene 4.0正式发布了(点击这里下载最新版),这个版本 ...

  4. Lucene学习总结之六:Lucene打分公式的数学推导 2014-06-25 14:20 384人阅读 评论(0) 收藏

    在进行Lucene的搜索过程解析之前,有必要单独的一张把Lucene score公式的推导,各部分的意义阐述一下.因为Lucene的搜索过程,很重要的一个步骤就是逐步的计算各部分的分数. Lucene ...

  5. Lucene学习总结之三:Lucene的索引文件格式(1) 2014-06-25 14:15 1124人阅读 评论(0) 收藏

    Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙. 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程, ...

  6. Lucene.Net3.0.3+盘古分词器学习使用

    一.Lucene.Net介绍 Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索 ...

  7. Lucene学习总结之四:Lucene索引过程分析

    对于Lucene的索引过程,除了将词(Term)写入倒排表并最终写入Lucene的索引文件外,还包括分词(Analyzer)和合并段(merge segments)的过程,本次不包括这两部分,将在以后 ...

  8. Lucene学习总结之七:Lucene搜索过程解析

    一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...

  9. Lucene学习总结之六:Lucene打分公式的数学推导

    在进行Lucene的搜索过程解析之前,有必要单独的一张把Lucene score公式的推导,各部分的意义阐述一下.因为Lucene的搜索过程,很重要的一个步骤就是逐步的计算各部分的分数. Lucene ...

随机推荐

  1. 使用Bower作为Web包管理器

    Bower是一个简单易用的Web包管理器,通过它我们可以非常简便的安装各种Web框架和库,同时它也负责管理不同包之间的关系依赖. 安装Bower Bower需要 npm 和 Git 的支持,在安装Bo ...

  2. SweetAlert – 替代 Alert 的漂亮的提示效果

    Sweet Alert 是一个替代传统的 JavaScript Alert 的漂亮提示效果.SweetAlert 自动居中对齐在页面中央,不管您使用的是台式电脑,手机或平板电脑看起来效果都很棒.另外提 ...

  3. 2013年最新流行的响应式 WordPress 主题【上篇】

    WordPress 是最流行的内容管理系统,经历了多年的发展和演变.它的成功体现在庞大的社区,数百万的用户,设计师和开发者推动着 WordPress 往更高的层次发展. 海量的免费主题是 WordPr ...

  4. 前端js文件合并三种方式

    最近在思考前端js文件该如何合并,当然不包括不能合并文件,而是我们能合并的文件,想了想应该也只有三种方式. 三个方式如下: 1. 一个大文件,所有js合并成一个大文件,所有页面都引用它. 2. 各个页 ...

  5. 浅析css布局模型1

    css是网页的外衣,好不好看全凭css样式,而布局是css中比较重要的部分,下面来分析一下常见的几种布局. 流动模型 流动模型是网页布局的默认模式,也是最常见的布局模式,他有两个特点: 1.块状元素都 ...

  6. 经典的Java基础面试题集锦

    经典的Java基础面试题集锦,欢迎收藏和分享. 问题:如果main方法被声明为private会怎样? 答案:能正常编译,但运行的时候会提示”main方法不是public的”. 问题:Java里的传引用 ...

  7. android加固系列—5.加固前先学会破解,hook(钩子)jni层系统api

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5138585.html] crackme项目jni的关键代码(项目地址见文章底部),获取当前程序 ...

  8. 简单粗暴的对android so文件加壳,防止静态分析

    转载自http://bbs.pediy.com/showthread.php?t=191649 以前一直对.so文件加载时解密不懂,不了解其工作原理和实现思路.最近翻看各种资料,有了一些思路.看到论坛 ...

  9. Swift中的部分更新与旧版的区别

    1. 函数中的外部变量名取消 “#”方式,仅能用直接命名方式 错误 func swift(#str :NSString){} 正确 func swift(str str :NSString){} 2. ...

  10. apache 虚拟ip

    参考 http://blog.sina.com.cn/s/blog_5d8ca1e90100hnpv.html <VirtualHost 127.0.0.1:80>      Docume ...