我很高兴自己履行了承诺,今天来总结QueryParser。因为世事变化无常,能implement自己许下的诺言,实属不易。

       上一章我们说,Google的底层可能是用了QueryParser来转换用户关键字的。正因为搜索引擎的Query对象有很多,所以我才不敢妄言。然而作为lucene的Query工具,QueryParser却是最重要的一个。

       简单的说,QueryParser能够根据用户的输入来进行解析,自动构建合适的Query对象。简单总结一下它的实现:

  1. 用户输入(词条的定义)

当用户输入他们想要的关键字串后,QueryParser首先会对其进行解析,而这种解析是以词条为基础的。而词条和词条之间呢,则是用空格分开的。

  1. QueryParser的初始化,“AND,OR,NOT”
 1 String field = “bookname”;//设置一个默认的field
 2 
 3 String queryStr = “Persist Google”;//用户输入的关键字
 4 
 5  
 6 
 7 //new了一个QueryParser,并且传进去两个参数。
 8 
 9 //第一个参数是默认要检索的field;
10 
11 //(因为在用户没有指定field时,lucene会在默认的field中检索)
12 
13 //第二个参数是用到的分析器;
14 
15 //(注意:这里用到的分析器一定是在建立索引时一样的分析器,
16 
17 //否则所分词条与索引中的内容不一致)
18 
19 QueryParser parser = new QueryParser(field,new StandardAnalyzer());
20 
21  
22 
23 Query q = parser.parser(queryStr);//执行QueryParser的parser方法

 

在这里,我们(用户)所输入的“Persist Google”被QueryParser分析成了“OR”的关系,即检索有“Persist”或者“Google”的文档。这并非我们的意愿,我们要查的是含有“Persist”和“Google”文档。那么我们尝试改变一下QueryParser默认的布尔逻辑。 

1 //上面的代码中只需要加上一句话
2 
3 parser.setDefaultOperator(QueryParser.AND_OPERATOR);

或者,将用户输入的关键字串“Persist Google”改为“Persist AND Google”

 到此为止,便是我们上一章总结的Google的搜索方式“AND,OR”。“NOT”同理。

  1. 短语和QueryParser

我们输入几个词,QueryParser就会把它解成几个词条。那么当我们输入一句话的时候,(如:Rome is not built in one day)此时这句话有七个词,我们并不想把它分成几个词来查询,怎么办呢?当然,lucene的开发者早已经想到了这点,也很人性化的解决了这一个问题,他们说:“给这句话加个引号吧!”。

1 //我们则只需要将代码
2 
3 String queryStr = “Rome is not built in one day”;
4 
5 //改为
6 
7 String queryStr = “/”Rome is not built in one day/””;


 

       短暂的休息之后,让我们重新向前! 

  1. QueryParser的模糊匹配查询

我们之前提到过FuzzyQuery,即模糊匹配查询。虽然没有细讲,它的用法与其他Query对象却是大同小异的。不同的是,FuzzyQuery有一个相似度的概念。我们不需要深刻理解,只需要知道它会去匹配和输入词条相似的其他词条即可。

 

1  //如:FuzzyQuery默认的相似度为0.5
2 
3               Term t = new Term(“bookname”, “work”);
4 
5               FuzzyQuery query = new FuzzyQuery(t);

 

 

用QueryParser的概念对输入关键字进行分析,我们只需要给输入的关键字加一个符号。如:work~0.2,即把work相似度0.5改为了0.2

 

  1. 通配符与QueryParser
1 //在之前的Google中提到的通配符原理亦是如此。
2 
3               Term t = new Term(“bookname”, “wor?”);
4 
5               WildcardQuery q = new WildcardQuery(t);
6 
7               //wor?可以被QueryParser识别,表示前三个字母为wor的词条。
8 
9 //即有可能是word,work...

 

 

  1. QueryParser指定Field查询
1 //此时回去检索发布时间为2010-12-5的所有文档,并且bookname为work
2 
3 String queryStr = “work publishdate:2010-12-5”;
4 
5 QueryParser parser = new QueryParser(“bookname”,new StandardAnalyzer());
6 
7 Parser.setDefaultOperator(QueryParser.AND_OPERATOR);
8 
9 Query query = parser.parser(queryStr);

 

 

  1. QueryParser的范围查找(RangeQuery):TO

            

1 //找出发布日期从2010-12-01到2010-12-05的所有文档
2 
3 String queryStr = “[2010-12-1 TO 2010-12-5]”;
4 
5 QueryParser parser = new QueryParser(“bookname”,new StandardAnalyzer());
6 
7 Parser.setDefaultOperator(QueryParser.AND_OPERATOR);
8 
9 Query query = parser.parser(queryStr);

 

 

       在Lucene中,还有很多搜索方式,如:多域搜索MutliFieldQueryParser,多索引搜索MultiSearcher,多线程搜索ParalellMultiSearcher等。用法都很简单,原理也大同小异,是比较好理解的。值得关注的是多线程搜索ParalellMultiSearcher,因为若只有单个线程的话,多访问时,总要等上个线程结束,反馈时间是很慢的,这里就需要多线程搜索来提高效率。以上所提到的所有方法都可以互相结合或者嵌套使用,对各种口味的用户都能给予满足,这也正是Lucene的灵活性。

 

posted on 2013-01-01 10:44  王国龙  阅读(385)  评论(0)    收藏  举报