经过了前面几篇文章的学习,我们基本上可以适用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. 使用Nwjs开发桌面应用体验

    之前一直用.net开发桌面应用,最近由于公司需要转为nodejs,但也是一直用nodejs开发后台应用,网站,接口等.近期,需要开发一个客户端,想着既然nodejs号称全栈,就试一下开发桌面应用到底行 ...

  2. 谈一谈泛型(Generic)

    谈一谈泛型 首先,泛型是C#2出现的.这也是C#2一个重要的新特性.泛型的好处之一就是在编译时执行更多的检查. 泛型类型和类型参数 ​ 泛型的两种形式:泛型类型( 包括类.接口.委托和结构 没有泛型枚 ...

  3. [HNOI 2011]XOR和路径

    Description 给定一个无向连通图,其节点编号为 1 到 N,其边的权值为非负整数.试求出一条从 1 号节点到 N 号节点的路径,使得该路径上经过的边的权值的“XOR 和”最大.该路径可以重复 ...

  4. [BJOI2006]狼抓兔子

    题目描述 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...

  5. bzoj 2560: 串珠子

    Description 铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不 ...

  6. ●洛谷P3687 [ZJOI2017]仙人掌

    题链: https://www.luogu.org/problemnew/show/P3687题解: 计数DP,树形DP. (首先对于这个图来说,如果初始就不是仙人掌,那么就直接输出0) 然后由于本来 ...

  7. 51nod1295 XOR key(可持久化trie)

    1295 XOR key题目来源: HackerRank基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个长度为N的正整数数组A,再给出Q个查询,每个查 ...

  8. 【USACO】 奶牛会展

    题目背景 奶牛想证明它们是聪明而风趣的.为此,贝西筹备了一个奶牛博览会,她已经对N 头奶牛进行 了面试,确定了每头奶牛的智商和情商. 题目描述 贝西有权选择让哪些奶牛参加展览.由于负的智商或情商会造成 ...

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

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

  10. BZOJ3052(树上带修莫队)

    树上莫队的基本思路是把树按dfs序分块,然后先按x所在块从小到大排序,再按y所在块从小到大排序,处理询问即可. 这道题带修改,再加一个时间维即可. 设块大小为T,那么时间复杂度为$O(nT+\frac ...