经过了前面几篇文章的学习,我们基本上可以适用Lucene来开发我们的站内搜索应用了。但是观察一下目前的主流的搜索引擎,我们会发现查询结果会有高亮的显示效果。所以,今天我们就来学习一下,给Lucene添加以下高亮的显示效果。


必备基础

我们这次的分享,代码还是基于前面的内容。所以还请仔细阅读前面的文章。

高亮原理

一般来说,高亮会显示在网页上,所以我们只需要把查询到的结果,词语的外边包裹一层HTML的font标签,来达到高亮的效果。

实际案例

/**
     * 带有高亮显示的分页查询
     *
     * @param queryString
     *            待查询的字符串
     * @param firstResult
     *            开始位置
     * @param maxResult
     *            页面记录最大数量
     * @return
     */
    public Page searchWithHighLighter(String queryString, int firstResult, int maxResult) {
        try {
            // 1.queryString -->>Query
            String[] queryFields = new String[] { "title", "content" };
            Analyzer analyzer = new StandardAnalyzer();
            analyzer.setVersion(Version.LUCENE_6_0_0.LUCENE_6_1_0);
            QueryParser queryParser = new MultiFieldQueryParser(queryFields, analyzer);
            Query query = queryParser.parse(queryString);
            // 2. 查询,得到topDocs
            IndexSearcher indexSearcher = LuceneUtils.getIndexSearcher();
            TopDocs topDocs = indexSearcher.search(query, 100);
            // 3.处理结果并返回
            int totalHits = topDocs.totalHits;
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            List<Article> articles = new ArrayList<Article>();
            int upperBound = (firstResult + maxResult) < scoreDocs.length ? (firstResult + maxResult)
                    : scoreDocs.length;
            firstResult = (firstResult >= 0 ? firstResult : 0);

            // -------------------------------高亮操作
            Formatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
            Scorer scorer = new QueryScorer(query);
            Highlighter highLighter = new Highlighter(formatter, scorer);
            // 第二个参数默认为100,即指定显示的摘要的文字的大小
            Fragmenter fragmenter = new SimpleFragmenter(100);
            // ---------------------------------高亮配置结束
            highLighter.setTextFragmenter(fragmenter);
            for (int i = firstResult; i < upperBound; i++) {
                ScoreDoc scoreDoc = scoreDocs[i];
                Document doc = indexSearcher.doc(scoreDoc.doc);
                // 监测有没有目标词
                String text = highLighter.getBestFragment(new StandardAnalyzer(), "content", doc.get("content"));
                // 这里的操作和3.0版本的不一致
                String content = "";
                if (text != null) {
                    TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(doc.get("content")));
                    content = highLighter.getBestFragment(tokenStream, doc.get("content"));
                }
                Article a = ArticleDocumentUtils.document2Article(doc, content);
                articles.add(a);
            }
            LuceneUtils.closeIndexSearcher(indexSearcher);

            // 处理查询结果,返回一个封装好的页面对象
            Page<Article> page = new Page();
            page.setLists(articles);
            page.setTotalResults(totalHits);

            return page != null ? page : null;
        } catch (Exception e) {
            throw new RuntimeException("ArticleIndexDao-->> search方法出错!\n" + e);
        }
    }

简化操作的一个工具方法

ArticleDocumentUtils.document2Article(doc, content);

具体代码如下:

/**
     * 高亮处理过的文本,转换为Article对象
     *
     * @param document
     * @param replaceText
     * @return
     */
    public static Article document2Article(Document document, String replaceText) {
        Article a = new Article();
        a.setId(Integer.parseInt(document.get("id")));
        a.setTitle(document.get("title"));
        a.setContent(replaceText);

        return a != null ? a : null;
    }

输出结果

-------------------查询到的总记录数----------------------17
Article [id=4, title=我的Save测试案例4, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!16]
Article [id=5, title=我的Save测试案例5, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!25]
Article [id=6, title=我的Save测试案例6, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!36]
Article [id=7, title=我的Save测试案例7, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!49]
Article [id=8, title=我的Save测试案例8, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!64]
Article [id=9, title=我的Save测试案例9, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!81]
Article [id=0, title=我的Save测试案例0, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!0]
Article [id=1, title=我的Save测试案例1, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!1]
Article [id=2, title=我的Save测试案例2, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!4]
Article [id=3, title=我的Save测试案例3, content=<font color='red'>Junit</font>是一个很好的测试工具,我们可以在这工具的帮助下下写出健壮性很强的代码!9]

案例解析

高亮器设置

// -------------------------------高亮操作
            Formatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
            Scorer scorer = new QueryScorer(query);
            Highlighter highLighter = new Highlighter(formatter, scorer);
            // 第二个参数默认为100,即指定显示的摘要的文字的大小
            Fragmenter fragmenter = new SimpleFragmenter(100);
            highLighter.setTextFragmenter(fragmenter);
            // ---------------------------------高亮配置结束

这基本上不会变动,所以我们拷贝一下就可以放到别的地方进行使用。很方便。

索引值包装并处理到实体结果集中

for (int i = firstResult; i < upperBound; i++) {
                ScoreDoc scoreDoc = scoreDocs[i];
                Document doc = indexSearcher.doc(scoreDoc.doc);
                // 监测有没有目标词
                String text = highLighter.getBestFragment(new StandardAnalyzer(), "content", doc.get("content"));
                // 这里的操作和3.0版本的不一致
                String content = "";
                // 如果有索引值信息,就把包裹完高亮的结果返回
                if (text != null) {
                    TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(doc.get("content")));
                    content = highLighter.getBestFragment(tokenStream, doc.get("content"));
                }
                // 将高亮结果封装到结果集中,然而这并不影响索引库中的实际信息的值。属于视图层面的变化。
                Article a = ArticleDocumentUtils.document2Article(doc, content);
                articles.add(a);
            }
            LuceneUtils.closeIndexSearcher(indexSearcher);

总结

高亮显示对于一个站内搜索系统而言,可以起到画龙点睛的作用。虽然很简单,但是我们仍然要好好的设计,来打造一个优雅的搜索系统。

全文检索 Lucene(4)的更多相关文章

  1. 全文检索 Lucene(3)

    看完前两篇博客之后,想必大家对于Lucene的使用都有了一个比较清晰的认识了.如果对Lucene的知识点还是有点模糊的话,个人建议还是先看看这两篇文章. 全文检索 Lucene(1) 全文检索 Luc ...

  2. 全文检索Lucene (2)

    接着全文检索Lucene (1) . 下面我们来深入的研究一下,如何使用Lucene! 从全文检索Lucene (1)中我们可以看出,Lucene就好比一个双向的工作流,一方面是对索引库的维护,另一方 ...

  3. Lucene 全文检索 Lucene的使用

    Lucene  全文检索  Lucene的使用 一.简介: 参考百度百科: http://baike.baidu.com/link?url=eBcEVuUL3TbUivRvtgRnMr1s44nTE7 ...

  4. 全文检索--Lucene & ElasticSearch

    全文检索--Lucene 2.1 全文检索和以前高级查询的比较 1.高级查询 缺点:1.like让数据库索引失效 2.每次查询都是查询数据库 ,如果访问的人比较多,压力也是比较大 2.全文检索框架:A ...

  5. [全文检索]Lucene基础入门.

    本打算直接来学习Solr, 现在先把Lucene的只是捋一遍. 本文内容: 1. 搜索引擎的发展史 2. Lucene入门 3. Lucene的API详解 4. 索引调优 5. Lucene搜索结果排 ...

  6. 全文检索Lucene (1)

    Lucene是apache开源的一个全文检索框架,很是出名.今天先来分享一个类似于HelloWorld级别的使用. 工作流程 依赖 我们要想使用Lucene,那就得先引用人家的jar包了.下面列举一下 ...

  7. 全文检索-Lucene.net

    Lucene.net是Lucene的.net移植版本,在较早之前是比较受欢迎的一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎. ...

  8. 全文检索Lucene框架---查询索引

    一. Lucene索引库查询 对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name ...

  9. ]NET Core Lucene.net和PanGu分词实现全文检索

    Lucene.net和PanGu分词实现全文检索 Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考   前言:目前自己在做使用Lucene. ...

随机推荐

  1. ●洛谷P1291 [SHOI2002]百事世界杯之旅

    题链: https://www.luogu.org/recordnew/show/5861351题解: dp,期望 定义dp[i]表示还剩下i个盖子没收集时,期望还需要多少次才能手机完. 初始值:dp ...

  2. C++traits——STL源码剖析

    有时候我们希望知道迭代器所指的元素类型. 以迭代器所指声明对象: template<typename Iterator, typename T> void func_impl(Iterat ...

  3. ●BZOJ 4556 [Tjoi2016&Heoi2016]字符串

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4556 题解: 巨恶心...但是题很好呀,可以练习好几个比较麻烦的算法~ 1).预处理 首先用 ...

  4. hihocoder #1142 : 三分·三分求极值

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的 ...

  5. [APIO2014]

    T1.回文树裸题. #include<cstdio> #include<iostream> #define ll long long using namespace std; ...

  6. Ubuntu 16.04安装JDK/JRE并配置环境变量

    作为一个Linux新手,在写这篇文章之前,安装了几次jdk,好多次都是环境变量配置错误,导致无法登录系统.经过几天的研究,今天新装系统,从头来完整配置一遍 系统版本:Ubuntu 16.04 JDK版 ...

  7. solr6.6初探之solrj

    一. solrj简介: solrj可以使Java应用程序很方便的访问与操作solr.solrj有几个核心类,分别为:1.SolrClient 2.SolrRequests 3.SolrQuerys 4 ...

  8. 在Unix系统中,主存索引节点和辅存索引节点从内容上比较有什么不同,为什么要设置主存索引节点?

    主存索引节点和辅存索引节点的不同主要体现在:主存索引节点状态:设备号.索引节点号:引用计数. 主存索引节点状态——反映主存索引节点的使用情况.它指示出: 1.  索引节点是否被锁上了: 2.  是否有 ...

  9. Python中编码的详细讲解

    看这篇文章前,你应该已经知道了为什么有编码,以及编码的种类情况 ASCII 占1个字节,只支持英文 GB2312 占2个字节,支持6700+汉字 GBK GB2312的升级版,支持21000+汉字 S ...

  10. Java的数组排序

    对数组进行排序 使用到的排序算法有: 1 选择排序   2 冒泡排序   3 插入排序    4 JavaAPI提高排序算法 选择排序的原理: 1 将数组中每个元素与第一个元素比较,如果这个元素小于第 ...