经过了前面几篇文章的学习,我们基本上可以适用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. Hibernate | Spring JPA | MySQL 使用过程遇到的一些问题

    1. 使用过程 2. 背景 3. 遇到问题 3.1 不指定Hibernate数据库方言,默认SQL生成方式 3.2 抛出异常Hibernate加入了@Transactional事务不会回滚 3.3 H ...

  2. 【以2-SAT为主题的婚礼UVA11294】

    ·新娘头饰复杂,这个婚礼怪异非凡. ·英文题,述大意:        婚宴上,有一个很长的桌子.桌子两边坐人(即人们坐成两排).新娘坐在其中一排,只能看见桌子对面所有的人.输入的m表示有m对人打过架. ...

  3. hdu 5573Binary Tree

    Binary Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tota ...

  4. [bzoj4908][BeiJing2017]开车

    来自FallDream的博客,未经允许,请勿转载,谢谢. 你有n辆车,分别a1, a2, ..., an位置和n个加油站,分别在b1, b2, ... ,bn .每个加油站只能支持一辆车的加油,所以你 ...

  5. bzoj1597[Usaco2008 Mar]土地购买 斜率优化dp

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5524  Solved: 2074[Submit] ...

  6. RAC基本原理

    RAC基本原理 什么是RAC? 多个实例跑在多个服务器上 一个数据库存放在共享的存储上,所有实例都可以访问 实例之间通过内联网络交换数据和信息 共享存储内容:数据文件.REDO.UNDO.控制文件 参 ...

  7. Windows 下 Ionic 开发环境搭建

    Ionic 介绍 首先,Ionic 是什么. Ionic 是一款基于 Cordova 及 Angular 开发 Hybrid/Web APP 的前端框架,类似的其他框架有:Intel XDK等. 简单 ...

  8. Eclipse插件安装4种方法

    第一种:直接复制法 假设Eclipse的安装目录在C:\eclipse,解压下载的eclipse 插件或者安装eclipse 插件到指定目录AA(如:c:\AA)文件夹,打开AA 文件夹,在AA文件夹 ...

  9. Python:操作数据库

    (一)      前言 本文说明如何连接Oracle.MySQL.sqlserver,以及执行sql.获取查询结果等. (二)      DB-API      DB-API阐明一系列所需对象和数据库 ...

  10. EF Core 2.0使用MsSql/Mysql实现DB First和Code First

    参考地址 EF官网 ASP.NET Core MVC 和 EF Core - 教程系列 环境 Visual Studio 2017 最新版本的.NET Core 2.0 SDK 最新版本的 Windo ...