【微服务】Elasticsearch数据聚合自动补全数据同步(四)

news2025/6/9 4:03:41

🚗Es学习·第四站~
🚩Es学习起始站:【微服务】Elasticsearch概述&环境搭建(一)
🚩本文已收录至专栏:微服务探索之旅
👍希望您能有所收获

在第二站的学习中,我们已经导入了大量数据到es中,实现了数据存储功能。接下来如需看自己实操效果请根据第二站的三.环境搭建部分导入初始数据。

一.数据聚合

(1) 聚合的作用

聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

  • 什么品牌的手机最受欢迎?
  • 这些手机的平均价格、最高价格、最低价格?
  • 这些手机每月的销售情况如何?

实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

(2) 聚合的种类

聚合常见的有三类:

  • (Bucket)聚合:用来对文档做分组

    • TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组
    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等

    • Avg:求平均值
    • Max:求最大值
    • Min:求最小值
    • Stats:同时求max、min、avg、sum等
  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合
    在这里插入图片描述

注意:参加聚合的字段必须是keyword、日期、数值、布尔类型

(3) Bucket聚合

如果我们要统计所有数据中的酒店品牌有几种,其实就是按照品牌对数据分组。此时可以根据酒店品牌的名称做聚合,也就是Bucket聚合。

(3.1) 基本使用

语法如下:

GET /hotel/_search
{
  "size": 0,  // 设置size为0,设置结果中不包含文档,只包含聚合结果
  "aggs": { // 定义聚合
    "brandAgg": { //给聚合起个名字
      "terms": { // 聚合的类型,按照品牌值聚合,所以选择term
        "field": "brand", // 参与聚合的字段
        "size": 20 // 希望获取的聚合结果数量
      }
    }
  }
}

结果如图:
在这里插入图片描述

doc_count为聚合分组后其中文档的数量。

(3.2) 结果排序

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。

我们可以通过指定order属性,自定义聚合的排序方式

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "order": {
          "_count": "asc" // 按照_count升序排列
        },
        "size": 20
      }
    }
  }
}

(3.3) 限定范围

默认情况下,Bucket聚合是对索引库的所有文档做聚合,但真实场景下,只会对用户搜索的结果聚合。因此上述聚合必须添加限定条件。

我们要限定聚合的文档范围,只需添加query条件即可:

GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "lte": 200 // 只对200元以下的文档聚合
      }
    }
  }, 
  "size": 0, 
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}

这次,聚合得到的品牌明显变少了:
在这里插入图片描述

(4) Metric聚合

上述我们通过使用Bucket聚合对酒店按照品牌分组,形成了一个个桶。现在我们需要对桶内的酒店做运算,获取每个品牌的用户评分的min、max、avg等值。

这就要用到Metric聚合了,例如stat聚合:就可以获取min、max、avg等结果。

语法如下:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": { 
      "terms": { 
        "field": "brand", 
        "size": 20
      },
      "aggs": { // 是brands聚合的子聚合,也就是分组后对每组分别计算
        "score_stats": { // 聚合名称
          "stats": { // 聚合类型,这里stats可以计算min、max、avg等
            "field": "score" // Metric聚合字段,这里是score
          }
        }
      }
    }
  }
}

这里的score_stats聚合是在brandAgg的聚合内部嵌套的子聚合。因为我们需要在每个桶分别计算。

另外,我们还可以给聚合结果做个排序,例如按照每个桶的酒店平均分做排序:
在这里插入图片描述

(5) RestAPI实现聚合

(5.1) 基础语法

聚合条件与query条件同级别,因此需要使用request.source()来指定聚合条件。

聚合条件的语法:
在这里插入图片描述

聚合的结果也与查询结果不同,API也比较特殊。不过同样是JSON逐层解析:
在这里插入图片描述

(5.2) 使用示例

需求:查询杭州的所有酒店分类数据。

@Test
void tesAggregationt( ) {
        // 1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备DSL
        // 2.1.query
       request.source().query(QueryBuilders.termQuery("city","杭州"));
        // 2.2.设置size
        request.source().size(0);
        // 2.3.聚合
        request.source().aggregation(AggregationBuilders
                                   .terms("brandAgg")
                                   .field("brand")
                                   .size(100)
                                  );
        // 3.发出请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.解析结果
        Aggregations aggregations = response.getAggregations();
   	    // 4.1.根据聚合名称获取聚合结果
   	    Terms brandTerms = aggregations.get(aggName);
   	    // 4.2.获取buckets
   	    List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
   	    // 4.3.遍历打印结果
   	    for (Terms.Bucket bucket : buckets) {
   	        // 4.4.获取key
   	        String key = bucket.getKeyAsString();
            System.out.println(key);
   	    }
}

运行可以看到我们成功查出了酒店数据
在这里插入图片描述

二.自动补全

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项,如图:
在这里插入图片描述

这种根据用户输入的字母,提示完整词条的功能,就是自动补全了。

(1) 拼音分词器

要实现根据字母做补全,就必须对文档按照拼音分词,这时就需要自己配置拼音分词功能,在GitHub上恰好有elasticsearch的拼音分词插件。
在这里插入图片描述

链接:https://pan.baidu.com/s/1eSlsQ6ypaDNkqXO75mC6IA
提取码:3yzw

资料中也提供了拼音分词器的安装包:
在这里插入图片描述

安装步骤:

  1. 连接服务器,切换到es绑定的插件数据卷中
cd /var/lib/docker/volumes/es-plugins/_data
2. 将压缩包上传至此目录并解压
unzip elasticsearch-analysis-pinyin-7.12.1.zip -d py

​ 3. 重启elasticsearch

docker restart es
  1. 测试用法
POST /_analyze
{
  "text": "如家酒店还不错",
  "analyzer": "pinyin"
}
  1. 结果:
    在这里插入图片描述

如上可以看到我们已经成功安装好了拼音分词器。但是它还存在一些问题,无法直接使用,接下来让我们一起解决吧。

(2) 自定义分词器

(2.1) 概述

默认的拼音分词器会将每个汉字单独分为拼音,而我们所希望的是每个词条形成一组拼音,因此需要对拼音分词器做个性化定制,形成自定义分词器。

elasticsearch中分词器(analyzer)的组成包含三部分:

  • character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
  • tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
  • tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

文档分词时会依次由这三部分来处理文档:
在这里插入图片描述

(2.2) 使用

我们在可以在创建索引库时,通过settings来配置自定义的analyzer(分词器)。

声明自定义分词器的语法如下:

PUT /test  // 创建索引库
{
  "settings": {
    "analysis": {
      "analyzer": { // 自定义分词器
        "my_analyzer": {  // 自定义分词器名称
          "tokenizer": "ik_max_word", // 切割词条
          "filter": "py"      // 自定义拼音处理方式
        }
      },
      "filter": { // 自定义tokenizer filter
        "py": { // 过滤器名称
          "type": "pinyin", // 过滤器类型,这里是pinyin
		  "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {  // 定义字段
        "type": "text",  // 定义类型
        "analyzer": "my_analyzer",  // 定义字段分词器
        "search_analyzer": "ik_smart" 
      }
    }
  }
}

拼音分词器filter属性详细配置介绍可以看官方文档拼音分词插件。

测试:
在这里插入图片描述

(2.3) 补充

拼音分词器适合在创建倒排索引的时候使用,但不适合在搜索的时候使用,这是为了避免搜索时搜到到同音字。
在这里插入图片描述

改进使用

PUT /test  
{
  "settings": {
    "analysis": {
      "analyzer": { 
        "my_analyzer": {  
          "tokenizer": "ik_max_word", 
          "filter": "py"      
        }
      },
      "filter": { 
        "py": {...}
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {  
        "type": "text",  
        "analyzer": "my_analyzer",  // 指定创建倒排索引分词器
        "search_analyzer": "ik_smart"   // 指定搜索时分词器
      }
    }
  }
}

我们可以在配置中指定两个分词器,一个用于创建倒排索引,一个用于搜索。

(3) 自动补全查询

es提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:

  • 参与补全查询的字段必须是completion类型。

  • 字段的内容一般是用来补全的多个词条形成的数组。

比如,一个这样的索引库:

// 创建索引库
PUT test
{
  "mappings": {
    "properties": {
      "title":{
        "type": "completion"
      }
    }
  }
}

然后插入下面的数据:

// 示例数据
POST test/_doc
{
  "title": ["Sony", "WH-1000XM3"]
}
POST test/_doc
{
  "title": ["SK-II", "PITERA"]
}
POST test/_doc
{
  "title": ["Nintendo", "switch"]
}

查询的DSL语句如下:

// 自动补全查询
GET /test/_search
{
  "suggest": {
    "title_suggest": {
      "text": "s", // 查询时待补全关键字
      "completion": {
        "field": "title", // 补全查询的字段
        "skip_duplicates": true, // 跳过重复的
        "size": 10 // 获取前10条结果
      }
    }
  }
}

测试结果:
在这里插入图片描述

如上可以看到我们已经成功实现了自动补全功能,接下来让我们一起用Java代码来实现一下。

(4) RestAPI实现自动补全

(4.1) 基础语法

先让我们看看发送请求代码对比
在这里插入图片描述

自动补全结果解析的代码如下:
在这里插入图片描述

(4.2) 使用示例

@Test
void testSuggester() {
        // 1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备DSL
        request.source().suggest(new SuggestBuilder().addSuggestion(
            "suggestions",
            SuggestBuilders.completionSuggestion("suggestion")
            .prefix("h")
            .skipDuplicates(true)
            .size(10)
        ));
        // 3.发起请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.解析结果
        Suggest suggest = response.getSuggest();
        // 4.1.根据补全查询名称,获取补全结果
        CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
        // 4.2.获取options
        List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
        // 4.3.遍历打印
        for (CompletionSuggestion.Entry.Option option : options) {
            String text = option.getText().toString();
            System.out.println(text)
        }
}

运行可以看到我们已经成功获取到补全结果
在这里插入图片描述

三.数据同步方案

本处不涉及代码,方案实现可以看项目实战篇

(1) 引入

es中的数据来自于mysql数据库,因此mysql数据发生改变时,es也必须跟着改变,这个就是elasticsearch与mysql之间的数据同步
在这里插入图片描述

(2) 思路分析

常见的数据同步方案有三种:

  • 同步调用
  • 异步通知
  • 监听binlog

(2.1 ) 同步调用

方案一:同步调用
在这里插入图片描述

基本步骤如下:

  • hotel-demo服务对外提供接口,用来修改elasticsearch中的数据
  • 酒店管理服务在完成数据库操作后,直接调用hotel-demo服务提供的修改接口,

(2.2) 异步通知

方案二:异步通知
在这里插入图片描述

流程如下:

  • hotel-admin服务对mysql数据库数据完成增、删、改后,发送MQ消息
  • hotel-demo服务监听MQ,接收到消息后完成elasticsearch数据修改

(2.3) 监听binlog

方案三:监听binlog

流程如下:

  • 给mysql开启binlog功能
  • mysql完成增、删、改操作都会记录在binlog中
  • hotel-demo基于canal监听binlog变化,实时更新elasticsearch中的内容

(2.4) 优缺点对比

方式一:同步调用

  • 优点:实现简单,粗暴
  • 缺点:业务耦合度高

方式二:异步通知

  • 优点:低耦合,实现难度一般
  • 缺点:依赖mq的可靠性

方式三:监听binlog

  • 优点:完全解除服务间耦合
  • 缺点:开启binlog增加数据库负担、实现复杂度高

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/334359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IBM AIX 升级Openssh 实现篇(编译安装)

升级成功佐证 !!!本文所有内容仅作参考,请在测试环境中具体测试完毕后才能应用于生产环境!!! [1]备份和恢复方案 开启telnet 服务,防止ssh 掉线后无法重连维护。在修复漏洞后关闭telnet。 备份该服务相关的所有文件,以便恢复。 root@TEST:/etc# vi inetd.conf #ftp…

原型图设计软件哪个好用?6款好用软件推荐

原型图软件列表 1、墨刀-极简超快的移动应用原型工具 2、ProcessOn-在线作图工具&#xff0c;你不用装 Visio 了 3、摩客-简洁高效的原型图设计工具 4、xiaopiu-国内优雅高效的在线 APP 原型工具 5、Axure-老牌原型工具&#xff0c;8.0 开始对响应式设计做了更好的支持&…

ONES 支持多项信创适配,打造自主可控的国产化平台

近日&#xff0c;ONES 顺利通过麒麟软件 NeoCertify、华为鲲鹏技术、达梦数据库的兼容性测试认证&#xff0c;至此&#xff0c;ONES 已完成国产操作系统、国产 CPU、国产数据库的多维度适配&#xff0c;成为目前唯一支持信创的研发管理平台&#xff0c;这标志着 ONES 在自主可控…

聚类分析--基本原理、方法(Kmeans,层次聚类)

文章目录聚类分析的定义基本原理商业应用场景聚类分析步骤聚类分析方法层次分析法/系统聚类法&#xff08;小样本&#xff09;提问&#xff1a;如何选择合适的分类结果K-means疑问&#xff1a;聚类分析的定义 聚类分析就是将研究对象根据一些特征指标&#xff0c;把比较相似的…

ubuntu qt程序无法输入中文 QLineEdit输入框无法切换输入法

目录一、问题描述二、解决思路三、步骤描述一、问题描述 测试软件在运行时无法通过键盘快捷键切换中文输入法&#xff0c;主要原因为qt应用程序没成功加载到输入法插件。 本文的以测试程序demo为例&#xff0c;进行过程展示&#xff0c;demo名字为“test-chinese-lineedit”。…

stream流处理初识

stream流处理初识 java8中的集合支持stream方法, 它会返回一个流(java.util.stream.Stream)IDEA集成的工具查看流式链过程&#xff1a; 流的操作 &#xff1a; 流的概念&#xff1a; java8中的集合支持stream方法,它会返回一个流(java.util.stream.Stream) 元素序列: 就像集…

【数据结构】优先级队列----堆

优先级队列----堆优先级队列堆堆的创建堆的插入&#xff1a;堆的删除&#xff1a;PriorityQueue的特性PriorityQueue的构造与方法优先级队列 优先级队列&#xff1a; 不同于先进先出的普通队列&#xff0c;在一些情况下&#xff0c;优先级高的元素要先出队列。而这种队列需要提…

开启Openharmony 开发之旅

之前因为太懒&#xff0c;所以很少写博客。最近做了一年的鸿蒙开发。想记录下&#xff0c;故开始写点东西&#xff0c;作为学习和开发笔记吧&#xff01;先分享几个开源鸿蒙的学习网站。 1.开源鸿蒙官网 OpenAtom OpenHarmonyhttps://docs.openharmony.cn/pages/v3.1/zh-cn/a…

《MySQL系列-InnoDB引擎19》文件-日志文件-二进制日志

日志文件 日志文件记录了影响MySQL数据库的各种类型活动。MySQL数据库中常见的日志文件有&#xff1a; 错误日志(error log)二进制日志(bilog)慢查询日志(slow query log)查询日志(log) 这些日志文件可以帮助DBA对MySQL数据库的运行状态进行诊断&#xff0c;从而更好的进行数…

INTx中断机制源码分析

INTx中断机制源码分析 文章目录INTx中断机制源码分析参考资料&#xff1a;一、 配置空间二、 扫描设备时分配中断号三、 使用INTx中断四、 PCIe中断树五、 PCIe INTx中断映射过程5.1 PCIe控制器支持的中断5.2 PCIe控制器注册中断5.3 PCIe设备中断号的分配5.3.1 IRQ domain5.3.2…

Java源码程序设计-房屋出租管理系统设计与实现

摘 要系统设计系统实现开发环境摘 要 随着我国市场经济的快速发展和人们生活水平的不断提高&#xff0c;简单的房屋出租服务已经不能满足人们的需求。如何利用先进的管理手段&#xff0c;提高房屋出租的管理水平&#xff0c;是当今社会所面临的一个重要课题。 本文采用结构化…

Win10系统电脑开机后总是蓝屏无法使用怎么办?

Win10系统电脑开机后总是蓝屏无法使用怎么办&#xff1f;电脑开机的时候出现了蓝屏问题&#xff0c;这个情况是我们的电脑系统不兼容导致的。遇到这个问题一般是需要去进行系统的重装来解决&#xff0c;安装一个更兼容的系统就可以解决问题了。一起来看看详细的解决方法分享吧。…

前端学习第八站——CSS定位和装饰

目录 一、定位 1.1 网页常见布局方式 1.2 定位的常见应用场景 2.1 定位初体验 2.2 使用定位 3.1 静态定位 4.1 相对定位 5.1 绝对定位 6.1 子绝父相 7. 固定定位 8.1 定位的层级关系 8.2 更改定位元素的层级 9.总结 二、装饰 1.1 了解基线 1.2 文字对齐问…

安卓小游戏:小板弹球

安卓小游戏&#xff1a;小板弹球 前言 这个是通过自定义View实现小游戏的第三篇&#xff0c;是小时候玩的那种五块钱的游戏机上的&#xff0c;和俄罗斯方块很像&#xff0c;小时候觉得很有意思&#xff0c;就模仿了一下。 需求 这里的逻辑就是板能把球弹起来&#xff0c;球…

股票交易开放接口是什么意思?

在股票量化市场上&#xff0c;大家可能对股票交易开放接口的意思不太理解&#xff0c;其实换个角度来看&#xff0c;就是关于由开发团队进行开发的股票交易开放接口&#xff0c;那么对于接口的开发原理跟代码是怎么样的呢&#xff1f;一、股票交易开放接口函数的调用&#xff1…

面试的同学看这里!这套Java面试八股文,已经帮助200+人进入大厂

在看这篇文章之前&#xff0c;我想我们需要先搞明白八股文是什么&#xff1f;&#xff1f;&#xff1f; 明清科举考试的一种文体&#xff0c;也称制义、制艺、时文、八比文。八股文章就四书五经取题&#xff0c;内容必须用古人的语气&#xff0c;绝对不允许自由发挥&#xff0c…

Git 常用命令

一、基本的git命令 1、查看现在在哪个分支 git branch 2、切换到某分支 git checkout 某分支 3、添加修改后的代码到缓存区 git add . 4、添加提交代码的备注 git commit -m "注释" 5、提交代码到指定的分支 git push origin 某分支 6、从远程仓库克隆git仓库…

四 、QML常用控件的使用详解

在Qt Quick的世界里&#xff0c;window对象用于创建一个与操作系统相关的顶层窗口&#xff0c;而其他的元素&#xff0c;如Text Rectangle,Image等&#xff0c;都睡Windows提功能场景里面的显示对象&#xff0c;Window还有一个派生类&#xff0c;即是大名鼎鼎的Application Win…

基于DSP+FPGA高速运动控制器设计

基于“PC运动控制器”结构的开放式机器人运动控制系统能够充分利用PC开放程 度高、通用性好、处理能力强等特点以及运动控制器运算速度快、实时性能好、控制能 力强等特点&#xff0c;因此得到较快发展&#xff0c;成为目前的研究热点。但目前采用此种结构的开放式 机器人运动控…

3D模型深度生成网络【ShapeAssembly】

推荐&#xff1a;使用 NSDT场景设计器 快速搭建 3D场景。 我们提出了一个深度生成模型&#xff0c;该模型学习在ShapeAssembly中编写新颖的程序&#xff0c;ShapeAssembly是一种用于建模3D形状结构的特定领域语言。 执行 ShapeAssembly 程序会生成一个由部件代理长方体的分层连…