要想使得一个搜索系统更加的完美,查询精确度和页面显示算是其中比较重要的两个方面。今天,我们就来谈谈怎么使得我们的搜索系统更加的完美。



关于分词

分词的好坏直接关系到我们的查询系统的精准度。所以一个更加适合的分词方式很重要。对于中文而言,更是如此。

Compass配置分词器简直是不能再简单了。我这里使用一个中科院研制的一个高效中文分词器。JE-Analysis,

下载地址

配置

我们使用xml的方式对分词器进行配置。

导入刚才下载的jar包之后,我们可以在项目的依赖中找到如图所示信息。

右键红色区域文件,点击copy qualified name。然后配置成如下面貌即可。

<?xml version="1.0" encoding="UTF-8" ?>
<compass-core-config xmlns="http://www.compass-project.org/schema/core-config"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.compass-project.org/schema/core-config
           http://www.compass-project.org/schema/compass-core-config-2.2.xsd">

    <compass name="default">
        <!-- 连接信息,好比数据库的连接信息 -->
        <connection>
            <file path="./indexDir/" />
        </connection>

        <!-- 映射信息,好比Hibernate的映射关系 -->
        <mappings>
            <class name="domain.Article" />
        </mappings>
        <!-- 分词器以及高亮器的配置 -->
        <settings>
            <!-- 分词器的配置,可选择中文的 -->
            <setting name="compass.engine.amalyzer.default.type" value="jeasy.analysis.MMAnalyzer" />

        </settings>
    </compass>
</compass-core-config>   

好了,大功告成了。

关于高亮

对于高亮而言,我们其实并未真正的改变原始数据,而是将取出来的数据进行了一些包装而已。这样影响的仅仅是显示在我们的页面上数据。

高亮在Compass中更加方便,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<compass-core-config xmlns="http://www.compass-project.org/schema/core-config"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.compass-project.org/schema/core-config
           http://www.compass-project.org/schema/compass-core-config-2.2.xsd">

    <compass name="default">
        <!-- 连接信息,好比数据库的连接信息 -->
        <connection>
            <file path="./indexDir/" />
        </connection>

        <!-- 映射信息,好比Hibernate的映射关系 -->
        <mappings>
            <class name="domain.Article" />
        </mappings>
        <!-- 分词器以及高亮器的配置 -->
        <settings>
            <!-- 分词器的配置,可选择中文的 -->
            <setting name="compass.engine.amalyzer.default.type" value="jeasy.analysis.MMAnalyzer" />
            <!-- 高亮器前缀 -->
            <setting name="compass.engine.highlighter.default.formatter.simple.pre" value="&lt;font color='red' &gt;" />
            <!-- 高亮器后缀 -->
            <setting name="compass.engine.highlighter.default.formatter.simple.post" value="&lt;/font&gt;" />
            <!-- 高亮器摘要的长度 -->
            <setting name="compass.engine.highlighter.default.fragmenter.simple.size" value="100" />
        </settings>
    </compass>
</compass-core-config>   

关于排序

类比国内某搜索引擎,排序其实并不公平。我们可以认为的控制排序,Compass亦是如此。

原理

不管是Compass还是数据库,我们都会通过冗余字段来提高检索速度。或者进行排序。所以我们会在bean对象中添加一个冗余字段来帮助我们对数据进行排序操作。

冗余字段

/**
 * @Date 2016年8月2日
 *
 * @author Administrator
 */
package domain;

import org.compass.annotations.ExcludeFromAll;
import org.compass.annotations.Index;
import org.compass.annotations.Searchable;
import org.compass.annotations.SearchableBoostProperty;
import org.compass.annotations.SearchableId;
import org.compass.annotations.SearchableProperty;
import org.compass.annotations.Store;

/**
 *
 * Compass的映射配置要求
 *
 * 在实体类上面有一个@Searchable注解<br>
 *
 * 在属性上面,至少有一个有@SearchableId
 *
 * 其他的属性只需要是@SearchableProperty即可
 *
 *
 *
 * @author 郭瑞彪
 */
@Searchable
public class Article {
    @SearchableId
    private Integer id;
    // @SearchableProperty(store = Store.YES, index =
    // Index.ANALYZED,,excludeFromAll=ExcludeFromAll.YES)查询的时候就会排除此项来进行查询操作
    @SearchableProperty(store = Store.YES, index = Index.ANALYZED)
    private String title;
    @SearchableProperty(store = Store.YES, index = Index.ANALYZED)
    private String content;

    ////////////////////////////////////////
    // 如果要想改变查询结果的顺序,这个bean里面就应该有一个记录boostValue的值,这样使用的时候在具体的结果集对象上进行修改即可
    @SearchableBoostProperty
    private float boostValue = 1F;
    ////////////////////////////////////////

    public float getBoostValue() {
        return boostValue;
    }

    public void setBoostValue(float boostValue) {
        this.boostValue = boostValue;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    @Override
    public String toString() {
        return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

}

使用方式

我们在存储数据的时候就可以指定某一个对象的权重了。即设置刚才的serBoostValue。这样在我们获取数据的时候,就会获得排序的数据。

测试排序

@Test
    public void testBoostValueSearch() throws Exception {

        String queryString = "lucene";

        // 查询,得到结果
        List<Article> articles = new ArrayList<Article>();

        // 建立索引
        Compass compassSessionFactory = CompassUtils.getCompassSessionFactory();

        CompassSession session = compassSessionFactory.openSession();
        CompassTransaction tx = session.beginTransaction();
        CompassHits hits = session.find(queryString);

        // 处理结果
        for (int i = 0; i < hits.length(); i++) {
            Article a = (Article) hits.data(i);
            if (i == 0)
                a.setBoostValue(2F);
            articles.add(a);
        }
        tx.commit();
        session.close();

        // 显示结果
        System.out.println(articles.toString());
        for (Article a : articles) {
            System.out.println("-----------搜索结果如下-----------------");
            System.out.println(">>>id: " + a.getId());
            System.out.println(">>>title:" + a.getTitle());
            System.out.println(">>>content:" + a.getContent());
        }
    }

关于过滤

原理

过滤的话,无非就是要哪一段数据,不要那一段数据。这自然是关乎到查询方式的变化,同样Compass就是基于这么个理念,赋予query对象新的filter。从而实现过滤操作。过滤的实现,同样要依赖于一个冗余字段。(需要在这个字段上声明@SearchableProperty注解)

冗余字段

/**
 * @Date 2016年8月2日
 *
 * @author Administrator
 */
package domain;

import org.compass.annotations.ExcludeFromAll;
import org.compass.annotations.Index;
import org.compass.annotations.Searchable;
import org.compass.annotations.SearchableBoostProperty;
import org.compass.annotations.SearchableId;
import org.compass.annotations.SearchableProperty;
import org.compass.annotations.Store;

/**
 *
 * Compass的映射配置要求
 *
 * 在实体类上面有一个@Searchable注解<br>
 *
 * 在属性上面,至少有一个有@SearchableId
 *
 * 其他的属性只需要是@SearchableProperty即可
 *
 *
 *
 * @author 郭瑞彪
 */
@Searchable
public class Article {
    @SearchableId
    private Integer id;
    // @SearchableProperty(store = Store.YES, index =
    // Index.ANALYZED,,excludeFromAll=ExcludeFromAll.YES)查询的时候就会排除此项来进行查询操作
    @SearchableProperty(store = Store.YES, index = Index.ANALYZED)
    private String title;
    @SearchableProperty(store = Store.YES, index = Index.ANALYZED)
    private String content;

    ////////////////////////////////////////
    // 为了过滤器所需
    @SearchableProperty(store = Store.YES, index = Index.ANALYZED)
    private int filmeta;

    public int getFilmeta() {
        return filmeta;
    }

    public void setFilmeta(int filmeta) {
        this.filmeta = filmeta;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    @Override
    public String toString() {
        return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

}

如何使用

使用的时候需要将过滤信息附加到查询对象query上,这样才能生效。

CompassQuery query = null;
CompassQueryFilter filter = null;
filter = session.queryFilterBuilder().between("filmeta", 3, 7, true, true);
query=session.queryBuilder().queryString(queryString).toQuery();
query.setFilter(filter);

测试过滤

@Test
    public void testFilterSearch() throws Exception {

        String queryString = "lucene";

        // 查询,得到结果
        List<Article> articles = new ArrayList<Article>();

        // 建立索引
        Compass compassSessionFactory = CompassUtils.getCompassSessionFactory();

        CompassSession session = compassSessionFactory.openSession();
        CompassTransaction tx = session.beginTransaction();
        CompassHits hits = null;
        CompassQuery query = null;
        CompassQueryFilter filter = null;
        // 构建查询对象,我们可以使用这样的queryBuilder方式创建出各式各样的查询方式,如布尔查询,关键词查询,短语查询,模糊查询等等
        filter = session.queryFilterBuilder().between("filmeta", 3, 7, true, true);
        query = session.queryBuilder().queryString(queryString).toQuery();
        query.setFilter(filter);
        hits = query.hits();

        // 处理结果
        for (int i = 0; i < hits.length(); i++) {
            Article a = (Article) hits.data(i);
            if (i == 0)
                a.setBoostValue(2F);
            articles.add(a);
        }
        tx.commit();
        session.close();

        // 显示结果
        System.out.println(articles.toString());
        for (Article a : articles) {
            System.out.println("-----------搜索结果如下-----------------");
            System.out.println(">>>id: " + a.getId());
            System.out.println(">>>title:" + a.getTitle());
            System.out.println(">>>content:" + a.getContent());
        }
    }

关于查询

在Compass中,查询操作更是方便,我们只需要调用相关的API即可。如下图

不难看出,各种查询的底层就是基于过滤来实现的,所以我们可以一句过滤的操作来实现我们的各种查询需求。

总结

经过了这两天的搜索引擎框架的学习,基本上我们可以开发出适合自己项目需求的站内搜索或者全文搜索了。至此,本系列学习也到此结束。

如果我的这些文章恰好给对此迷茫的你一点灵光,我就非常的欣慰了。

:-)

Compass 更智能的搜索引擎(3)--高亮,排序,过滤以及各种搜索的更多相关文章

  1. Compass 更智能的搜索引擎(2)--进阶

    经过了Compass 更智能的搜索引擎(1)–入门的学习,想必对于Compass的使用有了更深的认识了吧.下面谈点更加切合实际开发的东西.那就是CRUD. 面向对象的分页 dao层实现 代码释义 优点 ...

  2. Compass 更智能的搜索引擎(1)--入门

    学完了前面的Lucene系列教程: 全文检索 Lucene(1)–入门 全文检索 Lucene(2)–进阶 全文检索 Lucene(3)–分页 全文检索 Lucene(4)–高亮 Lucene确实是个 ...

  3. iPad版微信终于来临了 微信5.4版搜索更智能 转账就是发消息

    等待甚久的iPad版微信终于来临了!昨日微信iOS版本更新至5.4.0.16,新增功能包括搜索公众号.识别图中二维码.面对面收钱,同时适配iPad.(微信5.4安卓版重回ios风格 导航菜单都放底栏位 ...

  4. C# .NET更智能的数据库操作的封装

    前述: 对数据库操作的封装,相信网络上已经有一大堆,ORM框架,或者是.NET本身的EF,都很好的支持数据库操作.这篇文章是分享自己所思考的,对数据库操作的简单封装.我对于这篇文章,认为被浏览者所关注 ...

  5. 使用OpenAPI构建更智能的API

    像OpenAPI这样的API描述规范是一个关键工具,您应该尽可能地将其好好掌握,记录和执行API的工作由计算机和开发人员完成:OpenAPI 3.0现在允许额外的表现力,可以让机器为我们做更多有用的工 ...

  6. Win10系统升级更新方式将会更智能

    使用Win10系统的你肯定遇到过在工作时开始自动更新而不得不搁置工作的情况,想必你也已经被Win10系统的自动更新折磨不已,不过这种情况将会马上得到改观. 微软现在已经开始寻找更智能的版本升级更新方式 ...

  7. 从程序到系统:建立一个更智能的世界——记Joseph Sifakis“21世纪的计算”大会主题演讲

    Sifakis"21世纪的计算"大会主题演讲" title="从程序到系统:建立一个更智能的世界--记Joseph Sifakis"21世纪的计算&q ...

  8. 微软Project Oxford帮助开发人员创建更智能的应用

    Oxford帮助开发人员创建更智能的应用" title="微软Project Oxford帮助开发人员创建更智能的应用"> 假设你是一名对关于健身的应用充满奇思妙想 ...

  9. AI剪辑和自定义UI,打造更智能的剪辑体验

    为满足开发者构建高效的应用内视频编辑能力,7月的HMS Core 6.0 推出了视频编辑服务(Video Editor Kit),一站式的视频处理能力获得了积极反响.同时,我们也关注到开发者需要集成丰 ...

随机推荐

  1. 用PHP如何实现这种乘法口诀表?

    用PHP如何实现这种乘法口诀表? 1x1=1 ,1x2=2 ,1x3=3 ,.....,1x9=9 2x2=4 ,2x3=6 ,......,2x9=18 ........ ...... 8x8=64 ...

  2. Unity依赖注入

    一.简介 Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题.构建一个成功应用程序的关键是实现非常松散的 ...

  3. [C#]使用 Jenkins 为 .Net Core 实现持续集成/部署

    在前后端分离开发的项目当中为了避免重复构建发布,我们需要部署一个持续发布环境,而目前的开发环境服务器都是基于 CentOS 的,因此每次在本地发布之后还需要打包,上传,部署,十分繁琐.故这里采用了比较 ...

  4. [MongoDB教程] 1.简介

    MongoDB (名称来自「humongous (巨大无比的)」), 是一个可扩展的高性能,开源,模式自由,面向文档的NoSQL,基于 分布式 文件存储,由 C++ 语言编写,设计之初旨在为 WEB ...

  5. 3.如何搭建Appium自动化测试环境

    整个APP自动化环境安装可以参照虫师博客安装 附以下链接: http://www.cnblogs.com/fnng/category/695788.html 下面介绍运用到工作中遇到的一些问题 1.如 ...

  6. WebApi-路由机制

    一.WebApi路由机制是什么? 路由机制通俗点来说:其实就是WebApi框架将用户在浏览器中输入的Url地址和路由表中的路由进行匹配,并根据最终匹配的路由去寻找并匹配相应的Controller和Ac ...

  7. Html5调用电脑摄像头-----火狐浏览器、360浏览器、搜狗浏览器、谷歌浏览器

     <!DOCTYPE html>  <html lang="en">  <head>  <meta charset="UTF-8 ...

  8. php一句话反弹bash shell

    来源:https://www.leavesongs.com/PHP/backshell-via-php.html 用到了,记录一下 $sock = fsockopen($ip, $port); $de ...

  9. osx mitmproxy ssl 错误

    记录一下,总是在这里折腾. cd ~ cd .mitmproxy cp mitmproxy-ca-cert.pem ~/ 然后到目录下双击mitmproxy-ca-cert.pem ,在钥匙串中的登录 ...

  10. BZOJ 3938 Robot

    Description 小q有n只机器人,一开始他把机器人放在了一条数轴上,第i只机器人在ai的位置上静止,而自己站在原点.在这 之后小q会执行一些操作,他想要命令一个机器人向左或者向右移动x格.但是 ...