关于QueryParser类前后修改
2013-11-26 21:31
239 查看
转载请注明出处:/article/2606839.html
这几天在公司做一个项目,就是去将以前的老项目的lucene版本切换成4.3版本,并将以前的索引架构修改为实时索引(公司以前的那个项目是好几年前的了),为了和以前的版本兼容,第一步就是只是把lucene版本修改下,同时支持实时索引,至于所有的接口,都要和以前一样。在这中间就遇到了一个很大的问题,就是在出搜索结果的时候,修改后的版本要比以前的版本多很多搜索结果(上面要求要和原来的接口出的数据完全一样),函数也是用的以前的,为什么就出现不同的结果呢?
最后通过读源代码,发现是QueryParser类在作怪,下面先看一下QueryParser在前后3.1前后两个版本中的效果:
上面这个测试用例的结果为:
斗破苍穹30版本结果:key:"斗 破 苍 穹"
斗破苍穹43版本结果:key:斗 key:破 key:苍 key:穹
得出两个完全不同的Query对象,这也就是为什么会多出这么多的搜索结果的原因,下面就从源代码中探究其原因,下面的源代码均是通过反编译软件实现的。
先看下QueryParse的构造方法:
在进一步追一下,看起父类QueryParserBase是如何实现的init(Version matchVersion, String f, Analyzer a)方法
key:"斗 破 苍 穹" 这种结果是能够准确的定位到用户搜索到的结果,而且也十分准确,但是如果用户某一个词输入错误,或者是错别字,那得到的就不是用户想要的结果,甚至就搜索不出来任何的东西。
key:斗 key:破 key:苍 key:穹 这种结果虽然出现的结果会有很多,但是根据lucene的打分机制,“斗破苍穹”这条记录也出出现在第一条,即使用户输出了其中的某一个字,一还是可以搜索到用户想要的结果的。
至于这两种,那个效果比较好,自己还需大量的数据去测试,不能就根据自己的意愿去认为
这几天在公司做一个项目,就是去将以前的老项目的lucene版本切换成4.3版本,并将以前的索引架构修改为实时索引(公司以前的那个项目是好几年前的了),为了和以前的版本兼容,第一步就是只是把lucene版本修改下,同时支持实时索引,至于所有的接口,都要和以前一样。在这中间就遇到了一个很大的问题,就是在出搜索结果的时候,修改后的版本要比以前的版本多很多搜索结果(上面要求要和原来的接口出的数据完全一样),函数也是用的以前的,为什么就出现不同的结果呢?
最后通过读源代码,发现是QueryParser类在作怪,下面先看一下QueryParser在前后3.1前后两个版本中的效果:
/** *@Description: */ package cn.lulei.test; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.Query; import org.apache.lucene.util.Version; public class TestQueryParser { public static Query getOneFieldQuery43(String key, String field) throws ParseException{ QueryParser parse = new QueryParser(Version.LUCENE_43, field, new StandardAnalyzer(Version.LUCENE_43)); Query query = null; query = parse.parse(key); return query; } @SuppressWarnings("deprecation") public static Query getOneFieldQuery30(String key, String field) throws ParseException{ QueryParser parse = new QueryParser(Version.LUCENE_30, field, new StandardAnalyzer(Version.LUCENE_43)); Query query = null; query = parse.parse(key); return query; } public static void main(String[] args) throws ParseException { String key = "斗破苍穹"; System.out.println(key + "30版本结果:" + TestQueryParser.getOneFieldQuery30(key, "key").toString()); System.out.println(key + "43版本结果:" + TestQueryParser.getOneFieldQuery43(key, "key").toString()); } }
上面这个测试用例的结果为:
斗破苍穹30版本结果:key:"斗 破 苍 穹"
斗破苍穹43版本结果:key:斗 key:破 key:苍 key:穹
得出两个完全不同的Query对象,这也就是为什么会多出这么多的搜索结果的原因,下面就从源代码中探究其原因,下面的源代码均是通过反编译软件实现的。
先看下QueryParse的构造方法:
public QueryParser(Version matchVersion, String f, Analyzer a) { this(new FastCharStream(new StringReader(""))); init(matchVersion, f, a); }在以前的版本中是没有Version这个参数的,具体从那个版本开始加的,我也不是很清楚,自己也是最近才刚开始接触lucene的。
在进一步追一下,看起父类QueryParserBase是如何实现的init(Version matchVersion, String f, Analyzer a)方法
public void init(Version matchVersion, String f, Analyzer a) { this.analyzer = a; this.field = f; if (matchVersion.onOrAfter(Version.LUCENE_31)) setAutoGeneratePhraseQueries(false); else setAutoGeneratePhraseQueries(true); }其中setAutoGeneratePhraseQueries(boolean)方法修改的是类属性allowLeadingWildcard的值,这样allowLeadingWildcard的值对parse(String)的实现就有决定性的作用。
public Query parse(String query) throws ParseException { ReInit(new FastCharStream(new StringReader(query))); ParseException e; try { Query res = TopLevelQuery(this.field); return res != null ? res : newBooleanQuery(false); } catch (ParseException tme) { ParseException e = new ParseException(new StringBuilder().append("Cannot parse '").append(query).append("': ").append(tme.getMessage()).toString()); e.initCause(tme); throw e; } catch (TokenMgrError tme) { ParseException e = new ParseException(new StringBuilder().append("Cannot parse '").append(query).append("': ").append(tme.getMessage()).toString()); e.initCause(tme); throw e; } catch (BooleanQuery.TooManyClauses tmc) { e = new ParseException(new StringBuilder().append("Cannot parse '").append(query).append("': too many boolean clauses").toString()); e.initCause(tmc); }throw e; }也正事因为属性allowLeadingWildcard的值,决定了了第一个测试实例的结果,从源代码中也可以看出来,3.1(包括)之前的版本和之后的版本出来两种完全不同的结果,为什么会做这样的修改,我猜测可能是因为下面的原因:
key:"斗 破 苍 穹" 这种结果是能够准确的定位到用户搜索到的结果,而且也十分准确,但是如果用户某一个词输入错误,或者是错别字,那得到的就不是用户想要的结果,甚至就搜索不出来任何的东西。
key:斗 key:破 key:苍 key:穹 这种结果虽然出现的结果会有很多,但是根据lucene的打分机制,“斗破苍穹”这条记录也出出现在第一条,即使用户输出了其中的某一个字,一还是可以搜索到用户想要的结果的。
至于这两种,那个效果比较好,自己还需大量的数据去测试,不能就根据自己的意愿去认为
相关文章推荐
- 关于Android 4.2 以上系统(power键)电源键挂断电话修改方式
- 技术总结:关于JS执行前台和后台顺序的.另外一个是前后和后台变量的交互的.
- 关于Myeclipse + tomcat下 项目名修改的问题
- 关于ms sql server的所有者及修改数据库对象的所有者
- 关于修改单例信息
- 关于论文的修改--对小修的response
- 关于恢复注册表修改的一些代码
- 关于MySQL修改成utf8mb4编码后启动服务报错1067的解决方法
- 关于修改DB2主机名,IBM800给出的建议
- 关于ActionBar 的V7包样式修改兼容性问题
- 关于UDP的一个修改实例
- jsp页面中修改html元素内容关于单双引号的错误笔记
- 关于内存访问与修改
- 关于CentOS 7修改root用户密码
- 打通前后端全栈开发node+vue进阶【课程学习系统项目实战详细讲解】(3):用户添加/修改/删除 vue表格组件 vue分页组件
- RHEL修改最大文件打开数,关于epoll socket Too many open files问题的解决
- 【原创_解析】关于static型变量被外部文件修改的问题..
- 关于修改WordPress主题你需要知道的十件事
- 安卓应用开发(关于应用程序图标与名称的修改)
- 关于拼音的datrie树的修改