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。

时间: 2024-10-12 02:23:52

Lucene自定义扩展QueryParser的相关文章

Jquery自定义扩展方法(二)--HTML日历控件

一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看看效果图吧 效果图很简单,代码封装在JQuery中,网页端只需要要调用即可: 二.Jquery自定义实体对象 Jquery可以自定义函数function,有没有可以定义实体对象,里面封装方法那?查询了一下资料发现,是可以的,不仅能够封装属性,还可以写自己的方法,调用模板代码如下: $.Calende

WinForm TextBox自定义扩展方法数据验证

本文转载:http://www.cnblogs.com/gis-crazy/archive/2013/03/17/2964132.html 查看公司项目代码时,存在这样一个问题:winform界面上有很多信息填写,提交后台服务器更新,但数据的合法验证及值的转换却不太敢恭维,一堆的if判断和转换,便想着是否能扩展个方法出来,琢磨出个思路,记录下来与大家共同探讨,有不对的地方还请大家指正. 设计思路: 1. 由于大部分从TextBox控件中获取数据值,可以扩展个泛型方法出来,直接根据转换后的数据类型

jQuery 自定义扩展,与$冲突处理

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="jquery-2.2.4.min.js"></script> <script src="jQuery扩展.js"></script> <script> /

SharePoint 2013 自定义扩展菜单(二)

原文:SharePoint 2013 自定义扩展菜单(二) 接博文<SharePoint 2013 自定义扩展菜单>,多加了几个例子,方便大家理解. 例七 列表设置菜单扩展(listedit.aspx) 扩展效果 XML描述 <CustomAction Id="CustomAction1" Description="博客园-霖雨" Title="博客园-霖雨" GroupId="GeneralSettings"

SharePoint 2013 自定义扩展菜单

原文:SharePoint 2013 自定义扩展菜单 在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbon.列表里的下拉等等,都是一样原理的,都是XML+JS脚本实现的,如果想实现这些功能,只需要一个XML发布成Feature,并在网站功能启用,即可. 其实,关于这个并没有什么过多可以说的东西,大家在实践中,渐渐理解了.下面,我就举几个简单的例子,

Lucene 自定义分析器

自定义一个NGramAnalyzer: 1 package org.apache.lucene.analysis.ngram; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.io.Reader; 8 import java.util.ArrayList; 9 import java.

NHibernate3剖析:Query篇之NHibernate.Linq自定义扩展

系列引入 NHibernate3.0剖析系列分别从Configuration篇.Mapping篇.Query篇.Session策略篇.应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本.如果你还不熟悉NHibernate,可以快速阅读NHibernate之旅系列文章导航系列入门,如果你已经在用NHibernate了,那么请跟上NHibernate3.0剖析系列吧. NHibernate专题:http://kb.cnblogs.com

基于 HtmlHelper 自定义扩展Container

基于 HtmlHelper 自定义扩展Container Intro 基于 asp.net mvc 的权限控制系统的一部分,适用于对UI层数据呈现的控制,基于 HtmlHelper 的扩展组件 Code 基于 asp.net mvc 的权限控制系统示例代码:https://github.com/WeihanLi/AccessControlDemo 权限控制核心代码:https://github.com/WeihanLi/AccessControlDemo/tree/master/AccessCo

Easyui的validatebox验证方法自定义扩展

由于easyui的validatebox本身提供的验证方法较少,故对其进行了自定义扩展. 1.新建一个js文件 —— extendValidateboxRules.js   ,内容如下: /** * auther by Highness * date : xxxx-xx-xx */ // 时间格式规范var regex_dateTime = /\d{4}\-\d{2}\-\d{2} \d{2}\:\d{2}:\d{2}/;//@author ren $.extend($.fn.validateb