12 数据同步
elasticsearch中的酒店数据来自于mysql数据库,因此mysql数据发生改变时,elasticsearch也必须跟着改变,这个就是elasticsearch与mysql之间的 数据同步。
在微服务中,负责酒店管理(操作mysql )的业务与负责酒店搜索(操作elasticsearch )的业务可能在两个不同的微服务上,数据同步该如何实现呢?
思路分析常见的数据同步方案有三种:
同步调用
异步通知
监听binlog
同步调用
hotel-demo对外提供接口,用来修改elasticsearch中的数据
酒店管理服务在完成数据库操作后,直接调用hotel-demo提供的接口
优点:实现简单,粗暴
缺点:业务耦合度高
异步通知
hotel-admin对mysql数据库数据完成增、删、改后,发送MQ消息
hotel-demo监听MQ,接收到消息后完成elasticsearch数据修改
监听binlog
给mysql开启binlog功能
mysql完成增、删、改操作都会记录在binlog中
hotel-demo基于canal监听binlog变化,实时 ...
11 自动补全
当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项,如图:
这种根据用户输入的字母,提示完整词条的功能,就是自动补全
需要根据拼音字母来推断,因此要用到拼音分词功能。
拼音分词器要实现根据字母做补全,就必须对文档按照拼音分词。在GitHub上恰好有elasticsearch的拼音分词插件。地址:https://github.com/medcl/elasticsearch-analysis-pinyin,请安装ES对应版本的拼音分词器
安装方式
①解压
②上传到虚拟机中,elasticsearch的plugin目录
③重启elasticsearch
④测试
12345POST /_analyze{ "text": "如家酒店还不错", "analyzer": "pinyin"}
自定义分词器默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。
ela ...
10 数据聚合
聚合(aggregations) 可以让我们极其方便的实现对数据的统计、分析、运算。例如:
什么品牌的手机最受欢迎?
这些手机的平均价格、最高价格、最低价格?
这些手机每月的销售情况如何?
实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。
聚合的种类聚合常见的有三类:
桶(Bucket)聚合:用来对文档做分组
TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组
Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等
Avg:求平均值
Max:求最大值
Min:求最小值
Stats:同时求max、min、avg、sum等
管道(pipeline)聚合:其它聚合的结果为基础做聚合
注意:参加聚合的字段必须是keyword、日期、数值、布尔类型
DSL实现聚合要统计所有数据中的酒店品牌有几种,其实就是按照品牌对数据分组。此时可以根据酒店品牌的名称做聚合,也就是Bucket聚合。
Bucket聚合语法1 ...
9 酒店项目
搜索分页
实现黑马旅游的酒店搜索功能,完成关键字搜索和分页
在项目的首页,有一个大大的搜索框,还有分页按钮:
点击搜索按钮,可以看到浏览器控制台发出了请求:
请求参数如下:
需求分析
请求方式:POST
请求路径:/hotel/list
请求参数:JSON对象,包含4个字段:
key:搜索关键字
page:页码
size:每页大小
sortBy:排序,目前暂不实现
返回值:分页查询,需要返回分页结果PageResult,包含两个属性:
total:总条数
List<HotelDoc>:当前页的数据
业务流程
步骤一:定义实体类,接收请求参数的JSON对象
步骤二:编写controller,接收页面的请求
步骤三:编写业务实现,利用RestHighLevelClient实现搜索、分页
定义实体类实体类有两个,一个是前端的请求参数实体,一个是服务端应该返回的响应结果实体。
请求参数
前端请求的json结构如下:
123456{ "key": "搜索关键字", "page&quo ...
8 RestClient查询文档
基于RestHighLevelClient对象,步骤包括:
准备Request对象
准备请求参数
发起请求
解析响应
快速入门
发起查询请求
创建SearchRequest对象,指定索引库名
利用request.source()构建DSL,DSL中可以包含查询、分页、排序、高亮等
query():代表查询条件,利用QueryBuilders.matchAllQuery()构建一个match_all查询的DSL
利用client.search()发送请求,得到响应
request.source(),其中包含了查询、排序、分页、高亮等所有功能:
QueryBuilders,其中包含match、term、function_score、bool等各种查询:
解析响应
elasticsearch返回的结果是一个JSON字符串,结构包含:
hits:命中的结果
total:总条数,其中的value是具体的总条数值
max_score:所有结果中得分最高的文档的相关性算分
hits:搜索结果的文档数组,其中的每个文档都是一个json对象
_source:文档中的 ...
7 搜索结果处理
搜索的结果可以按照用户指定的方式去处理或展示。
排序elasticsearch默认是根据相关度算分(_score)来排序,但是也支持自定义方式对搜索结果排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。
普通字段排序
keyword、数值、日期类型排序的语法基本一致。
1234567891011GET /indexName/_search{ "query": { "match_all": {} }, "sort": [ { "FIELD": "desc" // 排序字段、排序方式ASC、DESC } ]}
排序条件是一个数组,也就是可以写多个排序条件。按照声明的顺序,当第一个条件相等时,再按照第二个条件排序,以此类推
酒店数据按照用户评价(score)降序排序,评价相同的按照价格(price)升序排序
地理坐标排序
地理坐标排序略 ...