Lucene学习使用小结(二)

Lucene学习使用小结(二)

       Lucene作为底层全文检索开发工具,虽然它没有强大的solr那样可怕,但是底层还是封装了一些特殊查询和一些高级应用,此处将简单的介绍一些特殊查询和一些高级应用,至于solr的使用和solr的可怕将在下一篇笔记中介绍.

特殊查询

Instantiable subclasses are:

 

Lucene官方API中介绍了这么多的特殊查询,我主要实现了TermQuery,BooleanQuery,WildcardQuery,FuzzyQuery,NumericRangeQuery.对于这些特殊查询的方式大同小异,只是传入的不同的Query从而产生不同的结果,此处对博客<使用小结(一)>中的测试方法进行了抽取,将Query作为参数传入.

public void search(Query query) throws Exception{

              //索引库位置

              Directory directory = FSDirectory.open(new File("luceneTest"));

              //索引读取

              IndexReader indexReader = DirectoryReader.open(directory);

              //索引查询

              IndexSearcher indexSearcher = new IndexSearcher(indexReader);

              //查询

              TopDocs topDocs = indexSearcher.search(query, 10);

              System.out.println("查询到"+topDocs.totalHits+"个文档");

              ScoreDoc[] scoreDocs = topDocs.scoreDocs;

              for (ScoreDoc doc : scoreDocs) {

                     //文档编号

                     int did = doc.doc;

                     //拿到文档

                     Document document = indexReader.document(did);

                     System.out.println("id:"+document.get("id"));

                     System.out.println("text:"+document.get("text"));

              }

       }

如果查出所有的数据?可以采用通配符查询WildcardQuery

WildcardQuery

@Test

       public void testWildcardQuery() throws Exception{

              WildcardQuery wildcardQuery = new WildcardQuery(new Term("text","*"));

              search(wildcardQuery);

       }

 

查询结果:

查询到4个文档

id:1

text:Tom喜欢使用华为手机

id:2

text:Jack一直在用iPhone

id:3

text:xiaomi在印度受广大欢迎

id:4

text:锤子手机真的很锤

星号表示的是另个或多个字符,所有查询出所有内容.

       @Test

       public void testWildcardQuery2() throws Exception{

              WildcardQuery wildcardQuery = new WildcardQuery(new Term("text","*手机*"));

              search(wildcardQuery);

       }

此处查询的是text中内容包含手机字段的内容

查询到2个文档

id:1

text:Tom喜欢使用华为手机

id:4

text:锤子手机真的很锤

TermQuery

@Test

       public void testTermQuery() throws Exception{

              TermQuery termQuery = new TermQuery(new Term("text","iphone"));

              search(termQuery);

       }

结果如下:

查询到1个文档

id:2

text:Jack一直在用iPhone

Term查询是根据词条完整匹配,查询text包含iPhone的文档,并且分词器将iPhone分为词条的文档.

FuzzyQuery

@Test

       public void testFuzzyQuery() throws Exception{

              FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("text","iphonn"));

              search(fuzzyQuery);

       }

模糊匹配查询指的是允许在匹配词条的时候出现错误单词,例如本例中输入的是iPhonn,依然可以查出iPhone的结果.但是值得注意的是在lucene的底层只允许错误两个,也就是如果输入iphyyy就无法查询到结果

查询到1个文档

id:2

text:Jack一直在用iPhone

 

其他具体的使用情况可以参见API

 

Lucene的高级使用

高亮显示

高亮显示的原理

       在百度或者其他搜索引擎上搜索内容可见,匹配上搜索词条的内容作为高亮显示,这种实现查询网站源码可知有很多方式,一般而言是在匹配上的内容上加上前端定义好样式的标签,从而实现样式的更改.百度很多添加<em></em>标签

这种实现方式在lucene底层也是有实现的.

       @Test

       public void testHighlight() throws Exception{

              //索引库位置

              Directory directory = FSDirectory.open(new File("luceneTest"));

              //索引读取

              IndexReader indexReader = DirectoryReader.open(directory);

              //索引查询

              IndexSearcher indexSearcher = new IndexSearcher(indexReader);

              //查询

              TermQuery query = new TermQuery(new Term("text","手机"));

              //样式编辑器

              Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");

              Scorer scorer =  new QueryScorer(query);

             

              Highlighter highlighter = new Highlighter(formatter,scorer);

              TopDocs topDocs = indexSearcher.search(query, 10);

              System.out.println("查询到"+topDocs.totalHits+"个文档");

              ScoreDoc[] scoreDocs = topDocs.scoreDocs;

              for (ScoreDoc doc : scoreDocs) {

                     //文档编号

                     int did = doc.doc;

                     //拿到文档

                     Document document = indexReader.document(did);

                     System.out.println("id:"+document.get("id"));

                     //拿到原来的text

                     String textString = document.get("text");

                     //高亮文本

                     String hTextString = highlighter.getBestFragment(new IKAnalyzer(), "text", textString);

                     System.out.println("text:"+hTextString);

              }

       }

运行结果如下:

查询到2个文档

id:1

加载扩展词典:ext.dic

加载扩展停止词典:stopword.dic

text:Tom喜欢使用华为<em>手机</em>

id:4

text:锤子<em>手机</em>真的很锤

 

排序

@Test

       public void testLuceneSort() throws Exception{

              //索引库位置

                            Directory directory = FSDirectory.open(new File("luceneTest"));

                            //索引读取

                            IndexReader indexReader = DirectoryReader.open(directory);

                            //索引查询

                            IndexSearcher indexSearcher = new IndexSearcher(indexReader);

                            //查询

                            WildcardQuery query = new WildcardQuery(new Term("text","*"));

                            //true表示十分降序排列

                            Sort sort = new Sort(new SortField("id",Type.LONG,true));

                            //查询的时候传入sort

                            TopDocs topDocs = indexSearcher.search(query, 10,sort );

                            System.out.println("查询到"+topDocs.totalHits+"个文档");

                            ScoreDoc[] scoreDocs = topDocs.scoreDocs;

                            for (ScoreDoc doc : scoreDocs) {

                                   //文档编号

                                   int did = doc.doc;

                                   //拿到文档

                                   Document document = indexReader.document(did);

                                   System.out.println("id:"+document.get("id"));

                                   System.out.println("text:"+document.get("text"));

                            }

       }

查询结果如下

查询到4个文档

id:4

text:锤子手机真的很锤

id:3

text:xiaomi在印度受广大欢迎

id:2

text:Jack一直在用iPhone

id:1

text:Tom喜欢使用华为手机

 

 

分页

此处需要强调的是Lucene并不支持物理分页,而只支持逻辑分页.

@Test

       public void testLucenePage() throws Exception{

              //从页面传来的值page当前页和pageSize每页展示的数量

              int page = 1;

              int pageSize=2;

              //起始和结束位置

              int start = (page-1)*pageSize;

              int end = start+pageSize;

             

              //索引库位置

              Directory directory = FSDirectory.open(new File("luceneTest"));

              //索引读取

              IndexReader indexReader = DirectoryReader.open(directory);

              //索引查询

              IndexSearcher indexSearcher = new IndexSearcher(indexReader);

              //查询

              WildcardQuery query = new WildcardQuery(new Term("text","*"));

              //true表示十分降序排列

              Sort sort = new Sort(new SortField("id",Type.LONG,true));

              //查询的时候传入sort

              //此处end之后的数据无需查询了

              TopDocs topDocs = indexSearcher.search(query, end,sort);

              System.out.println("查询到"+topDocs.totalHits+"个文档");

              ScoreDoc[] scoreDocs = topDocs.scoreDocs;

              for(int i=start;i<end;i++){

                     int docID = scoreDocs[i].doc;

                     Document document = indexReader.document(docID);

                     System.out.println(document.get("id"));

                     System.out.println(document.get("text"));

              }

       }

 

测试结果如下

查询到4个文档

4

锤子手机真的很锤

3

xiaomi在印度受广大欢迎

 

 

可以看到,虽然是分页查询,但是还是查询到了4条数据,只是我们返回2条数据而已,个人觉得lucene的分页一直都有些尴尬,希望深一步的学习可以搞懂为什么不支持物理分页吧.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值