前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Boot + Elasticsearch实现大批量数据集下中文的精确匹配-案例剖析

Spring Boot + Elasticsearch实现大批量数据集下中文的精确匹配-案例剖析

作者头像
MavenTalker
发布2023-03-07 10:25:56
5820
发布2023-03-07 10:25:56
举报
文章被收录于专栏:歪脖贰点零歪脖贰点零

缘由

数据存储在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中,脚本样例如下:

代码语言:javascript
复制
#!/bin/sh

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

echo '
{
    "type": "jdbc",
    "jdbc": {
        "elasticsearch.autodiscover": true,
        "url": "jdbc:mysql://192.168.1.3:3306/test",
        "user": "root",
        "password": "root",
        "sql": "SELECT * from tb_name1",
        "elasticsearch": {
            "host": "192.168.1.1",
            "port": 9300
        },
        "index": "my-index",
        "type": "my-type"
    }
}
' | java \
    -cp "${lib}/*" \
    -Dlog4j.configurationFile=${bin}/log4j2.xml \
    org.xbib.tools.Runner \
    org.xbib.tools.JDBCImporter

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

问题跟踪解决

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

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

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

代码语言:javascript
复制
CURL -XPOST http://192.168.1.105:9200/my-index -d {

    {
    "mappings": {
        "my-type": {
            "properties": {
                "name": {
                    "type": "string",
                    "index": "not_analyzed"
                },
                "num": {
                    "type": "string",
                    "index": "not_analyzed"
                }
            }
        }
    }
}

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

SpringBoot应用

pom.xml关键配置

代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>log4j-over-slf4j</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.1.RELEASE</version>
</dependency>

与elasticsearch交互实体

代码语言:javascript
复制
@Data
@Document(indexName = "my-index", type = "my-type", shards = 5, replicas = 1, indexStoreType = "fs", refreshInterval = "-1")
public class DataBean {

    /**
     * code:名称
     * 
     * @since JDK 1.6
     */
    public String name;

    /**
     * msg:编号
     * 
     * @since JDK 1.6
     */
    public String num;

}

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

代码语言:javascript
复制
public interface DataBeanRepository extends ElasticsearchRepository<DataBean, Long> {
    //案例中并未使用,但可以用
    public List<BlackGreyData> findByNameAndNum(String name, String num);
}

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

代码语言:javascript
复制
@Autowired
    DataBeanRepository repository;

    @Override
    public List<DataBean> query(String name, String num, String type) {
        //采用过滤器的形式,提高查询效率
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        builder.must(QueryBuilders.termQuery("name", name)).must(QueryBuilders.termQuery("num", num));
        Iterable<DataBean> lists = repository.search(builder);

        List<DataBean> datas = new ArrayList<>();
        for (DataBean dataBean : lists) {
            datas.add(dataBean);
            logger.info("---------------------->>>Request result = 【" + dataBean + "】");
        }
        return datas;
    }

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

测试结果

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

源码地址

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MavenTalk 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 缘由
  • 技术方案
  • es安装
  • 走过的大弯路
  • 问题跟踪解决
  • SpringBoot应用
  • 测试结果
  • 源码地址
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档