8.搜索请求的过滤和解析

主要内容:组合关键词搜索、关键词的解析、多索引搜索、多线程搜索

1.        构建多种搜索请求

前面介绍了使用 TermQuery 构建最基本的搜索,即普通的关键词搜索。

Lucene 中,使用 Query 对象封装搜索请求。 Query 类本身是一个抽象类,其不同的子类( TermQuery BooleanQuery )分别用来构建不同的搜索请求。

 

1.1 词条搜索 TermQuery

词条搜索就是 TermQuery 。首先构建 Term ,然后以 Term 为对象构建 TermQuery ,代码如下:

Term t = new Term( 被搜索的 Field, 搜索关键词 );

TermQuery q = new TermQuery(t);

示例: Test.Java 词条搜索

 

1.2 组合搜索 BooleanQuery

使用 BooleanQuery 对象封装组合搜索请求,与

用法:首先构建多个 TermQuery ,然后以多个 TermQuery 为参数构建 BooleanQuery ,在多个 Term 之间进行逻辑运算。例如:

        Term t1 = new Term("text", "love");

        TermQuery q1 = new TermQuery(t1);

       

        Term t2 = new Term("text", "mother");

        TermQuery q2 = new TermQuery(t2);

       

        BooleanQuery q = new BooleanQuery();

        q.add(q1,BooleanClause.Occur.MUST);

        q.add(q2,BooleanClause.Occur.MUST);

BooleanQuery 对象的 add 方法将 TermQuery 对象添加进来,第一个参数是 TermQuery 对象,第二个参数是该 TermQuery 对象的逻辑表达,有三个取值:

BooleanClause.Occur.MUST 搜索结果必须满足该 Term

BooleanClause.Occur.MUST_NOT 搜索结果必须排除该 Term

BooleanClause.Occur.SHOULD 搜索结果可以满足该 Term

利用这三个值可以在 TermQuery 之间构造多种逻辑关系

BooleanClause.Occur.MUST BooleanClause.Occur.MUST 组合在一起:逻辑与

BooleanClause.Occur.MUST_NOT :逻辑非

BooleanClause.Occur.SHOULE :逻辑或

 

BooleanQuery 对象所支持的子查询数量默认情况下最多 1024 个,可以通过 setMaxClauseCount(int num) 方法修改这个默认值。子查询数量少,查询速度会加快。

 

1.3 范围搜索 RangeQuery

搜索结果处于某个范围之内。使用 RangeQuery 对象来封装范围搜索的请求,构造方法:

RangeQuery(Term lowerTerm, Term upperTerm, Boolean inclusive);

第一个参数是起始 Term ,第二个参数是终止 Term ,第三个参数表示是否包含边界(是否包含起始 Term

Term tb = new Term("id", "0");

              Term te = new Term("id", "2");

             

              RangeQuery q = new RangeQuery(tb,te,true);

ID 号限定的范围

 

1.4 前缀搜索 PrefixQuery

如搜索“标题前三个字是‘大中华’”,就需要用到前缀搜索

Lucene 专门提供类 PrefixQuery 处理这种搜索。

Term t = new Term("text", "genius");         

              PrefixQuery q = new PrefixQuery(t);

 

1.5 短语搜索 PhraseQuery

PhraseQuery 类把一些短语组合起来形成新的短语。在这种搜索类型中可以设置匹配度。

可以用 PhraseQuery 把“鼠”和“标”组合成“鼠标”这个短语。也可以设置间隔量的方法,将其组合成“鼠 *** 标”,从而使得“老鼠爱上标”这样的结果也符合条件,实现模糊匹配。

使用方法:首先建立几个 Term ,然后按顺序添加到 PhraseQuery 中。

方法 setSlop(int s) 可以设定允许 Term 词语之间间隔的字符数量,不设为 0

Term t1 = new Term("text", " ");

        Term t2 = new Term("text", " ");

       

        PhraseQuery q = new PhraseQuery();

 

q.setSlop(1);  // 设置间隔

 

        q.add(t1);

        q.add(t2);

 

1.6 多短语搜索 MultiPhraseQuery

相当于首先指定一个前缀,然后把其它词语加在后面,形成新的词语。

例如,指定“飞”作为统一前缀,然后指定“鸟”、“机”为后缀, Lucene 会自动组成“飞鸟”、“飞机”两个词进行搜索。

Term t = new Term("text", " ");

       

        Term t1 = new Term("text", " ");

        Term t2 = new Term("text", " ");

 

        MultiPhraseQuery q = new MultiPhraseQuery();

        // 统一前缀

        q.add(t);

        // 后续            

        q.add(new Term[]{t1,t2});

 

1.7 模糊搜索 FuzzyQuery

用于西文搜索,如果两个词词形相似,那么可以设定匹配度,从而搜索出结果。

如,使用了 FuzzyQuery 就可以使搜索引擎把用户输入的“ good ”当作“ god ”处理

Term t = new Term(“text”, “god”);

FuzzyQuery q = new FuzzyQuery(t, 0.6f);

第二个参数是模糊度,一个 float 值,默认为 0.5 ,越小模糊性越强

 

1.8 通配符搜索 WildcardQuery

* ”表示任意多个字符,“?”表示任意一个字符

Term t = new Term(“text”, “ 飞? ”);

WildcardQuery q = new WildcardQuery(t);

对于经过分词的文本域,这种搜索的意义不大

 

1.9 正则表达式匹配搜索 RegexQuery

正则表达式匹配搜索集匹配搜索之大成,是最有用的模糊搜索。该类目前还不属于 Lucene 的标准类,如需使用要把 contrib/regex 下的 Lucene-regex-2.1.0.jar 添加到编译路径中。

Term t = new Term(“text”, “ 正则表达式 ”);

RegexQuery q = new RegexQuery(t);

 

例:正则表达式 “^ 表示以非开头的词语

 

1.10 综述

Lucene 的搜索类很多,并不止上面介绍的这些。

TermQuery BooleanQuery 是根本。功能最强的是 RegexQuery ,掌握这三个类即可,其它的搜索类可以很容易自己构造。

 

2.        解析搜索请求

按照设定好的某种逻辑分析用户搜索的真实意图。解析搜索请求属于前端分析,针对的是用户输入的关键词。 Lucene 提供 QueryParser 类用来解析搜索请求。

QueryParser 类可以进行与或非的处理,还可以进行通配符识别和范围搜索识别等。不过作者并不推荐使用 QueryParser 类进行搜索请求解析工作,而是把搜索请求处理放在搜索引擎程序前面一层的应用程序中。

 

2.1 QueryParser 类的基本使用

其代码位置与 TermQuery 相同

import org.apache.lucene.queryParser.QueryParser;

QueryParser parser = QueryParser(“ 字段名称 ”, “ 分析器实例 ”);

Query q = parser.parse(“ 关键词 ”);

示例:

//IndexSearcher

              IndexSearcher searcher = new IndexSearcher(rd);

             

              //Term & Query

              String searchField = "text";

              String searchPhrase = "love ";

             

              QueryParser parser = new QueryParser(searchField,new StandardAnalyzer());

              Query q = parser.parse(searchPhrase);

              System.out.println(q);

             

              //Hits

              Hits hs = searcher.search(q);

结果:

将搜索请求解析为: text:love

 

2.2 解析多个关键词

如果搜索关键词是 String searchPhrase = "love mother"; 那么输出结果将是

text:love text:mother

也即 Lucene 把输入的关键词按照逻辑或的关系进行了处理。

我们可以修改这种逻辑,让其以逻辑与的关系处理

String searchField = "text";

        String searchPhrase = "love mother";

       

        QueryParser parser = new QueryParser(searchField,new StandardAnalyzer());

       

        parser.setDefaultOperator(QueryParser.Operator.AND); // 默认是 OR

       

        Query q = parser.parse(searchPhrase);

        System.out.println(q);

解析结果: +text:love  +text:mother

在“ text ”字段搜索 love ,在 text 字段搜索 mother ,两部分结果取公共部分

setDefaultOperator 的默认参数是 QueryParser.Operator.OR

 

3.        高级搜索

主要内容:多字段搜索、多索引搜索、多线程搜索

3.1 多字段搜索

一个文档含有“标题”、“正文”等字段,搜索一个关键词,不管在“标题”还是“正文”中出现都满足条件,就是多字段搜索。

1 )利用 BooleanQuery 实现多字段搜索

前面已经介绍,首先设置两个 TermQuery ,再进行逻辑或运算即可。

Term t1 = new Term("text", "love");

              TermQuery q1 = new TermQuery(t1);

             

              Term t2 = new Term("id", "love");

              TermQuery q2 = new TermQuery(t2);

             

              BooleanQuery q = new BooleanQuery();

              q.add(q1,BooleanClause.Occur.SHOULD);

              q.add(q2,BooleanClause.Occur.SHOULD);

2 )利用 MultiFieldQuery 实现多字段搜索

Lucene 专门提供了 MultiFieldQueryParser 类,用来实现多字段搜索。其实,它只是对 BooleanQuery 封装。

构造方法:

MultiFieldQueryParser(String[] fields, Analyzer analyzer)

第一个参数是多个字段名称组成的数组,第二个参数是分析器实例

使用方法:

String[] fields = {“text”, “id”};

MultiFieldQueryParser mp = new MultiFieldQueryParser(fields, new StandardAnalyzer());

Query q = mp.parse(“love”);

3 )封装的方法

自定义函数实现,这也是 MultiFieldQueryParser 类的实现方法

String[] fields = {"text","id"};

        String phrase = "love";

        Query q = my(fields,phrase);

函数

public static BooleanQuery my(String fields[],String phrase)

{

        int len = fields.length;

        BooleanQuery q = new BooleanQuery();

        for(int i=0;i<len;i++)

        {

               String fie = fields[i];

               Term t = new Term(fie,phrase);

               TermQuery tq = new TermQuery(t);

               q.add(tq,BooleanClause.Occur.SHOULD);

        }

        return q;

}

 

3.2 多索引搜索

为了减少单个索引目录的大小,时常将索引放在许多目录中,这些目录的结构是一致的。

要实现多索引搜索,只需对每个索引目录都用 IndexSearcher 搜索一遍,最后将结果合并。

Lucene 专门提供了 MultiSearcher 类实现多索引搜索。方法如下:

IndexSearcher searcher1 = new IndexSearcher("index1");

        IndexSearcher searcher2 = new IndexSearcher("index2");

        IndexSearcher[] searchers = {searcher1,searcher2};

        MultiSearcher searcher = new MultiSearcher(searchers);

建立 MultiSearcher 对象后,使用方法就和 IndexSearcher 一样了

最后关闭搜索器的时候,只需关闭 MultiSearcher 的实例,在关闭它的时候,相应的几个 IndexSearcher 也被关闭了。

 

3.3 多线程搜索

MultiSearcher 的实现机制是对 IndexSearcher 数组中的每个 IndexSearcher 对象执行搜索,得到搜索结果后进行合并,它们是串行进行的。

Lucene 提供了 ParallelMultiSearcher 类实现多线程搜索,它是 MultiSearcher 的子类,使用方法与 MultiSearcher 一致。

IndexSearcher searcher1 = new IndexSearcher("index1");

IndexSearcher searcher2 = new IndexSearcher("index2");

IndexSearcher[] searchers = {searcher1,searcher2};

ParallelMultiSearcher searcher = new ParallelMultiSearcher(searchers);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值