ElasticSearch保姆级入门教程

x33g5p2x  于2021-11-15 转载在 ElasticSearch  
字(17.7k)|赞(0)|评价(0)|浏览(683)

一、初识ElasticSearch

  • elasticsearch是elastic stack的核心,负责存储、搜索、分析数据

  • Lucene是一个Java语言的搜索引擎类库,是Apache公司的顶级项目。
  • Lucene官方
  1. Lucene优势:

  2. 易扩展

  3. 高性能(基于倒排索引)

  • mysql和elasticsearch相关概念

  • MySQL擅长:事务类的操作,可以确保数据的安全和一致性
  • Elasticsearch擅长:海量数据的搜索、分析、计算

二、安装Elasticsearch

2.1 创建网络

  • 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:
  1. docker network create es-net #创建网络

2.2 下载资源/加载镜像

ElasticSearch官网并且下载kibana依赖包
或者
采用镜像tar包

  1. docker load -i tar

2.3 运行

  • 运行docker命令,部署单点es
  1. docker run -d \
  2. --name es \
  3. -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  4. -e "discovery.type=single-node" \
  5. -v es-data:/usr/share/elasticsearch/data \
  6. -v es-plugins:/usr/share/elasticsearch/plugins \
  7. --privileged \
  8. --network es-net \
  9. -p 9200:9200 \
  10. -p 9300:9300 \
  11. elasticsearch:7.12.1
  • -e "cluster.name=es-docker-cluster":设置集群名称
  • -e "http.host=0.0.0.0":监听的地址,可以外网访问
  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小
  • -e "discovery.type=single-node":非集群模式
  • -v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录
  • -v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定es的日志目录
  • -v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定es的插件目录
  • --privileged:授予逻辑卷访问权
  • --network es-net :加入一个名为es-net的网络中
  • -p 9200:9200:端口映射配置

在浏览器输入 ip:9200 即可看见一下消息说明 elasticsearch安装成功

2.4 部署kibana

  • kibana可以给我们提供一个elasticsearch的可视化界面,便于我们学习。

2.4.1 部署

  1. docker run -d \
  2. --name kibana \
  3. -e ELASTICSEARCH_HOSTS=http://es:9200 \
  4. --network=es-net \
  5. -p 5601:5601 \
  6. kibana:7.12.1
  • 部署完成后 浏览器访问 ip:5601
  • --network es-net :加入一个名为es-net的网络中,与elasticsearch在同一个网络中
  • -e ELASTICSEARCH_HOSTS=http://es:9200":设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch
  • -p 5601:5601:端口映射配置

2.5 安装IK分词器

  • IK分词器下载
  • 下载好后我们把IK分词器的资源放入到我们docker挂载的数据卷中
  • 查看es的数据卷挂载目录
  1. docker volume inspect es-plugins
  • 显示结果
  1. [
  2. {
  3. "CreatedAt": "2022-05-06T10:06:34+08:00",
  4. "Driver": "local",
  5. "Labels": null,
  6. "Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",
  7. "Name": "es-plugins",
  8. "Options": null,
  9. "Scope": "local"
  10. }
  11. ]
  • 把IK分词器的解压文件放入/var/lib/docker/volumes/es-plugins/_data中即可
  • 重启es
  1. docker restart es

2.5.1 IK分词器的两种模式

  • ik_smart:最少切分
  • ik_max_word:最细切分

2.5.2 IK分词器的扩展词词典

  • 随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“绝绝子” 等。我们需要把一些新词扩展到IK分词器中
  • 打开IK分词器config目录

  • 在IKAnalyzer.cfg.xml配置文件内容添加:

  • 在这个目录下新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改,然后输入新词保存即可。
  • 重启elasticsearch
  1. docker restart es

2.5.2 停用词词典

  • 与扩展词词典一样、config目录下默认有stopword.dic文件打开后把我们想停用的词输入 保存即可。
  • 重启elasticsearch
  1. docker restart es

2.6 Mapping索引库操作

  • 索引库类似于数据库中的建表操作

2.6.1 常见mapping属性

type数据类型
type数据类型
index是否索引
analyzer分词器
properties子字段
type常见有哪些
字符串text,keyword
数字long/integet/short/byte/double/float
布尔boolean
日期date
对象object

2.6.2 创建索引库

  • ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下:
  1. PUT /索引库名称
  2. {
  3. "mappings": {
  4. "properties": {
  5. "字段名":{
  6. "type": "text",
  7. "analyzer": "ik_smart"
  8. },
  9. "字段名2":{
  10. "type": "keyword",
  11. "index": "false"
  12. },
  13. "字段名3":{
  14. "properties": {
  15. "子字段": {
  16. "type": "keyword"
  17. }
  18. }
  19. },
  20. // ...略
  21. }
  22. }
  23. }

2.6.3 查看、删除、更新索引库

  • 查询索引库
  1. PUT /索引库名
  • 删除索引库
  1. DELETE /索引库名
  • 更新索引库
  1. #更新索引库 只能添加新字段,不能修改已有字段
  2. PUT /索引库名/_mapping
  3. {
  4. "properties": {
  5. "新字段名":{
  6. "type": "integer"
  7. }
  8. }
  9. }

2.7 文档操作

  • 查看文档:GET /索引库名/_doc/文档id
  • 添加文档
  1. POST /索引库名/_doc/文档id
  2. {
  3. "字段1": "值1",
  4. "字段2": "值2",
  5. "字段3": {
  6. "子属性1": "值3",
  7. "子属性2": "值4"
  8. },
  9. // ...
  10. }
  • 删除文档:DELETE /索引库名/_doc/文档id
  • 更新文档
    1.全量修改,会删除旧文档,添加新文档
  1. PUT /索引库名/_doc/文档id
  2. {
  3. "字段1": "值1",
  4. "字段2": "值2",
  5. // ... 略
  6. }

2.增量修改,修改指定字段值

  1. POST /索引库名/_update/文档id
  2. {
  3. "doc": {
  4. "字段名": "新的值",
  5. }
  6. }

2.8 RestClient操作客户端

2.8.1 通过java代码实现对elasticsearch的操作

  • pom依赖
  1. 引入esRestHighLevelClient依赖:
  2. <dependency>
  3. <groupId>org.elasticsearch.client</groupId>
  4. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  5. </dependency>
  • 创建测试类初始化客户端
  1. @BeforeEach//先运行这个方法进行绑定客户端
  2. void setUp(){
  3. this.client=new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.36.129:9200")));
  4. }

2.8.2 RestClient索引库的增删查

  • 公共部分
  1. private RestHighLevelClient client;
  • 创建索引库
  1. //创建索引库
  2. @Test
  3. void t2() throws IOException {
  4. //1. 创建索引库对象
  5. CreateIndexRequest request = new CreateIndexRequest("hotel");
  6. //2. 请求参数,HotelIndex.INDEX_MAPPING是创建索引库的字符串模板,内容是创建索引库的DSL语句
  7. request.source(HotelIndex.INDEX_MAPPING, XContentType.JSON);
  8. //3. 发送请求
  9. client.indices().create(request, RequestOptions.DEFAULT);
  10. }
  • 删除索引库
  1. //删除索引库
  2. @Test
  3. void t3() throws IOException {
  4. //1.创建删除索引库请求对象
  5. DeleteIndexRequest request = new DeleteIndexRequest("hotel");
  6. //发送删除请求
  7. client.indices().delete(request,RequestOptions.DEFAULT);
  8. }
  • 查询索引库
  1. //查询索引库是否存在
  2. @Test
  3. void t4() throws IOException {
  4. //1.创建查询索引库请求对象
  5. GetIndexRequest request = new GetIndexRequest("hotel");
  6. //发送请求
  7. boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
  8. System.out.println(exists==true?"索引库已经存在":"索引库不存在");
  9. }

2.8.3 RestClient文档的增删改查

  • 新增文档
  1. //新增文档
  2. @Test
  3. void t5() throws IOException {
  4. Hotel data = hotelService.getById(61083L);
  5. HotelDoc hotelDoc = new HotelDoc(data);
  6. //1.准备Request对象
  7. IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
  8. //2.准备JSON文档(索引库中的数据)
  9. request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
  10. //3.发送请求
  11. client.index(request,RequestOptions.DEFAULT);
  12. }
  • 删除文档
  1. //删除文档
  2. @Test
  3. void t8() throws Exception{
  4. DeleteRequest request = new DeleteRequest("hotel","61083");
  5. client.delete(request,RequestOptions.DEFAULT);
  6. }
  • ````修改文档```
  1. //更新文档
  2. @Test
  3. void t7() throws Exception{
  4. //1.准备Request
  5. UpdateRequest request = new UpdateRequest("hotel","61083");
  6. //2.准备请求参数
  7. request.doc(
  8. //部分更新 key value的形式
  9. "price","666",
  10. "name","李四"
  11. );
  12. client.update(request,RequestOptions.DEFAULT);
  13. }
  • 查询文档
  1. //查询文档
  2. @Test
  3. void t6() throws IOException {
  4. //1.查询请求对象
  5. GetRequest request = new GetRequest("hotel","61083");
  6. //2.发送请求,得到文档响应数据
  7. GetResponse documentFields = client.get(request, RequestOptions.DEFAULT);
  8. //3.拿到文档数据中的source
  9. String data = documentFields.getSourceAsString();
  10. //4.将source反序列化为对象
  11. HotelDoc hotelDoc = JSON.parseObject(data, HotelDoc.class);
  12. System.out.println("文档数据===>"+hotelDoc);
  13. }
  • 批量新增
  1. //批量新增
  2. @Test
  3. void t9() throws Exception{
  4. BulkRequest request = new BulkRequest();
  5. List<Hotel> lists = hotelService.list();
  6. for (Hotel list : lists) {
  7. HotelDoc hotelDoc = new HotelDoc(list);
  8. request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));
  9. }
  10. client.bulk(request,RequestOptions.DEFAULT);
  11. }

2.9 DSL查询语法

  • 查询所有:查询出所有数据,一般测试用。例如:match_all
  • 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:match_query 和 multi_match_query
  • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:ids range term
  • 地理(geo)查询:根据经纬度查询。例如:geo_distance 和 geo_bounding_box

2.9.1 DSL Query基本语法

  1. GET /indexName/_search
  2. {
  3. "query": {
  4. "查询类型": {
  5. "查询条件": "条件值"
  6. }
  7. }
  8. }
  9. 例:
  10. GET /hotel/_search
  11. {
  12. "query": {
  13. "match_all": {}
  14. }
  15. }

2.9.2 DSL全文检索查询

  • 全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索
  1. GET /索引库/_search
  2. {
  3. "query": {
  4. "match": {
  5. "FIELD": "TEXT"
  6. }
  7. }
  8. }
  9. 例:
  10. GET /hotel/_search
  11. {
  12. "query": {
  13. "match": {
  14. "all": "外滩五钻"
  15. }
  16. }
  17. }
  • 查询多个字段
  1. GET /索引库/_search
  2. {
  3. "query": {
  4. "multi_match": {
  5. "query": "TEXT",
  6. "fields": ["FIELD1", " FIELD12"]
  7. }
  8. }
  9. }
  • match:根据一个字段查询
  • multi_match:根据多个字段查询,参与查询字段越多,查询性能越差

2.9.3 DSL精确查询

  • term精确查询
  1. #精确查询
  2. GET /hotel/_search
  3. {
  4. "query": {
  5. "term": {
  6. "FIELD": {
  7. "value": "VALUE"
  8. }
  9. }
  10. }
  11. }
  12. 例:
  13. #精确查询
  14. GET /hotel/_search
  15. {
  16. "query": {
  17. "term": {
  18. "city": {
  19. "value": "上海"
  20. }
  21. }
  22. }
  23. }
  • range范围查询
  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "range": {
  5. "FILED": {
  6. "gte": value,
  7. "lte": value
  8. }
  9. }
  10. }
  11. }
  12. 例:
  13. GET /hotel/_search
  14. {
  15. "query": {
  16. "range": {
  17. "price": {
  18. "gte": 100,
  19. "lte": 200
  20. }
  21. }
  22. }
  23. }

2.9.4 DSL地理位置查询

  • 根据geo-distance位置范围查询
  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "geo_distance":{
  5. # distance: 可以设定查询距离
  6. "distance":"2km",
  7. # location:当前地址位置,此字段必须是 geo_point类型
  8. "location":"31.21,121.5"
  9. }
  10. }
  11. }

2.9.5 Function Score Query

  • 当我们对第一次的搜索排序进行人工干预时,就需要用到Function Score 函数 可以自定义结果,让排序的结果变成我们想要的解构。 比如进行排名,一些酒店掏钱了,那么我们就可以通过Function Score进行加权算分 让我们想要的结果变成真
  • 在原来查询的条件下进行加权算分
  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "function_score": {
  5. #第一次进行条件查询匹配
  6. "query": {"match": {
  7. "all": "外滩"
  8. }},
  9. #算分函数
  10. "functions": [
  11. {
  12. "filter": {
  13. "term": {
  14. "brand": "如家"
  15. }
  16. },
  17. #算分权重为 10
  18. "weight": 10
  19. }
  20. ],
  21. #加权模式 boost_mode:乘法
  22. "boost_mode": "multiply"
  23. }
  24. }
  25. }

2.9.6 Boolean Query

  • 布尔查询是一个或多个查询子句的组合。子查询的组合方式有:
  1. must:必须匹配每个子查询,类似“与”
  2. should:选择性匹配子查询,类似“或”
  3. must_not:必须不匹配,不参与算分,类似“非”
  4. filter:必须匹配,不参与算分
  • 演示
  • 需求:搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店。
  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. {
  7. "match": {
  8. "name": "如家"
  9. }
  10. }
  11. ],
  12. "must_not": [
  13. {
  14. "range": {
  15. "FIELD": {
  16. "lte": 500
  17. }
  18. }
  19. }
  20. ],
  21. "filter": [
  22. {
  23. "geo_distance": {
  24. "distance": "10km",
  25. "location": {
  26. "lat": 31.21,
  27. "lon": 121.5
  28. }
  29. }
  30. }
  31. ]
  32. }
  33. }
  34. }

2.10 搜索结果处理

2.10.1 排序 sort

  • 语法
  1. GET /索引库名称/_search
  2. {
  3. "query": {
  4. "match_all": {}
  5. },
  6. "sort": [
  7. {
  8. "FIELD": "desc" // 排序字段和排序方式ASC、DESC
  9. }
  10. ]
  11. }

2.10.2 分页 from size

  • 语法
  1. GET /索引库名称/_search
  2. {
  3. "query": {
  4. "match_all": {}
  5. },
  6. "from": 从第几条数据开始查询, // 分页开始的位置,默认为0
  7. "size": 显示查询几条, // 期望获取的文档总数
  8. "sort": [
  9. {"按照哪个字段排序": "asc"}
  10. ]
  11. }

2.10.3 高亮处理

  • 语法:高亮处理,默认情况搜索字段必须与高亮字段保持一致
  1. GET /索引库名称/_search
  2. {
  3. "query": {
  4. "match": {
  5. "FIELD": "TEXT"
  6. }
  7. },
  8. "highlight": {
  9. "fields": { // 指定要高亮的字段
  10. "FIELD": {
  11. "require_field_match":"false" #搜索字段与高亮字段匹配为false
  12. "pre_tags": "<em>", // 用来标记高亮字段的前置标签
  13. "post_tags": "</em>" // 用来标记高亮字段的后置标签
  14. }
  15. }
  16. }
  17. }

2.10 RestClient 查询文档

2.10.1 快速入门查询文档

  1. @Test
  2. void t1() throws IOException {
  3. //1.创建搜索请求对象
  4. SearchRequest request = new SearchRequest("索引库名称");
  5. //2.准备DSL参数
  6. request.source().query(QueryBuilders.matchAllQuery()).from(0).size(10);
  7. //3.发送请求 得到数据集合
  8. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  9. //4.解析响应数据
  10. SearchHits hits = search.getHits();
  11. //拿到数据集合中Hits数据的条数
  12. long value = hits.getTotalHits().value;
  13. //拿到数据集合
  14. SearchHit[] hits1 = hits.getHits();
  15. //5.遍历数据
  16. for (SearchHit hit : hits1) {
  17. System.out.println(hit.getSourceAsString());
  18. }
  19. }

2.10.2 全文检索 单字段查询

  1. @Test
  2. void t2() throws IOException {
  3. //1.创建搜索请求对象
  4. SearchRequest request = new SearchRequest("索引库名");
  5. //2.准备DSL参数
  6. request.source().query(QueryBuilders.matchQuery("字段","值")).from(0).size(10);
  7. //3.发送请求 得到数据集合
  8. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  9. //4.解析响应数据
  10. SearchHits hits = search.getHits();
  11. //拿到数据集合中Hits数据的条数
  12. long value = hits.getTotalHits().value;
  13. //拿到数据集合
  14. SearchHit[] hits1 = hits.getHits();
  15. //5.遍历数据
  16. for (SearchHit hit : hits1) {
  17. System.out.println(hit.getSourceAsString());
  18. }
  19. }

2.10.3 全文检索 多字段查询

  1. @Test
  2. void t3() throws IOException {
  3. //1.创建搜索请求对象
  4. SearchRequest request = new SearchRequest("hotel");
  5. //2.准备DSL参数
  6. request.source().query(QueryBuilders.multiMatchQuery("查询的值","查询字段","查询字段",...)).from(0).size(10);
  7. //3.发送请求 得到数据集合
  8. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  9. //4.解析响应数据
  10. SearchHits hits = search.getHits();
  11. //拿到数据集合中Hits数据的条数
  12. long value = hits.getTotalHits().value;
  13. //拿到数据集合
  14. SearchHit[] hits1 = hits.getHits();
  15. //5.遍历数据
  16. for (SearchHit hit : hits1) {
  17. System.out.println(hit.getSourceAsString());
  18. }
  19. }

2.10.4 bool多条件查询

  1. @Test
  2. void t4() throws IOException {
  3. //1.创建搜索请求对象
  4. SearchRequest request = new SearchRequest("hotel");
  5. //2.准备DSL参数
  6. BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
  7. //精确查询
  8. boolQueryBuilder.must(QueryBuilders.termQuery("字段名","查询的值"));
  9. //范围查询
  10. boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(300));
  11. request.source().query(boolQueryBuilder);
  12. //3.发送请求 得到数据集合
  13. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  14. //4.解析响应数据
  15. SearchHits hits = search.getHits();
  16. //拿到数据集合中Hits数据的条数
  17. long value = hits.getTotalHits().value;
  18. //拿到数据集合
  19. SearchHit[] hits1 = hits.getHits();
  20. //5.遍历数据
  21. for (SearchHit hit : hits1) {
  22. System.out.println(hit.getSourceAsString());
  23. }
  24. }

2.10.5 排序

  1. @Test
  2. void t5() throws Exception{
  3. //1.创建搜索请求对象
  4. SearchRequest request = new SearchRequest("索引库名");
  5. //2.准备DSL参数
  6. request.source().sort("price", SortOrder.ASC).from(0).size(5);
  7. //3.发送请求 得到数据集合
  8. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  9. handleResponse(search);
  10. }

2.10.6 高亮处理

  1. @Test
  2. void t6()throws Exception{
  3. //1.创建搜索请求对象
  4. SearchRequest searchRequest = new SearchRequest("hotel");
  5. //2.准备DSL参数
  6. searchRequest.source().query(QueryBuilders.matchQuery("查询字段","value值"));
  7. searchRequest.source().highlighter(new HighlightBuilder().field("高亮的字段").requireFieldMatch(false));
  8. //3.发送请求 得到数据集合
  9. SearchResponse search = client.search(searchRequest,RequestOptions.DEFAULT);
  10. //4.解析响应数据
  11. SearchHits hits = search.getHits();
  12. //拿到数据集合中Hits数据的条数
  13. long value = hits.getTotalHits().value;
  14. //拿到数据集合
  15. SearchHit[] hits1 = hits.getHits();
  16. //5.遍历数据
  17. for (SearchHit hit : hits1) {
  18. //拿到高亮字段
  19. Map<String, HighlightField> highlightFields = hit.getHighlightFields();
  20. if (!CollectionUtils.isEmpty(highlightFields)) {
  21. //拿到高亮字段的key
  22. HighlightField name = highlightFields.get("name");
  23. if(name!=null){
  24. String highlightName = name.getFragments()[0].string();
  25. System.out.println(highlightName);
  26. }
  27. }
  28. }
  29. }

三、数据聚合

  1. 聚合(aggregations):可以实现对文档数据的统计、分析、运算。聚合常见的有三类:

  2. Bucket:对文档数据分组,并统计每组数量

  3. Metric:对文档数据做计算,例如avg

  4. Pipeline:基于其它聚合结果再做聚合

  5. 聚合(aggregations):的字段类型必须是

  6. keyword

  7. 数值

  8. 布尔

  9. 日期

  10. 聚合(aggregations)聚合三要素:聚合名称、聚合类型、聚合字段

3.1 DSL实现Bucket聚合

  1. GET /索引库名/_search
  2. {
  3. "size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
  4. "aggs(固定名称)": { // 定义聚合
  5. "brandAgg(自定义聚合名称)": { //给聚合起个名字
  6. "terms": { // 聚合的类型,按照品牌值聚合,所以选择term
  7. "field": "参与聚合的字段名", // 参与聚合的字段
  8. "order": {
  9. "排序字段": "asc" // 按照升序排列
  10. },
  11. "size": 20 // 希望获取的聚合结果数量
  12. }
  13. }
  14. }
  15. }

3.2 Bucket聚合-限定聚合范围

  1. GET /索引库名/_search
  2. {
  3. #先进行查询,然后再将查询后的数据进行聚合
  4. "query": {
  5. "match": {
  6. "name": "酒店"
  7. }
  8. },
  9. "size": 0,
  10. "aggs": {
  11. "brandAgg": {
  12. "terms": {
  13. "field": "brand",
  14. "size": 20
  15. }
  16. }
  17. }
  18. }
聚合可配置的属性
size指定聚合结果数量
order指定聚合结果排序方式
field指定聚合字段

3.3 DSL实现Metric聚合

  • 可以获取min、max、avg等值
  1. GET /索引库名/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "brandAgg(自定义聚合名)": {
  6. "terms(添加聚合类型)": {
  7. "field": "字段",
  8. "size": 20
  9. },
  10. "aggs": { // 是上面聚合的子聚合,也就是分组后对每组分别计算
  11. "score_stats": { // 聚合名称
  12. "stats": { // 聚合类型,这里stats可以计算min、max、avg等
  13. "field": "score" // 聚合字段,这里是score
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }

3.4 RstClient实现聚合

  1. @Test
  2. void t7()throws Exception{
  3. //1.准备搜索请求对象
  4. SearchRequest request = new SearchRequest("hotel");
  5. //2.准备DSL
  6. request.source().size(0);
  7. request.source().aggregation(AggregationBuilders
  8. //准备聚合:值为自定义聚合名称
  9. .terms("brandAgg")
  10. //聚合的字段
  11. .field("brand")
  12. //展示几条
  13. .size(10));
  14. //3.发出请求得到解析对象
  15. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  16. //4.拿到聚合对象
  17. Aggregations aggregations = search.getAggregations();
  18. //5.通过聚合对象.get(自定义聚合名称) 拿到具体的聚合类型的结果 对象
  19. Terms brandAgg = aggregations.get("brandAgg");
  20. //6.拿到桶Buckets
  21. List<? extends Terms.Bucket> buckets = brandAgg.getBuckets();
  22. //7.遍历每一条数据
  23. for (Terms.Bucket bucket : buckets) {
  24. String key = bucket.getKeyAsString();
  25. System.out.println(key);
  26. }
  27. }

四、安装拼音分词器

  1. 拼音分词器下载地址

  2. 下载与elasticsearch对应版本的拼音分词器包

  3. 解压拼音分词器.zip

  4. 将拼音分词器解压后的文件夹放入elasticsearch数据卷相对应的es-plugin文件夹下

  5. docker insepect es 查看es的数据卷目录

  6. 重启 es

  7. 自定义分词器中过滤器的参数文档:参数文档

  1. PUT /test
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": { // 自定义分词器
  6. "my_analyzer(自定义分词器名称)": { // 分词器名称
  7. "tokenizer": "ik_max_word",
  8. "filter": "py" #对应下面的过滤器名称
  9. }
  10. },
  11. "filter": { // 自定义tokenizer filter
  12. "py": { // 过滤器名称
  13. "type": "pinyin", // 过滤器类型,这里是pinyin
  14. "keep_full_pinyin": false,
  15. "keep_joined_full_pinyin": true,
  16. "keep_original": true,
  17. "limit_first_letter_length": 16,
  18. "remove_duplicated_term": true,
  19. "none_chinese_pinyin_tokenize": false
  20. }
  21. }
  22. }
  23. },
  24. "mappings": {
  25. "properties": {
  26. "name":{
  27. "type": "text",
  28. "analyzer": "my_analyzer", #当我插入文档数据时,会根据自定义分词规则进行过滤
  29. "search_analyzer": "ik_smart" #搜索时使用ik分词器 可以避免搜到同音字
  30. }
  31. }
  32. }
  33. }

4.1 自动补全

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

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

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

  4. 创建语法:

  1. // 创建索引库
  2. PUT test
  3. {
  4. "mappings": {
  5. "properties": {
  6. "title":{
  7. "type": "completion"
  8. }
  9. }
  10. }
  11. }
  12. // 示例数据
  13. POST test/_doc
  14. {
  15. "title": ["Sony","switch","LOL", "WH-1000XM3"]
  16. }
  17. POST test/_doc
  18. {
  19. "title": ["switch", "WH-1000XM4"]
  20. }
  • 查询语法:
  1. // 自动补全查询
  2. GET /test2/_search
  3. {
  4. "suggest": {
  5. "title_suggest": {
  6. "text": "s", // 关键字
  7. "completion": {
  8. "field": "title", // 补全查询的字段
  9. "skip_duplicates": true, // 跳过重复的
  10. "size": 10 // 获取前10条结果
  11. }
  12. }
  13. }
  14. }

4.2 RestClient实现自动补全

  1. @Test
  2. void t8()throws Exception{
  3. //1.准备搜索请求对象
  4. SearchRequest request = new SearchRequest("test2");
  5. //2.准备DSL语句
  6. request.source().suggest(new SuggestBuilder().addSuggestion(
  7. // 自定义suggestion名称
  8. "mySuggest",
  9. //补全功能搜索的字段
  10. SuggestBuilders.completionSuggestion("title")
  11. //跳过重复的数据
  12. .skipDuplicates(true)
  13. //根据前缀来搜索补全的值,这里的值将来会通过前端传过来
  14. .prefix("s")
  15. //显示几条数据
  16. .size(10)));
  17. //3.发送请求得到数据结果
  18. SearchResponse search = client.search(request, RequestOptions.DEFAULT);
  19. //4.拿到suggest所有数据
  20. Suggest suggest = search.getSuggest();
  21. //4.1 拿到真正的suggestion补全数据的json串儿
  22. Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> mySuggest = suggest.getSuggestion("mySuggest");
  23. //5.遍历补全数据json串儿
  24. for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> options : mySuggest) {
  25. //拿到自动补全数据
  26. String data = options.getText().string();
  27. System.out.println(data);
  28. }
  29. System.out.println(search);
  30. }

总结

提示:学习视频来自B站

相关文章

最新文章

更多