SpringCloud(十)——ElasticSearch简单了解(三)数据聚合和自动补全

news2024/11/27 1:38:56

文章目录

  • 1. 数据聚合
    • 1.1 聚合介绍
    • 1.2 Bucket 聚合
    • 1.3 Metrics 聚合
    • 1.4 使用 RestClient 进行聚合
  • 2. 自动补全
    • 2.1 安装补全包
    • 2.2 自定义分词器
    • 2.3 自动补全查询
    • 2.4 拼音自动补全查询
    • 2.5 RestClient 实现自动补全
      • 2.5.1 建立索引
      • 2.5.2 修改数据定义
      • 2.5.3 补全查询
      • 2.5.4 解析结果

1. 数据聚合

1.1 聚合介绍

聚合(aggregations)可以实现对文档数据的统计、分析、运算。

聚合常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组
    • TermAggregation:按照文档字段值分组
    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等
    • Avg:求平均值
    • Max:求最大值
    • Min:求最小值
    • Stats:同时求max、min、avg、sum等
  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合

参与聚合的字段为以下字段:

  • keyword
  • 数值
  • 日期
  • 布尔

注意,不能是 text 字段

1.2 Bucket 聚合

这里假如我们需要对不同品牌的酒店进行聚合人,那么我们就可以使用桶聚合,桶聚合的例子如下:

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

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

如果我们需要在一些查询的条件下进行聚合,比如我们只对200元一下的酒店文档进行聚合,那么聚合条件如下:

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

1.3 Metrics 聚合

如果我们需要按照每个品牌的用户的评分的最大值、最小值、平均值等进行排序,那么这就需要用到 Metrics 聚合了,我们使用 stats 查看所有的聚合属性,该聚合的实现如下:

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

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

如果我们想要对按照聚合的平均值进行排序,那么DSL语句如下:

GET /hotel/_search
{
  "size": 0, 
  "aggs": {
    "brandAgg": { 
      "terms": { 
        "field": "brand", 
        "size": 20,
        "order": {
          "scoreAgg.avg": "asc"  //按照平均值进行排序
        }
      },
      "aggs": { 
        "scoreAgg": { 
          "stats": {
            "field": "score" 
          }
        }
      }
    }
  }
}

1.4 使用 RestClient 进行聚合

我们以各个酒店的品牌聚合为例,其中java语句与DSL语句的一一对应关系如下:
在这里插入图片描述
使用RestClient进行聚合的代码如下:

    @Test
    void testAgg() throws IOException {
        //1.准备Request对象
        SearchRequest request = new SearchRequest("hotel");
        //2.准备size
        request.source().size(0);
        //3.进行聚合
        request.source().aggregation(AggregationBuilders
                .terms("brandAgg")
                .field("brand")
                .size(10));
        //4.发送请求
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        //解析聚合结果
        Aggregations aggregations = response.getAggregations();
        //根据名称获取聚合结果
        Terms brandterms = aggregations.get("brandAgg");
        //获取桶
        List<? extends Terms.Bucket> buckets = brandterms.getBuckets();
        // 遍历
        for (Terms.Bucket bucket: buckets){
            // 获取key,也就是品牌信息
            String brandName = bucket.getKeyAsString();
            System.out.println(brandName);
        }
    }

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

2. 自动补全

2.1 安装补全包

自动补全我们需要实现的效果是当我们输入拼音的时候,就有一些产品的提示,这种情况下就需要我们对拼音有一定的处理,所以我们在这里下载一个拼音分词器,下载的方式与上面下载 IK 分词器相差不大,都是首先进入容器内部,然后在容器插件目录下进行安装,

# 进入容器内部
docker exec -it es /bin/bash

# 在线下载并安装
/usr/share/elasticsearch/bin/elasticsearch-plugin install --batch \
    https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v7.12.1/elasticsearch-analysis-pinyin-7.12.1.zip

#退出
exit

#重启容器
docker restart es

重启后,使用拼音分词器试试效果,如下:

POST /_analyze
{
  "text": ["你干嘛哎哟"],
  "analyzer": "pinyin"
}

在这里插入图片描述

2.2 自定义分词器

从上面的例子我们可以看出,拼音分词器是将一句话的每个字都进行分开,并且首字母的拼音全部都在一起的,这肯定不是我们想要看到的,我们想要的是对句子进行分词后还能根据词语来创建拼音的索引,所以,这就需要我们自定义分词器了。

首先,我们需要了解分词器的工作步骤,elasticsearch中分词器(analyzer)的组成包含三部分:

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

自定义分词器的DSL代码如下:

PUT /test   //针对的是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"
      }
    }
  }
}

进行测试如下:

POST /test/_doc/1
{
  "id": 1,
  "name": "下雪"
}

POST /test/_doc/2
{
  "id": 2,
  "name": "瞎学"
}

GET /test/_search
{
  "query": {
    "match": {
      "name": "武汉在下雪嘛"
    }
  }
}

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

2.3 自动补全查询

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

  • 参与补全查询的字段必须是 completion 类型。
  • 字段的内容一般是用来补全的多个词条形成的数组。

首先我们先建立索引库以及索引库约束,

PUT test2
{
  "mappings": {
    "properties": {
      "title":{
        "type": "completion"
      }
    }
  }
}

test2 索引库中添加数据

// 示例数据
POST test2/_doc
{
  "title": ["Sony", "WH-1000XM3"]
}

POST test2/_doc
{
  "title": ["SK-II", "PITERA"]
}

POST test2/_doc
{
  "title": ["Nintendo", "switch"]
}

进行自动补全查询,我们给出一个关键字 s ,对其进行补全查询如下,

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

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

2.4 拼音自动补全查询

如果想要使用拼音自动补全进行查询,那么就必须自定义分词器了,自定义分词器如下:

PUT /test3
{
  "settings": {
    "analysis": {
      "analyzer": { 
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        },
        "completion_analyzer": {
          "tokenizer": "keyword",
          "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": {
      "title": {
        "type": "completion",
        "analyzer": "completion_analyzer"
      }
    }
  }
}

然后创建一个索引库,并添加一些文档,如下:

PUT /test3
{
  "mappings": {
    "properties": {
      "title":{
        "type": "completion"
      }
    }
  }
}

POST test3/_doc
{
  "title": ["上子", "熵字", "下雪"]
}

POST test3/_doc
{
  "title": ["赏金", "秀色", "猎人"]
}

然后就可以根据首字母缩写或者拼音来进行查询了,DSL代码如下:

GET /test3/_search
{
  "suggest": {
    "suggestions": {
      "text": "xx",
      "completion": {
        "field": "title",
        "skip_duplicates": true,
        "size": 10
      }
    }
  }
}

如上,我们输入的是下雪的拼音缩写 xx ,进行查询时,结果如下:
在这里插入图片描述
当然,也可以对拼音进行按顺序的补全查询。

2.5 RestClient 实现自动补全

2.5.1 建立索引

要实现对索引库的内容进行自动补全,我们需要重新创建索引库,我们的索引库需要多出一个 completion 字段的类型,所以删除原有的索引库后创建新的索引库如下:

DELETE /hotel

PUT /hotel
{
  "settings": {
    "analysis": {
      "analyzer": { 
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "py"
        },
        "completion_analyzer": {
          "tokenizer": "keyword",
          "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": {
      "id": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_max_word",
        "copy_to": "all"
      },
      "address": {
        "type": "keyword",
        "index": false
      },
      "price": {
        "type": "integer"
      },
      "score": {
        "type": "integer"
      },
      "brand": {
        "type": "keyword",
        "copy_to": "all"
      },
      "city": {
        "type": "keyword"
      },
      "starName": {
        "type": "keyword"
      },
      "bussiness": {
        "type": "keyword",
        "copy_to": "all"
      },
      "location": {
        "type": "geo_point"
      },
      "pic": {
        "type": "keyword",
        "index": false
      },
      "all": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "suggestion": {
        "type": "completion",
        "analyzer": "completion_analyzer"
      }
    }
  }
}

2.5.2 修改数据定义

除此之外,还需要将 Hotel 的定义进行修改,因为自动补全的字段不止一个字段,所以我们使用列表类型,定义如下:

@Data
@NoArgsConstructor
@ToString
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    private List<String> suggestion;

    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
        this.suggestion = Arrays.asList(this.brand, this.business);
    }
}

以上定义就是将 brandbusiness 都进行补全的数据结构定义。

之后再按照之前的批量添加将数据库中的数据进行批量新增即可。

2.5.3 补全查询

以下是RestClient与DSL语句的一一对应关系,
在这里插入图片描述
补全查询的语句如下:

    @Test
    void testSuggest() throws IOException{
        //1. 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2. 准备DSL
        request.source().suggest(new SuggestBuilder().addSuggestion(
                "suggestions",
                SuggestBuilders.completionSuggestion("suggestion")
                        .prefix("hu")
                        .skipDuplicates(true)
                        .size(10)
        ));
        //3. 发起请求
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        //4. 输出结果
        System.out.println(response);
    }

2.5.4 解析结果

输出的查询结果是一个包含很多形式的信息的Map类型,我们需要对其进行解析,获取其中想要的结果才行,解析的语句与DSL查询的结果对应关系如下:
在这里插入图片描述
解析的结果的语句如下:

    @Test
    void testSuggest() throws IOException{
        //1. 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2. 准备DSL
        request.source().suggest(new SuggestBuilder().addSuggestion(
                "suggestions",
                SuggestBuilders.completionSuggestion("suggestion")
                        .prefix("hu")
                        .skipDuplicates(true)
                        .size(10)
        ));
        //3. 发起请求
        SearchResponse response = restHighLevelClient.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);
        }
    }

处理后的结果输出如下:
在这里插入图片描述

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

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

相关文章

Web安全——信息收集上篇

Web安全 一、信息收集简介二、信息收集的分类三、常见的方法四、在线whois查询在线网站备案查询 五、查询绿盟的whois信息六、收集子域名1、子域名作用2、常用方式3、域名的类型3.1 A (Address) 记录&#xff1a;3.2 别名(CNAME)记录&#xff1a;3.3 如何检测CNAME记录&#xf…

yolov5自定义模型训练二

前期准备好了用于训练识别是否有火灾的数据集后就可以开始修改yolo相关文件来进行训练 数据集放到yolov5目录里 在data目录下新建yaml文件设置数据集信息如下 在model文件夹下新增新的model文件 开始训练 训练出错 确认后是对训练数据集文件夹里的文件名字有要求&#xff0c;原…

YOLO目标检测——人脸数据集下载分享

目标检测人脸数据集在人脸识别、监控和安防、社交媒体、情感分析、医疗诊断等多个领域都具有广泛的应用潜力。 数据集点击下载&#xff1a;YOLO人脸数据集7000图片.rar

Shell 脚本入门

目录 一、Shell是什么 1.1 我们为什么要学习Shell和使用Shell&#xff1f; 1.2 Shell的分类有哪些&#xff1f; 二、Shell脚本入门知识 2.1 Shell文件命名规范 2.2 Shell解析器 2.3 用Shell 编写hello World 三、Shell的四种变量类型 3.1 系统预定义变量 3.2 自定义变…

移动端几种适配方式

移动端几种适配方式 第一种&#xff1a;rem <meta name"viewport" content"widthdevice-width, initial-scale1.0,,maximum-scale1,user-scalableno">设置窗口不能缩放 一般设备宽度的十分之一 如果这个值是动态计算的需要使用js去设置 根据设备…

【rar密码】使用WinRAR加密的三种方法

如何使用WinRAR加密压缩包&#xff1f;详细介绍WinRAR中的三种加密方法给大家。 方法一&#xff1a;加密 最简单的加密方法&#xff0c;就是在加密文件时输入想要设置的密码&#xff0c;完成加密和压缩了。 方法二&#xff1a;自动加密 普通的加密方式&#xff0c;需要我们加…

1.8.7 练习 冒泡排序 Bubble Sort(提取函数)

C自学精简教程 目录(必读) 1 前驱知识点 for循环语句 、 if语句、函数 、动态内存 2 排序 是将元素按照从小到大的顺序存放的方法。 一开始元素可能并不是按照从小到大的顺序存放的。 这时候我们需要找到需要调整的元素对&#xff0c;并交换这两个元素的值&#xff0c;不…

无涯教程-Android - Absolute Layout函数

Absolute Layout 可让您指定其子级的确切位置(x/y坐标)&#xff0c;绝对布局的灵活性较差且难以维护。 Absolute Layout - 属性 以下是AbsoluteLayout特有的重要属性- Sr.NoAttribute & 描述1 android:id 这是唯一标识布局的ID。 2 android:layout_x 这指定视图的x坐标…

什么是面向对象以及和面向过程的区别

概念 面向对象是一种编程范式&#xff0c;它将现实世界中的事物抽象为对象&#xff0c;并通过对象之间的交互来实现程序的设计和开发。在面向对象编程中&#xff0c;对象是程序的基本单元&#xff0c;具有状态&#xff08;属性&#xff09;和行为&#xff08;方法&#xff09;…

【python爬虫】3.爬虫初体验(BeautifulSoup解析)

文章目录 前言BeautifulSoup是什么BeautifulSoup怎么用解析数据提取数据 对象的变化过程总结 前言 上一关&#xff0c;我们学习了HTML基础知识&#xff0c;知道了HTML是一种用来描述网页的语言&#xff0c;又了解了HTML的基本结构。 认识了HTML中的常见标签和常见属性&#x…

A系统跳转到B系统URl传参与接收

处理url字符串拼接方法new URLSearchParams() A系统 let data { study_id: row.study_id, hospital_id: row.hospital_id, pageType: detail };let params new URLSearchParams(); for (let key in data) {params.append(key, data[key]); } window.open(url ? params.toS…

SpringCloud(十)——ElasticSearch简单了解(二)DSL查询语句及RestClient查询文档

文章目录 1. DSL查询文档1.1 DSL查询分类1.2 全文检索查询1.3 精确查询1.4 地理查询1.5 查询算分1.6 布尔查询1.7 结果排序1.8 分页查询1.9 高亮显示 2. RestClient查询文档2.1 查询全部2.2 其他查询语句2.3 排序和分页2.4 高亮显示 1. DSL查询文档 1.1 DSL查询分类 查询所有…

中央仓库更新失败,IDEA报错repository is non-nexus repo, or does not indexed

某个仓库未被识别为 Nexus 仓库&#xff0c;或者没有被正确地索引。导致引入依赖一直爆红&#xff0c;找不到。只有本地仓库的依赖没报错&#xff0c;因为下载过了&#xff0c;添加新的依赖就需要到远程仓库找就爆红。 解决 去阿里云Maven官网看了一下&#xff0c;发现阿里云…

详解 SpringMVC 中获取请求参数

文章目录 1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、[RequestParam ](/RequestParam )4、[RequestHeader ](/RequestHeader )5、[CookieValue ](/CookieValue )6、通过POJO获取请求参数7、解决获取请求参数的乱码问题总结 在Spring MVC中&#xff0c;获取请…

前后端项目部署上线详细笔记

部署 参考文章&#xff1a;如何部署网站&#xff1f;来比比谁的方法多 - 哔哩哔哩大家好&#xff0c;我是鱼皮&#xff0c;不知道朋友们有没有试着部署过自己开发的网站呢&#xff1f;其实部署网站非常简单&#xff0c;而且有非常多的花样。这篇文章就给大家分享几种主流的前端…

自编码器AE全方位探析:构建、训练、推理与多平台部署

本文深入探讨了自编码器&#xff08;AE&#xff09;的核心概念、类型、应用场景及实战演示。通过理论分析和实践结合&#xff0c;我们详细解释了自动编码器的工作原理和数学基础&#xff0c;并通过具体代码示例展示了从模型构建、训练到多平台推理部署的全过程。 关注TechLead&…

软件测试/测试开发丨Python 学习笔记 之 链表

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/26458 链表与数组的区别 复杂度分析 时间复杂度数组链表插入删除O(n)O(1)随机访问O(1)O(n) 其他角度分析 内存连续&#xff0c;利用CPU的机制&#xff0…

上海炒股开户哪个证券公司好?找谁能开低佣金的账户?

在上海炒股开户选择哪家券商都可以&#xff0c;但是要拿到低佣金的账户就有点难度了。上海&#xff0c;简称“沪&#xff0c;是国务院批复确定的中国国际经济、金融、贸易、航运、科技创新中心&#xff01;正是如此&#xff0c;上海地区的券商公司也是非常之多的&#xff0c;这…

centos安装jdk-8u371-linux-x64.tar.gz包

java -version //查看jdk版本 rpm -qa | grep jdk 删除带有"openjdk"字样的jdk 例: rpm -e --nodeps java-1.7.0-openjdk-1.7.0.141-2.6.10.5.el7.x86_64 下载该版本的jdk(jdk-8u371-linux-x64.tar.gz) (https://www.oracle.com/java/technologies/javase/javase8u2…

AI:04-基于机器学习的蘑菇分类

蘑菇是一类广泛分布的真菌,其中许多种类具有重要的食用和药用价值,但也存在着一些有毒蘑菇。因此,准确地区分可食用和有毒的蘑菇对于保障人们的食品安全和健康至关重要。本研究旨在基于机器学习技术开发一种蘑菇分类系统,以实现对蘑菇的自动分类和识别。通过构建合适的数据…