zoukankan      html  css  js  c++  java
  • Spring Boot + Elasticsearch实现大批量数据集下中文的精确匹配-案例剖析

    缘由

    数据存储在MYSQ库中,数据基本维持不变,但数据量又较大(几千万)放在MYSQL中查询效率上较慢,寻求一种简单有效的方式提高查询效率,MYSQL并不擅长大规模数据量下的数据查询。

    技术方案

    考虑后期同样会使用到es,此次直接结合spring-boot框架形成一个独立服务,并不涉及UI展现内容,(ES版本2.4.5,5.0+版本的话就不能再使用spring data elasticsearch)技术组合如下:

    Spring Boot+ Spring-data-elasticsearch + Elasticsearch

    结合elasticsearch-jdbc插件,全量将数据一次性导入es中,后期不涉及数据变更。

    es安装

    测试期间单机安装,官网下载对应版本,由于笔者工作环境基于JDK7,所以下载5.0以下版本,5.0+均依赖Java8,同时使用到elasticsearch-jdbc插件,一并下载安装完成。

    走过的大弯路

    直接使用elasticsearch-jdbc工具,编写脚本文件,抽取数据到es中,脚本样例如下:

    1. #!/bin/sh

    2. DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

    3. bin=${DIR}/../bin

    4. lib=${DIR}/../lib

    5. echo '

    6. {

    7.    "type": "jdbc",

    8.    "jdbc": {

    9.        "elasticsearch.autodiscover": true,

    10.        "url": "jdbc:mysql://192.168.1.3:3306/test",

    11.        "user": "root",

    12.        "password": "root",

    13.        "sql": "SELECT * from tb_name1",

    14.        "elasticsearch": {

    15.            "host": "192.168.1.1",

    16.            "port": 9300

    17.        },

    18.        "index": "my-index",

    19.        "type": "my-type"

    20.    }

    21. }

    22. ' | java

    23.    -cp "${lib}/*"

    24.    -Dlog4j.configurationFile=${bin}/log4j2.xml

    25.    org.xbib.tools.Runner

    26.    org.xbib.tools.JDBCImporter

    数据导入成功后,可使用head插件直接查看到。使用基本查询测试,查询条件是name=测试&num=100,使用精确匹配term语句,查询数据未果,实际使用num=100独立查询时,有相关数据。

    问题跟踪解决

    导致此现象的原因在于中文分词的问题,使用elasticsearch-jdbc脚本中并未处理列的mapping类型。(中间做过一次尝试,在脚本中定义对应的type_mapping,但并未成功,有兴趣的朋友可再做尝试)。

    注:es与ik分词插件结合,版本匹配需要特别关注,但本案例并不涉及

    结合此案例,查询时并不需要分词,而是精确匹配,但es默认情况下是指定string类型的分词,所以在index创建之前我们需要手动指定相关列不需要分词:not_analyzed,形如:

    1. CURL -XPOST http://192.168.1.105:9200/my-index -d {

    2.    {

    3.    "mappings": {

    4.        "my-type": {

    5.            "properties": {

    6.                "name": {

    7.                    "type": "string",

    8.                    "index": "not_analyzed"

    9.                },

    10.                "num": {

    11.                    "type": "string",

    12.                    "index": "not_analyzed"

    13.                }

    14.            }

    15.        }

    16.    }

    17. }

    创建索引成功后,再使用elasticsearch-jdbc的脚本导入数据,相关数据列不会再使用分词分析,再使用term组合精确查询时,就可以查询相关数据来。

    SpringBoot应用

    pom.xml关键配置

    1. <dependency>

    2.    <groupId>org.springframework.boot</groupId>

    3.    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>

    4. </dependency>

    5. <dependency>

    6.    <groupId>org.springframework.boot</groupId>

    7.    <artifactId>spring-boot-starter-web</artifactId>

    8.    <exclusions>

    9.        <exclusion>

    10.            <artifactId>log4j-over-slf4j</artifactId>

    11.            <groupId>org.slf4j</groupId>

    12.        </exclusion>

    13.    </exclusions>

    14. </dependency>

    15. <dependency>

    16.    <groupId>org.springframework.boot</groupId>

    17.    <artifactId>spring-boot-starter</artifactId>

    18.    <exclusions>

    19.        <exclusion>

    20.            <groupId>org.springframework.boot</groupId>

    21.            <artifactId>spring-boot-starter-logging</artifactId>

    22.        </exclusion>

    23.    </exclusions>

    24. </dependency>

    25. <dependency>

    26.    <groupId>org.springframework.boot</groupId>

    27.    <artifactId>spring-boot-starter-test</artifactId>

    28.    <scope>test</scope>

    29. </dependency>

    30. <dependency>

    31.    <groupId>org.springframework.boot</groupId>

    32.    <artifactId>spring-boot-starter-log4j</artifactId>

    33.    <version>1.3.1.RELEASE</version>

    34. </dependency>

    与elasticsearch交互实体

    1. @Data

    2. @Document(indexName = "my-index", type = "my-type", shards = 5, replicas = 1, indexStoreType = "fs", refreshInterval = "-1")

    3. public class DataBean {

    4.    /**

    5.     * code:名称

    6.     *

    7.     * @since JDK 1.6

    8.     */

    9.    public String name;

    10.    /**

    11.     * msg:编号

    12.     *

    13.     * @since JDK 1.6

    14.     */

    15.    public String num;

    16. }

    与es交互接口类,返回数据的唯一_id值,若查得数据表示命中数据,若为空并未数据不存在

    1. public interface DataBeanRepository extends ElasticsearchRepository<DataBean, Long> {

    2.    //案例中并未使用,但可以用

    3.    public List<BlackGreyData> findByNameAndNum(String name, String num);

    4. }

    下面是业务处理层,采用BoolQueryBuilder构建查询条件,也即可基于DSL模块查询数据,还可以采用Criteria查询。

    1. @Autowired

    2.    DataBeanRepository repository;

    3.    @Override

    4.    public List<DataBean> query(String name, String num, String type) {

    5.        //采用过滤器的形式,提高查询效率

    6.        BoolQueryBuilder builder = QueryBuilders.boolQuery();

    7.        builder.must(QueryBuilders.termQuery("name", name)).must(QueryBuilders.termQuery("num", num));

    8.        Iterable<DataBean> lists = repository.search(builder);

    9.        List<DataBean> datas = new ArrayList<>();

    10.        for (DataBean dataBean : lists) {

    11.            datas.add(dataBean);

    12.            logger.info("---------------------->>>Request result = 【" + dataBean + "】");

    13.        }

    14.        return datas;

    15.    }

    其它再编写对应的请求响应逻辑,即可完成简单服务的完成。

    测试结果

    GPS数据量5000W+,精确匹配查询出来50条数据,耗时700ms左右,结果查询缓存机制,基本可以稳定在300ms左右。这也是在单节点,未作任何优化的情况的结果。

    源码地址

    https://github.com/backkoms/spring-boot-elasticsearch

    扩展阅读:

    成长的乐趣,在于分享!
    大龄程序员,一路走来,感慨颇多。闲暇时写写字,希望能给同行人一点帮助。
    本文版权归作者growithus和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    CSS清浮动
    深入理解BFC
    深入理解CSS浮动
    CSS颜色模式转换器的实现
    深入理解CSS背景
    理解CSS前景色和透明度
    深入理解CSS六种颜色模式
    HTML学习目录
    深入理解display属性
    深入理解盒模型
  • 原文地址:https://www.cnblogs.com/growithus/p/11012210.html
Copyright © 2011-2022 走看看