Lucene自定义扩展QueryParser
Lucene版本:4.10.2
在使用lucene的时候,不可避免的需要扩展lucene的相关功能来实现业务的需要,比如搜索时,需要在满足一个特定范围内的document进行搜索,如年龄在20和30岁之间的document中搜索并排序。其实lucene自带的NumericRangeQuery类已经能实现这个功能了,如下:
public void testInclusive() throws Exception {
Directory dir = FSDirectory(---);
IndexSearcher searcher = new IndexSearcher(dir);
NumericRangeQuery query = NumericRangeQuery.newIntRange("age",20,30,true,true);
TopDocs matches = searcher.search(query,10);
}
这个是通过lucene内置的query类型来进行搜索,但是这样使用起来的缺点就是无法再搜索期间生成对应的NumericRangeQuery实例,如比如直接在搜索的时候传入搜索text: age:[20 TO 30],这样就可以动态的使用范围搜索,更为灵活,那么要是实现这个功能,我们就需要自定义QueryParser了。
QueryParser,故名思议,就是讲前台传入的查询条件,解析为Query实例,从而进行查询,所以简单的说,我们需要自定义一个NumericRangeQueryParser,用来实现,从 age:[20 TO 30] 转化为
NumericRangeQuery query = NumericRangeQuery.newIntRange("age",20,30,true,true);
的一个Query实例。
在lucene中扩展QueryParser是比较简单的,我们可以直接继承QueryParser类,然后实现特定的方法就可以了(查询age在20至30岁的记录):
//自定义queryParser
class NumericRangeQueryParser extends QueryParser { /**
* @param arg0
*/
protected NumericRangeQueryParser(String field,Analyzer analyzer) {
//调用父类的构造方法
super(field,analyzer);
// TODO Auto-generated constructor stub
} //获取query实例的方法
public Query getRangeQuery(String field,String part1,String part2,boolean startInclusive,boolean endInclusive) throws ParseException {
//调用父类的getRangeQuery方法获取query实例
TermRangeQuery query = (TermRangeQuery) super.getRangeQuery方法获取query实例(field, part1, part2, startInclusive,endInclusive);
//如果是搜索age Field
if("age".equals(field)) {
System.out.println(query.getLowerTerm().utf8ToString());
System.out.println(query.getUpperTerm().utf8ToString()); //按照业务需求处理query生成新的query实例并返回
return NumericRangeQuery.newDoubleRange("price", Double.parseDouble(query.getLowerTerm().utf8ToString()),
Double.parseDouble(query.getUpperTerm().utf8ToString()), query.includesLower(), query.includesUpper());
} else {
return query;
}
} }
其实代码很简单,因为我只是将范围查询的上下限从Int类型格式化成Double类型。其中最重要的一条代码是:
NumericRangeQuery.newDoubleRange("price", Double.parseDouble(query.getLowerTerm().utf8ToString()),
Double.parseDouble(query.getUpperTerm().utf8ToString()), query.includesLower(), query.includesUpper());
NumericRangeQuery.newDoubleRange是调用了lucene自带的方法来生成相应的query实例,在这里是浮点数范围查询Query实例。其中参数的解释:
query.getLowerTerm().utf8ToString():getLowerTerm是指获取范围查询中的下限,在这里是20。getLowerTerm()返回一个BytesRef对象,lucene自定义的一种对象,我们需要转换成String类型再转成Double类型的对象,传给NumericRangeQuery.newDoubleRange方法,在这里我一开始想到的是toString方法,结果老是报错,最后查看源码才知道应该使用utf8ToString()方法,它会将BytesRef转成utf8编码的String对象。
public String utf8ToString() Interprets stored bytes as UTF8 bytes, returning the resulting string
query.getUpperTerm().utf8ToString():与query.getLowerTerm().utf8ToString()同理,获取范围查询中的上限,在这里是30
query.includesLower()和query.includesUpper():是否包含临界值,在这里值是否包含年龄为20和30岁的记录,即[20,30]或[20,30)…
下面我没来测试NumericRangeQueryParser:
public static void main(String[] args) throws IOException, ParseException {
String expression = "age:[10 TO 20]";
Analyzer analyzer = new StandardAnalyzer();
QueryParser parser = new QueryParser("age",analyzer);
Query query = parser.parse(expression);
QueryParser testParser = kscSearch.new NumericRangeQueryParser("age",analyzer);
Query testQuery = testParser.parse(expression);
System.out.println(expression + " parser to " + query);
System.out.println(expression + " parser to " + testQuery);
}
测试结果如下:
age:[10 TO 20] parser to age:[10 TO 20] age:[10 TO 20] parser to price:[10.0 TO 20.0]
可以看到使用NumericRangeQueryParser后,10和20都变成了浮点数。
相应的我们可以自定义日期QueryParser或者是更为复杂的QueryParser。不过从这个简单的NumericRangeQueryParser中我们可以看到QueryParser的原理,就是讲给定的查询字符串解析生成Lucene能识别的Query实例,从而进行查询,我们这里是使用了Lucene内置的NumericRangeQuery扩展QueryParser,如果有需要,甚至可以自定义NumericRangeQuery。
Lucene自定义扩展QueryParser的更多相关文章
- SharePoint 2013 自定义扩展菜单
在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbo ...
- SharePoint 2013 自定义扩展菜单(二)
接博文<SharePoint 2013 自定义扩展菜单>,多加了几个例子,方便大家理解. 例七 列表设置菜单扩展(listedit.aspx) 扩展效果 XML描述 <CustomA ...
- WCF自定义扩展,以实现aop!
引用地址:https://msdn.microsoft.com/zh-cn/magazine/cc163302.aspx 使用自定义行为扩展 WCF Aaron Skonnard 代码下载位置: S ...
- Jquery自定义扩展方法(二)--HTML日历控件
一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看 ...
- Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议(转载)
Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...
- jQuery 自定义扩展,与$冲突处理
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件
需求 SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件 扩展 class SparkContext(pyspark.SparkContext): def ...
- 基于 HtmlHelper 的自定义扩展Container
基于 HtmlHelper 的自定义扩展Container Intro 基于 asp.net mvc 的权限控制系统的一部分,适用于对UI层数据呈现的控制,基于 HtmlHelper 的扩展组件 Co ...
- 第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)
一. 自定义扩展名 1. 前言 凡是实现了IHttpHandler接口的类均为Handler类,HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...
随机推荐
- Android-SVN
服务器启动svn服务 svnserve -d -r /home/wbp/svn/actia/ 1 .svn 重新定位location , 改变新仓库的uuid , 今天操作SVN Client 发现 ...
- JNI type
ref: JNI type The mapping between the Java type and C type is: Type Signature Java Type Z boolean B ...
- 报错:ORA-02287: 此处不允许序号
CREATE TABLE MY_TAB (N1 NUMBER(5),N2 DATE); SELECT * FROM MY_TAB; CREATE SEQUENCE ...
- 开始Swift之旅 - HelloWorld
//: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...
- javascript 原生 cookie 处理
来自网络! function getCookie(name) { var start = document.cookie.indexOf(name + "="); var len ...
- 数据类型和Json格式[转]
1. 前几天,我才知道有一种简化的数据交换格式,叫做yaml. 我翻了一遍它的文档,看懂的地方不多,但是有一句话令我茅塞顿开. 它说,从结构上看,所有的数据(data)最终都可以分解成三种类型: 第一 ...
- Memcached源码分析——process_command函数解析
以下为个人笔记 /** * process_command 在memcached中是用来处理用户发送的命令的, * 包括get set,add,delete,replace,stats,flush_a ...
- Maven插件开发
Maven为我们提供了丰富的插件资源,使得开发调试过程中非常方便,可以满足大多数场景下的需求.当然有时候,我们也需要根据需求定制自己的插件.下面是在开发Maven插件时的一点备忘录,具体的开发流程请G ...
- UITextFiled自动补全输入,选中补全内容。NSRange和UITextRange的相互转换。-b
有个需求就是 需要用户输入几位以后账号,可以根据本地存储的登录成功的账号,进行自动补全,并且补全内容为选中状态,不影响用户的新输入. 研究了一下,下面是完整的实现的方法. 补充个下载地址http:// ...
- linux c redirect 重定向
用execvp实现时,运行adb,如果adb 服务没有启动,会启动adb服务,启动adb服务时,pipe返回的管道在读的时候堵塞了. 查看了popen的源码,发现popen是用sh -c来执行的,避免 ...