经过了前面几篇文章的学习,我们基本上可以适用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. 顺序或者说优先级的重要性---解决dom生成问题有感

    我们的大脑有逻辑,程序也有逻辑,只要一切都刚刚好,那么我们大脑的逻辑和程序的逻辑是没有冲突的:但是,有时候,我们想当然,只顾自己头脑中的逻辑,而随意臆想程序的逻辑,这个时候,就会有很多我们觉得不可思议 ...

  2. [WC 2013]糖果公园

    Description 题库链接 给你一棵 \(n\) 个节点,有 \(m\) 种颜色的树.每个节点上有一个颜色.定义一条树上路径的价值为 \[\sum_c V_c(\sum_{i=1}^{tim_c ...

  3. BZOJ 4260 Codechef REBXOR

    Description Input 输入数据的第一行包含一个整数N,表示数组中的元素个数. 第二行包含N个整数A1,A2,…,AN. Output 输出一行包含给定表达式可能的最大值. Sample ...

  4. ●POJ 2187 Beauty Contest

    题链: http://poj.org/problem?id=2187 题解: 计算几何,凸包,旋转卡壳 一个求凸包直径的裸题,旋转卡壳入门用的. 代码: #include<cmath> # ...

  5. 【Peaks加强版 BZOJ 3551】你被坑了吗?

    这道在没加读入优化时间在20s左右的题终于在大米饼两天的死缠烂打.鬼混.乱整乱撞后艰难地AC了.但惋惜的是,大米饼一号代码其实更加简洁,但至今找不出BUG,我将它放在下面,也许有一天从远方来的另一个大 ...

  6. [bzoj4405][wc2016]挑战NPC

    来自FallDream的博客,未经允许,请勿转载,谢谢. 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. ...

  7. THUPC2017 抱大腿记

    Day 0: 移步http://www.cnblogs.com/juruolty/p/6854848.html Day 1: 来到了清华大学. 见到了zrt巨巨. 又发了件衣服,我们开始看别的队的名字 ...

  8. of_alias_get_id 函数与设备树中aliases节点的关系【转】

    转自:https://blog.csdn.net/qq_30145093/article/details/78053823?locationNum=10&fps=1 转自http://www. ...

  9. Fashion-MNIST:A MNIST-like fashion product database. Benchmark

    Zalando的文章图像的一个数据集包括一个训练集6万个例子和一个10,000个例子的测试集. 每个示例是一个28x28灰度图像,与10个类别的标签相关联. 时尚MNIST旨在作为用于基准机器学习算法 ...

  10. Linux 下 HTTP连接超时

    将项目部署到现场环境,HTTP请求莫名奇妙的连接超时,通过抓包定位了问题,是请求的IP被禁止掉.其中用到了抓包,将记录记录于此. tcpdump host 120.197.89.51 -i any - ...