lucene中另外一种丰富的查询方式----正则查询

关于lucene中另外一种丰富的查询方式----正则查询,lucene内置了许多的查询API,以及更强大的自定义查询方式的QueryParse,大部分情况下我们使用内置的查询API,基本上就可以满足我们的需求了,但是如果你想更灵活的定制自己的查询或者改写自己的查询API那么你完全可以继承QueryParse类来完成这项工作。


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

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



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


Java代码 复制代码 收藏代码
1.RegexpQuery query=new RegexpQuery(new Term(field, ".*"+searchStr+".*"));
2. // System.out.println(query.toString());
3. TopDocs s=search.search(query,null, 100);
4. // TopDocs s=search.search(bool,null, 100);
5. System.out.println(s.totalHits);
6. for(ScoreDoc ss:s.scoreDocs){
7.
8. Document docs=search.doc(ss.doc);
9. System.out.println("id=>"+docs.get("id")+" name==>"+docs.get("bookName")+" author==>"+docs.get("author"));
10. // System.out.println(docs.get(field));
11. }


下面我们先来测,对不分词的字段的做模糊查询,测试的代码如下:


Java代码 复制代码 收藏代码
1.dao.testRegQuery("bookName","并发");


结果如下:


Java代码 复制代码 收藏代码
1.命中数据 :2
2.id=>2 name==>并发数据挑战面临巨大的挑战 author==>并发数据挑战面临巨大的挑战
3.id=>4 name==>我们的并发数量并秦东亮在不不是很大 author==>我们的并发数量并秦东亮在不不是很大


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


Java代码 复制代码 收藏代码
1.dao.testRegQuery("author","并发");


结果如下:


Java代码 复制代码 收藏代码
1.命中数据 :3
2.id=>2 name==>并发数据挑战面临巨大的挑战 author==>并发数据挑战面临巨大的挑战
3.id=>3 name==>the food is perfect! author==>我们的并发数量并不是很大
4.id=>4 name==>我们的并发数量并秦东亮在不不是很大 author==>我们的并发数量并秦东亮在不不是很大


我们发现对分词字段的模糊匹配,也同样没问题,下面我们来测下对分词字段的边界查询。代码如下:


Java代码 复制代码 收藏代码
1.dao.testRegQuery("bookName","e q");
2. dao.testRegQuery("bookName","量并");
3. System.out.println("===========对比界限=============");
4. dao.testRegQuery("author","e q");
5. dao.testRegQuery("author","量并");


结果如下:


Java代码 复制代码 收藏代码
1.命中数据 :1
2.id=>1 name==>the quick brown fox jumps over the lazy dog author==>the quick brown fox jumps over the lazy dog
3.命中数据 :1
4.id=>4 name==>我们的并发数量并秦东亮在不不是很大 author==>我们的并发数量并秦东亮在不不是很大
5.===========对比界限=============
6.命中数据 :0
7.命中数据 :0


由以上结果,我们可以发现分词后的字段,如果在某个字之间被切分成两个term,那么无论你用什么样的方式模糊这两个term边界之间的数据,都查询不到任何结果,而不分词的字段,却能查出来,这是因为,不分词的字段都是作为一个单独的term来处理的,来lucene的内部匹配方式,恰恰又是以term作为最小检索单位的,故能检索到结果,这一点需要我们格外注意,在实现我们的业务时,要根据自己的场景来设计出最优的分词策略。

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


Java代码 复制代码 收藏代码
1.dao.testRegQuery("bookName","[fb]ox");//利用正则式检索


结果如下:


Java代码 复制代码 收藏代码
1.命中数据 :2
2.id=>1 name==>the quick brown fox jumps over the lazy dog author==>the quick brown fox jumps over the lazy dog
3.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,大数据检索时,性能尤为重要,注意应避免使用前置模糊的方式,无论是正则查询还是通配符查询。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lucene使用文分词器ik-analyzers可以自定义字典。下面是一个简单的例子: 1. 首先,下载ik-analyzers的jar包,将其添加到项目的classpath。 2. 创建一个自定义词典文件,例如mydict.txt,将需要添加的词语逐行写入该文件。 3. 在代码使用以下代码片段来加载自定义词典: ```java // 创建IK分词器 Analyzer analyzer = new IKAnalyzer(true); // 获取IK分词器的配置对象 IKAnalyzerConfig config = ((IKAnalyzer) analyzer).getConfig(); // 加载自定义词典 config.setUseSmart(true); config.setMainDictionary("mydict.dic"); config.setQuantifierDicionary("mydict.qdic"); ``` 其,IKAnalyzerConfig是IK分词器的配置对象,通过该对象可以设置分词器的一些参数。setMainDictionary和setQuantifierDicionary方法分别用于设置主词典和量词词典的文件名。 4. 使用分词器进行分词: ```java // 创建分词器 Analyzer analyzer = new IKAnalyzer(true); // 对字符串进行分词 String text = "我爱北京天安门"; TokenStream tokenStream = analyzer.tokenStream("", new StringReader(text)); // 遍历分词结果 CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); tokenStream.reset(); while (tokenStream.incrementToken()) { System.out.println(charTermAttribute.toString()); } tokenStream.end(); tokenStream.close(); ``` 在以上代码,我们创建了一个IK分词器并对一个字符串进行了分词,遍历分词结果并输出。 注意:在使用自定义词典时,需要保证自定义词典的文件名与代码设置的文件名一致,并且自定义词典文件必须放在分词器的类路径下。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值