一、Elasticsearch的扩展
1.1 数据聚合
聚合是对文档的统计、分析、计算;
1.1.1 聚合的种类
聚合常见的有三大类:
-
桶(Bucket)聚合:Bucket聚合根据指定的条件将文档划分到不同的桶(Bucket)中,然后对每个桶中的文档进行统计和计算。桶聚合可以按照某个字段的值、日期范围等条件将文档分组,并统计每组的文档数量或某个字段的最大、最小、平均值等。
- TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组
- Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
-
度量(Metric)聚合:度量聚合是一种用于计算数值型字段上统计度量的聚合方式,可以计算某个字段的总和、平均值、最大值、最小值、标准差等度量。
- Avg:求平均值
- Max:求最大值
- Min:求最小值
- Stats:同时求max、min、avg、sum等
-
管道(pipeline)聚合:管道聚合是一种可以对其他聚合结果进行二次处理的聚合方式,可以对其他聚合的结果进行排序、百分位数计算等操作。
注意:参加聚合的字段必须是keyword、日期、数值、布尔类型;
1.1.2 Elasticsearch实现聚合
aggs
是Elasticsearch中聚合(Aggregation)API的一个参数,与query
同级,它可以对查询结果进行统计和分析操作,在进行聚合的时候query
的作用是限定聚合的文档范围。
- 桶聚合
GET /hotel/_search
{
"size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
"aggs": { // 定义聚合
"聚合名称": {
"聚合的类型": {
"field": "聚合字段",
"order": {//排序规则
"_count": "asc"//按数量升序
},
"size": 希望获取的聚合结果数量
}
}
}
}
- 度量聚合
GET /hotel/_search
{
"size": 0,
"aggs": {
"聚合名称": {
"聚合的类型": {
"field": "聚合字段",
"size": 希望获取的聚合结果数量
},
"aggs": { // 是brands聚合的子聚合,也就是分组后对每组分别计算
"聚合名称": {
"stats": { // 聚合类型,这里stats可以计算min、max、avg等
"field": "聚合字段"
}
}
}
}
}
}
1.1.3 RestClient实现聚合
语法格式:
//1.准备Request
SearchRequest request = new SearchRequest("索引库");
//2.准备DSL
//设置size为0,结果中不包含文档,只包含聚合结果
request.source().size(0);
//聚合
request.source().aggregation(AggregationBuilders
.terms("聚合名")
.field("聚合字段")
.size(希望获取的聚合结果数量)
);
//3.发出请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析聚合结果
Aggregations aggregations = response.getAggregations();
//根据名称获取聚合结果
Terms brandTerms = aggregations.get("聚合名");
//获取桶
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
for (Terms.Bucket bucket:buckets) {
String brandName = bucket.getKeyAsString();
//这里输出的是每个桶名称和数量
System.out.println(brandName + ":" + bucket.getDocCount());
}
1.2 自动补全
elasticsearch中分词器(analyzer)的组成包含三部分:
- character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
- tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
- tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等
1.2.1 安装平均分词器
- 下载
地址:拼音分词器
-
解压并上传至虚拟机Elasticsearch的plugin目录
-
重启Elasticsearch
-
配置分词器
在创建索引库的时候通过setting来配置自定义的analyzer(分词器):
示例:
PUT /test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
}
},
"filter": {
"py": {
"type": "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"
}
}
}
}
注:为了避免搜索到同音字,搜索时不要使用拼音分词器;
1.2.2 Completion Suggester
Completion Suggester是Elasticsearch提供的一种建议(Suggest)功能,它可以根据输入的前缀来自动补全候选项,并且支持中文、英文、数字等各种类型的自动补全。它通常用于实现搜索框自动补全等场景。
Completion Suggester的实现原理是将需要自动补全的字段(例如商品名称)以及对应的候选项(例如具体的商品名称)作为一个单独的文档类型进行存储,并使用特定的数据结构(FST)来加速前缀匹配和候选项查找。当用户输入一个前缀时,Completion Suggester会在FST中查找以该前缀开头的候选项,并返回给用户。
为了提高补全查询的效率,对于文档中字段的类型有一些约束:
-
参与补全查询的字段必须是completion类型。
-
字段的内容一般是用来补全的多个词条形成的数组。
示例:
// 自动补全查询
GET /索引库/_search
{
"suggest": {
"自定义名称": {
"text": "关键字",
"completion": {
"field": "补全字段",
"skip_duplicates": true, // 跳过重复的数据
"size": 获取结果的数量
}
}
}
}
RestAPI:
//1.准备Request
SearchRequest request = new SearchRequest("索引库名");
//2.准备DSL
request.source().suggest(new SuggestBuilder().addSuggestion(
"suggest名称",
SuggestBuilders.completionSuggestion("关键字")
.prefix("补全字段")
.skipDuplicates(true) // 跳过重复的数据
.size(获取结果的数量)
));
//3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.解析结果
Suggest suggest = response.getSuggest();
//根据补全查询名称获取查询结果
CompletionSuggestion suggestions = suggest.getSuggestion("suggest名称");
//获取options
List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
//遍历
for (CompletionSuggestion.Entry.Option option:options) {
//text就是获取到的数据
String text = option.getText().toString();
}
1.3 数据同步
1.3.1 什么是数据同步,为什么要实现数据同步
什么是数据同步?
数据同步是指将一个系统的数据更新到另一个系统中,以保持两个系统的数据一致性。在实际应用中,由于不同系统之间的数据结构和存储方式可能不同,因此数据同步通常需要进行数据转换、格式化、映射等操作,以确保数据可以被正确地导入到目标系统中。
为什么要实现数据同步?(以MySQL为例)文章来源:https://www.toymoban.com/news/detail-463736.html
Elasticsearch和MySQL是两个不同的数据库,Elasticsearch是文档型数据库,而MySQL是关系型数据库,两者的数据虽然可以相互转换,但两者内部不存在双向绑定的关系。因此,在每次进行数据通信时,需要将MySQL中的关系型数据转换为Elasticsearch中的文档型数据,保证数据的一致性和完整性,实现数据同步。文章来源地址https://www.toymoban.com/news/detail-463736.html
1.3.2 使用MQ队列实现数据同步
- 添加依赖
<!--amqp-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 添加mq配置
spring:
rabbitmq:
host: ip地址
port: 5672
username: 用户名
password: 密码
virtual-host: 虚拟主机
- 添加MQ配置类
@Configuration
public class MqConfig {
//定义交换机
@Bean
public TopicExchange topicExchange(){
return new TopicExchange(交换机名称,true,false);
}
//定义队列
@Bean
public Queue insertQueue(){
return new Queue(插入更新队列名称,true);
}
@Bean
public Queue deleteQueue(){
return new Queue(删除队列名称,true);
}
//绑定关系
@Bean
public Binding insertQueueBinding(){
return BindingBuilder.bind().to(topicExchange()).with(插入更新KEY);
}
@Bean
public Binding deleteQueueBinding(){
return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(删除KEY);
}
}
- 在mysql数据库服务的业务层添加代码
//key值指的是插入更新KEY、删除KEY
//传入的数据可以是对应主键也可以是实体类
rabbitTemplate.convertAndSend(交换机名称,key值,传入数据);
- 在Elasticsearch服务添加监听
@Component
public class Listener {
@Autowired
private IService service;
/**
* 监听酒店新增或修改的业务
* @param id 酒店id
*/
@RabbitListener(queues = 插入更新队列名称)
public void listenInsertOrUpdate(Long id){
service.insertById(id);
}
/**
* 监听删除的业务
* @param id 酒店id
*/
@RabbitListener(queues = 删除队列名称)
public void listenDelete(Long id){
service.deleteById(id);
}
}
到了这里,关于Elasticsearch的扩展的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!