lucene4.7 正则查询(RegexpQuery)(八)

今天要分享的是关于lucene中另一种丰富的查询方式----正则查询,lucene内置了许多的查询API,以及更强大的自定义查询方式的QueryParse,大部分状况下咱们使用内置的查询API,基本上就能够知足咱们的需求了,可是若是你想更灵活的定制本身的查询或者改写本身的查询API那么你彻底能够继承QueryParse类来完成这项工做。 

从某种方式上来讲,正则查询(RegexpQuery)跟通配符查询(WildcardQuery)的功能很类似,由于他们均可以完成同样的工做,可是不一样的是正则查询支持更灵活定制细化查询,这一点与通配符的泛化是不同的,并且正则查询天生支持使用强大的正则表达式的来准确匹配一个或几个term,须要注意的是,使用正则查询的字段最好是不分词的,由于分词的字段可能会致使边界问题,从而使查询失败,得不到任何结果,这一点和WildcardQuery效果是同样的。 

下面先来看一下,散仙的测试数据,为了看出分词与不分词给查询形成的影响,散仙的用一样的内容作测试,分词工具使用的是IK的分词器,截图以下: 
java

在上图中,散仙使用2个字段存储同样的内容,一个是分过词的,一个没分过词的,下面给出使用正则查询的核心代码:正则表达式

 RegexpQuery query=new RegexpQuery(new Term(field, ".*"+searchStr+".*"));
                  // System.out.println(query.toString());
                  TopDocs s=search.search(query,null, 100);
                //  TopDocs s=search.search(bool,null, 100);
                   System.out.println(s.totalHits);
                  for(ScoreDoc ss:s.scoreDocs){
                         
                         Document docs=search.doc(ss.doc);
                         System.out.println("id=>"+docs.get("id")+"   name==>"+docs.get("bookName")+"   author==>"+docs.get("author"));
                    // System.out.println(docs.get(field));
                     }

下面咱们先来测,对不分词的字段的作模糊查询,测试的代码以下:并发

 dao.testRegQuery("bookName","并发");

结果以下:
工具

命中数据 :2
id=>2   name==>并发数据挑战面临巨大的挑战   author==>并发数据挑战面临巨大的挑战
id=>4   name==>咱们的并发数量并秦东亮在不不是很大   author==>咱们的并发数量并秦东亮在不不是很大

咱们发现它很出色完成了模糊的查询,而且耗时比通配符查询一样的查询条件的耗时要少,下面咱们对分词的字段,进行检索,测试代码以下:
性能

 dao.testRegQuery("author","并发");

结果以下:测试

命中数据 :3
id=>2   name==>并发数据挑战面临巨大的挑战   author==>并发数据挑战面临巨大的挑战
id=>3   name==>the food is perfect!   author==>咱们的并发数量并非很大
id=>4   name==>咱们的并发数量并秦东亮在不不是很大   author==>咱们的并发数量并秦东亮在不不是很大

咱们发现对分词字段的模糊匹配,也一样没问题,下面咱们来测下对分词字段的边界查询。代码以下:
大数据

 dao.testRegQuery("bookName","e q");
         dao.testRegQuery("bookName","量并");
         System.out.println("===========对比界限=============");
         dao.testRegQuery("author","e q");
         dao.testRegQuery("author","量并");

结果以下:ui

命中数据 :1
id=>1   name==>the quick brown fox jumps over the lazy dog   author==>the quick brown fox jumps over the lazy dog
命中数据 :1
id=>4   name==>咱们的并发数量并秦东亮在不不是很大   author==>咱们的并发数量并秦东亮在不不是很大
===========对比界限=============
命中数据 :0
命中数据 :0

由以上结果,咱们能够发现分词后的字段,若是在某个字之间被切分红两个term,那么不管你用什么样的方式模糊这两个term边界之间的数据,都查询不到任何结果,而不分词的字段,却能查出来,这是由于,不分词的字段都是做为一个单独的term来处理的,来lucene的内部匹配方式,偏偏又是以term做为最小检索单位的,故能检索到结果,这一点须要咱们格外注意,在实现咱们的业务时,要根据本身的场景来设计出最优的分词策略。spa

下面散仙要测的是正则查询的老本行了,使用正则表达式进行查询,代码以下:
设计

     dao.testRegQuery("bookName","[fb]ox");//利用正则式检索

结果以下:

命中数据 :2
id=>1   name==>the quick brown fox jumps over the lazy dog   author==>the quick brown fox jumps over the lazy dog
id=>5   name==>log is small box   author==>log is small box

咱们发现含有fox,box的两条数据都被正确的检索出来了,其实检索的条件,在匹配时会被分解成4个条件,分别是,fox,fo,box,bo只要含有这几个term的数据,都会被检索出来,而这一点偏偏省去了,咱们在使用其余的查询时使用OR或者AND进行拼接的繁琐,也能够简化成所谓的SQL里面的IN查询,固然使用正则表达式查询方式能够有不少种,在这里只是简单的举了个例子,有兴趣的朋友们,能够本身测测。 

最后在总结一下,1,若是是在不分词的字段里作模糊检索,优先使用正则查询的方式会比其余的模糊方式性能要快。2,在查询的时候,应该注意分词字段的边界问题。3,在使用OR或AND拼接条件查询时或一些特别复杂的匹配时,也应优先使用正则查询。4,大数据检索时,性能尤其重要,注意应避免使用前置模糊的方式,不管是正则查询仍是通配符查询。

相关文章
相关标签/搜索