Java学习Day60:回家!(ElasticStatic)

1.what is ElasticStatic

The Elastic Stack, 包括 Elasticsearch、 Kibana、 Beats 和 Logstash(也称为 ELK Stack)。能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。

Elaticsearch,简称为 ES, ES 是一个开源的高扩展的分布式全文搜索引擎, 是整个 ElasticStack 技术栈的核心。

它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。

一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。

搜索的数据对象是大量的非结构化的文本数据。
文件记录量达到数十万或数百万个甚至更多。
支持大量基于交互式文本的查询。
需求非常灵活的全文搜索查询。
对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎 。

2.ES倒排索引

2.1倒排索引

也称之为反向索引,建立词和文档id之间的对应关系。即把“文档→单词”的形式变为“单词→文档”的形式。

java编程思想 -----> 分词 -----> java、编程、思想、编程思想、java编程思想

先对数据进行分词,得到一个个的词条,然后将词条与文档的对应关系保存起来,最后在对词条本身做索引排序。

如下数据:

idname
1小米手机
2华为手机
3小米电视
4三星电视

ES主要实现数据的搜索,并且ES还不支持事务,因此要保证数据一致性,那么此时还需要使用到数据库。

2.2.ES环境搭建

ElasticSearch本质就是一个搜索引擎,用来实现海量数据的搜索。

Kibana是一个可视化的工具,配合ES进行使用,可以ES中所存储的数据进行可视化的展示(柱状图、饼状图、散点图、折线图...)。并且在Kibana中还提供了开发者工具

# 启动容器(如果不存在容器就创建、存在则修改)
docker compose -f docker-compose.yml up -d

# 删除所有容器
docker compose -f docker-compose.yml down

# 停止所有容器
docker compose -f docker-compose.yml stop

# 启动所有容器
docker compose -f docker-compose.yml start

# 重启所有容器
docker compose -f docker-compose.yml restart

2.3ik分词器

在IK分词器中提供了两种分词器算法:

1、ik_smart:粗粒度分词,分出的词比较少

2、ik_max_word:细粒度分词,分出的词比较多

2.4自定义词典

1、在plugins/ik/config目录下创建一个ext.dic文件

touch ext.dic

2.更改IKAnalyzer.cfg.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 --><entry key="ext_dict">ext.dic</entry><!--用户可以在这里配置自己的扩展停止词字典--><entry key="ext_stopwords">stopword.dic</entry><!--用户可以在这里配置远程扩展字典 --><!-- <entry key="remote_ext_dict">words_location</entry> --><!--用户可以在这里配置远程扩展停止词字典--><!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

3.重启ES

docker restart es

3 ES核心概念

为了方便理解ES(8.5.0)中的相关概念,我们可以对比着MySQL进行学习,如下所示:

MySQLElasticsearch说明
TableIndex索引(index),就是文档的集合,类似数据库的表(table)
RowDocument文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式
ColumnField字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)
SchemaMappingMapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)
SQLDSLDSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式,比如下面这条用户数据;

{
    "name" :     "John",
    "sex" :      "Make",
    "age" :      25,
    "birthDate": "2024/05/01",
    "about" :    "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

mapping是处理数据的方式和规则方面做一些限制,如:某个字段的数据类型、默认值、分析器、是否被索引等等。这些都是映射里面可以设置的,其它就是处理ES里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。

4 ES基本操作(DSL)

4.2.1 创建索引库

PUT /my_index结果:
{"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_index"
}

4.2.2 查看所有索引库

语法: GET /_cat/indices?v

4.2.3 查看单个索引库

语法: GET /{索引名称}

GET /my_index
结果:
{"my_index" : {"aliases" : { },"mappings" : { },"settings" : {"index" : {"creation_date" : "1633499968211","number_of_shards" : "1","number_of_replicas" : "1","uuid" : "bclHUdHrS4W80qxnj3NP0A","version" : {"created" : "7080099"},"provided_name" : "my_index"}}}
}

4.2.4 删除索引库

DELETE /my_index
结果:
{"acknowledged" : true
}

4.3 文档操作

PUT /my_index/_doc/1
{"title": "小米手机","category": "小米","images": "/xm.jpg","price": 3999
}返回结果:
{"_index" : "my_index","_type" : "_doc","_id" : "1","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

4.3.2 查看文档

语法: GET /{索引名称}/{类型}/{id}

GET /my_index/_doc/1
结果:
{"_index" : "my_index","_type" : "_doc","_id" : "1","_version" : 1,"_seq_no" : 0,"_primary_term" : 1,"found" : true,"_source" : {"title" : "小米手机","category" : "小米","images" : "/xm.jpg","price" : 3999}
}

4.3.3 修改文档

PUT /my_index/_doc/1
{"title": "华为手机","category": "华为","images": "/hw.jpg"
}

0注意:上述的修改是先根据id把文档删除掉,然后重新添加文档

4.3.4 指定字段修改

POST /my_index/_update/1
{"doc": {"price": 4500}
}

4.3.5 删除文档

DELETE /my_index/_doc/1
结果:
{"_index" : "my_index","_type" : "_doc","_id" : "1","_version" : 12,"result" : "deleted","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 11,"_primary_term" : 1
}

4.4 映射mapping

语法: GET /{索引名称}/_mapping

Mapping的常见属性:

  • type:字段数据类型,常见的简单类型有:

    • 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)

    • 数值:long、integer、short、byte、double、float、

    • 布尔:boolean

    • 日期:date

    • 对象:object

  • index:是否创建倒排索引,默认为true

  • analyzer:指定在创建索引的时候所使用的分词器

  • search_analyzer:指定在搜索的时候所使用的分词器(如果没有指定该分词器,那么搜索的时候使用analyzer所指定的分词器)

4.4.3 创建索引指定映射

#删除原创建的索引
DELETE /my_index#创建索引,并同时指定映射关系和分词器等。
PUT /my_index
{"mappings": {"properties": {"id":{"type": "long","index": true},"title": {"type": "text","index": true,"analyzer": "ik_max_word","search_analyzer": "ik_smart"},"category": {"type": "keyword","index": true},"images": {"type": "keyword","index": false},"price": {"type": "integer","index": true}}}
}结果:
{"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_index"
}

创建映射的两种方式:

1、使用ES自动映射推断机制

2、在创建索引库的时候指定映射

上述两种方式如何进行选择?

1、优先选择"自动映射推断机制", 如果这种方式创建出来的映射中的某一个字段相关属性和我们所期望的有点不太一样,删除索引库

2、此时选择第二种方式创建映射(把有问题的字段属性设置一下即可)

5 ES高级查询(DSL)

5.1 查询所有(match_all)

GET /my_index/_search
{"query": {   # query 关键字就是设置搜索方式以及一些其他的搜索参数"match_all": {}}
}

5.2 匹配查询(match)

GET /my_index/_search
{"query": {"match": {"title": "华为智能手机"   # 会对搜索的关键字进行分词,然后使用各个词条从对应的倒排索引表中进行搜索}}
}

5.3 多字段匹配(multi_match)

GET /my_index/_search
{"query": {"multi_match": {"query": "华为智能手机","fields": ["title","category"]}}
}

5.4 关键字精确查询(term)

GET /my_index/_search
{"query": {"term": {"title": {"value": "华为手机"}}}
}

5.5 范围查询(range)

GET /my_index/_search
{"query": {"range": {"price": {"gte": 3000,"lte": 5000}}}
}

范围查询使用range。

  • gte: 大于等于

  • lte: 小于等于

  • gt: 大于

  • lt: 小于

5.6 组合查询(bool)

bool各条件之间有and,or或not的关系

  • must: 各个条件都必须满足,所有条件是and的关系

  • should: 各个条件有一个满足即可,即各条件是or的关系

  • must_not: 不满足所有条件,即各条件是not的关系

  • filter: 与must效果等同,但是它不计算得分,效率更高点。

ES会根据用户所输入的关键字和文档的匹配程度去计算文档的得分,后期会使用文档的得分对文档数据进行排序,返回的时候就会返回排序的结果

5.6.1 must

GET /my_index/_search
{"query": {"bool": {"must": [{"match": {"title": "华为"}},{"range": {"price": {"gte": 3000,"lte": 5000}}}]}}
}

5.6.2 should

GET /my_index/_search
{"query": {"bool": {"should": [{"match": {"title": "华为"}},{"range": {"price": {"gte": 3000,"lte": 5000}}}]}}
}

5.6.3 must_not

GET /my_index/_search
{"query": {"bool": {"must_not": [{"match": {"title": "华为"}},{"range": {"price": {"gte": 3000,"lte": 5000}}}]}}
}

5.7 排序(sort)

GET /my_index/_search
{"query": {"bool": {"must": [{"match": {"title": "华为"}}]}},"sort": [{"price": {"order": "asc"}}]
}

5.8 分页查询(from、size)

分页的两个关键属性:from、size

  • from: 当前页的起始索引,默认从0开始。 from = (pageNo - 1) * pageize

  • size: 每页显示多少条

POST /my_index/_search
{"query": {"match_all": {}},"from": 0,"size": 2
}

5.9 高亮查询(highlight)

高亮显示的实现分为两步:

1)给文档中的所有关键字都添加一个标签,例如<em>标签

2)页面给<em>标签编写CSS样式

POST /my_index/_search
{"query": {"match": {"title": "华为"}},"highlight": {"fields": { // 指定要高亮的字段"FIELD": {"pre_tags": "<em>",  // 用来标记高亮字段的前置标签"post_tags": "</em>" // 用来标记高亮字段的后置标签}}}
}

6 Spring Data ES

Spring Data是一个用于简化数据库、非关系型数据库、索引库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce

框架和云计算数据服务。 Spring Data可以极大的简化JPA(Elasticsearch…)的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。

Spring Data Elasticsearch 基于Spring data API 简化 Elasticsearch操作(基本的增删改查),将原始操作Elasticsearch的客户端API 进行封装 。

Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch也是基于ORM思想进行设计

思考问题:怎么使用呢?需要建立实体类索引库之间的对应关系,以及实体类中的属性和索引库字段之间的对应关系【使用相关的注解完成】。

6.4 环境搭建

6.4.1 创建项目

创建一个spring boot的项目(spring-data-es),在pom.xml文件中加入如下的依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.5</version><relativePath/>
</parent><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
</dependencies>
<build><plugins><!-- java编译插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.2</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin></plugins>
</build>

6.4.2 yml文件

# es连接地址配置
spring:elasticsearch:uris: 192.168.136.147:9200

6.4.3 启动类

package com.es;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringDataEsApplication {public static void main(String[] args) {SpringApplication.run(SpringDataEsApplication.class , args) ;}}

6.4.4 实体类

// 商品实体类
@Data
@Document(indexName = "product")        // 建立实体类和es索引库中的对应关系
public class Product {@Idprivate Long id ;                  // 主键@Field(name = "productName" , type = FieldType.Text , analyzer = "ik_max_word" )private String productName ;        // 商品的名称,普通的属性@Field(type = FieldType.Integer)private Integer store ;         // 产品库存@Field(type = FieldType.Double)private Double price ;			// 产品价格@Field(type = FieldType.Long)private Long brandId ;			// 品牌id@Field(type = FieldType.Keyword)private String brandName ;		// 品牌名称@Field(type = FieldType.Nested)  // 针对List集合类型的属性需要将其类型设置为Nested, TODO: 为什么需要设置为Nestedprivate List<Attr> attrList ;    // 产品属性}@Data
@NoArgsConstructor
@AllArgsConstructor
public class Attr {			// 产品属性实体类@Idprivate Long attrId ;           // 属性id@Field(type = FieldType.Keyword)private String attrName ;       // 属性名称@Field(type = FieldType.Keyword)private String attrValue ;      // 属性值}

注解含义:

@Document 作用在类,标记实体类为文档对象。indexName属性:对应索引库名称

@Id 作用在成员变量,标记一个字段作为id主键

@Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:

1、type:字段类型,取值是枚举:FieldType

2、index:是否索引,布尔类型,默认是true

3、store:是否存储,布尔类型,默认是false

4、analyzer:分词器名称:ik_max_word

6.5 使用方式一

借助:ElasticsearchRepository接口

定义持久层操作接口:

@Repository
public interface ProductRepository extends ElasticsearchRepository<Product , Long> {}

6.5.1 添加文档

@Test
public void saveProduct() {List<Attr> attrList = Arrays.asList(new Attr(1L, "内存", "8G"), new Attr(2L, "硬盘", "256G"));Product prod = Product.builder().id(4L).productName("vivo手机").price(2999.0).store(50).brandId(3L).brandName("vivo").attrList(attrList).build();productRepository.save(prod) ;}

6.5.2 根据id查询

@SpringBootTest(classes = SpringDataEsApplication.class)
public class ProductRepositoryTest {@Autowiredprivate ProductRepository productRepository ;@Testpublic void findById() {Optional<Product> product = productRepository.findById(1L);Product prod = product.get();System.out.println(prod);}}

6.5.4 分页查询

@Test
public void queryPage() {Pageable pageable = PageRequest.of(0, 1);Page<Product> products = productRepository.findAll(pageable);products.forEach( s -> System.out.println(s) );
}

6.6 使用方式二

借助:ElasticsearchClient

ElasticsearchClient是Elasticsearch中所提供的一个操作ES的新的核心类,并且已经被Spring Boot实现了自动化配置。

6.6.1 基本操作

@SpringBootTest(classes = SpringDataEsApplication.class)
//classes = SpringDataEsApplication.class 表示加载应用的主配置类
public class ElasticsearchClientTest {@Autowiredprivate ElasticsearchClient elasticsearchClient ;@Testpublic void saveProduct() throws IOException {List<Attr> attrList = Arrays.asList(new Attr(1L, "内存", "6G"), new Attr(2L, "硬盘", "128G"));Product prod = Product.builder().id(2L).productName("小米手机").price(3999.0).store(200).brandId(2L).brandName("小米").attrList(attrList).build();//IndexRequest 是 Elasticsearch 的请求对象,表示向 Elasticsearch 发送一个索引请求,将一个文档存入指定的索引库。IndexRequest indexRequest = new IndexRequest.Builder<Product>().index("product")       // 指定索引库的名称.id("2")                // 指定文档id.document(prod).build() ;IndexResponse indexResponse = elasticsearchClient.index(indexRequest) ;System.out.println(indexResponse);}
}
根据id查询
@Test
public void getById() throws IOException {GetRequest getRequest = new GetRequest.Builder().index("product").id("2").build() ;GetResponse<Product> response = elasticsearchClient.get(getRequest, Product.class);Product product = response.source();System.out.println(product);
}
@Test
public void updateById() throws IOException {Product prod = Product.builder().id(1L).store(150).build();// Builder类上的两个泛型:TDocument表示完整的文档类型,而TPartialDocument表示部分更新的文档类型。UpdateRequest updateRequest = new UpdateRequest.Builder<Product , Product>().index("product").id("1").doc(prod).build() ;UpdateResponse updateResponse = elasticsearchClient.update(updateRequest, Product.class);System.out.println(updateResponse);
}
@Test
public void deleteById() throws IOException {DeleteRequest deleteRequest = new DeleteRequest.Builder().index("product").id("3").build() ;DeleteResponse deleteResponse = elasticsearchClient.delete(deleteRequest);System.out.println(deleteResponse);
}

6.6.2 高级操作

查询所有

@Test
public void search() throws IOException {// 创建搜索条件对象Query query = new Query.Builder().matchAll(QueryBuilders.matchAll().build()).build();// 创建搜索请求对象SearchRequest searchRequest = new SearchRequest.Builder().index("product")           // 设置索引库的名称.query(query).build() ;// 发送搜索请求SearchResponse<Product> searchResponse = elasticsearchClient.search(searchRequest, Product.class);// 解析结果HitsMetadata<Product> hitsMetadata = searchResponse.hits();long total = hitsMetadata.total().value() ;System.out.println("满足条件的总记录数:" + total);List<Hit<Product>> hits = hitsMetadata.hits();for(Hit<Product> hit : hits) {Product product = hit.source();System.out.println(product);}
}
// 范围查询
Query query = new Query.Builder().range(QueryBuilders.range().field("store").gt(JsonData.of(180)).build()).build() ;// 匹配查询
Query query = new Query.Builder().match(QueryBuilders.match().field("productName").query("小米").build()).build();// 多字段匹配查询Query query = new Query.Builder().multiMatch(QueryBuilders.multiMatch().fields("productName" , "brandName").query("手机").build()).build();// 词条查询
Query query = new Query.Builder().term(QueryBuilders.term().field("brandName").value("小米").build()).build() ;
  @Testpublic void updataRequest() throws IOException {Product prod = Product.builder().id(1L).price(2000D).build();// Builder类上的两个泛型:TDocument表示完整的文档类型,而TPartialDocument表示部分更新的文档类型。UpdateRequest updateRequest = new UpdateRequest.Builder<Product , Product>().index("product").id("1").doc(prod).build() ;UpdateResponse updateResponse = elasticsearchClient.update(updateRequest, Product.class);System.out.println(updateResponse);//        //属性数据
//        List<Attr> attrList = List.of(new Attr(1L,"内存","32GB"),
//                new Attr(2L,"内存","64GB"));
//        //商品数据
//        Product product = new
//                Product(3L,"华为手机",999,6599.99,5L,"华为",attrList);
//
//        UpdateRequest<Object, Object> build = new UpdateRequest.Builder<>()
//                .index("product")
//                .id("2")
//                .doc(product)
//                .build();
//        elasticsearchClient.update(build,Product.class);}
Product prod = Product.builder().id(1L).price(2000D).build();//构造器模式
    @Testpublic void jingqueSearch() throws IOException {//            TermQuery termQuery = new TermQuery.Builder()
//                .field("brandName")
//                .value("苹果")
//                .build();
//        Query query = new Query.Builder()
//                .term(termQuery->termQuery.field("brandName").value("苹果"))
//                .build();SearchRequest build = new SearchRequest.Builder().query(query1->query1.term(termQuery->termQuery.field("brandName").value("苹果"))).build();SearchResponse searchResponse= elasticsearchClient.search(build,Product.class);System.out.println(searchResponse);}
}
  @Testpublic void jingqueSearch() throws IOException {//            TermQuery termQuery = new TermQuery.Builder()
//                .field("brandName")
//                .value("苹果")
//                .build();
//        Query query = new Query.Builder()
//                .term(termQuery->termQuery.field("brandName").value("苹果"))
//                .build();SearchRequest build = new SearchRequest.Builder().query(query1->query1.term(termQuery->termQuery.field("brandName").value("苹果"))).build();SearchResponse searchResponse= elasticsearchClient.search(build,Product.class);System.out.println(searchResponse);}
 @Testpublic void highLight() throws IOException {MatchQuery matchQuery = new MatchQuery.Builder().query("华为").field("brandName").build();HighlightField highlightField = new HighlightField.Builder().preTags("<font color='red'>").postTags("</font>").build();Highlight highlight = new Highlight.Builder().fields("brandName",highlightField).build();Query query =new Query.Builder().match(matchQuery).build();SearchRequest searchRequest=new SearchRequest.Builder().highlight(highlight).query(query).build();SearchResponse<Product> searchResponse=elasticsearchClient.search(searchRequest,Product.class);HitsMetadata<Product> hitsMetadata = searchResponse.hits();long total = hitsMetadata.total().value() ;System.out.println("满足条件的总记录数:" + total);List<Hit<Product>> hits = hitsMetadata.hits();for (Hit<Product> hit : hits){// 获取原始文档数据Product product = hit.source();// 解析高亮结果Map<String, List<String>> highlightFielMap = hit.highlight();if(highlightFielMap != null && highlightFielMap.size() > 0) {List<String> productNameHighlightList = highlightFielMap.get("productName");if(productNameHighlightList != null && productNameHighlightList.size() > 0) {String productNameHighlightValue = productNameHighlightList.get(0);product.setProductName(productNameHighlightValue);}}// 输出结果System.out.println(product);}}
}
    @Testpublic void highLight() throws IOException {Highlight highlight = new Highlight.Builder().fields("brandName",highlightField->highlightField.preTags("<font color='red'>").postTags("</font>")).build();Query query =new Query.Builder().match(matchQuery->matchQuery.field("brandName").query("华为")).build();SearchRequest searchRequest=new SearchRequest.Builder().highlight(highlight).query(query).build();SearchResponse<Product> searchResponse=elasticsearchClient.search(searchRequest,Product.class);HitsMetadata<Product> hitsMetadata = searchResponse.hits();long total = hitsMetadata.total().value() ;System.out.println("满足条件的总记录数:" + total);List<Hit<Product>> hits = hitsMetadata.hits();for (Hit<Product> hit : hits){// 获取原始文档数据Product product = hit.source();// 解析高亮结果Map<String, List<String>> highlightFielMap = hit.highlight();if(highlightFielMap != null && highlightFielMap.size() > 0) {List<String> productNameHighlightList = highlightFielMap.get("productName");if(productNameHighlightList != null && productNameHighlightList.size() > 0) {String productNameHighlightValue = productNameHighlightList.get(0);product.setProductName(productNameHighlightValue);}}// 输出结果System.out.println(product);}}
}

7.Nested类型

8.聚合查询

ES聚合查询是一种统计、分组和过滤数据的方式,通过对文档中的字段进行聚合操作,实现对数据的统计分析。类似于MySQL分组操作(group by)以及聚合函数(max、min、avg 、sum、 count)。

ES提供的聚合分析功能有指标聚合(metrics aggregations)桶聚合(bucket aggregations)管道聚合(pipeline aggregations)三大类。

8.1 桶型聚合

桶型聚合是将文档按照某个字段进行分组,把相同值的文档放入同一个桶中,然后对桶中的文档进行统计、计算等操作(类似于MySQL中的Group by)。ES中的桶型

8.1.1 桶型聚合简介

8.1.2 terms聚合演示

 @Testpublic void bucketAggreation() throws IOException {// MatchAll 查询MatchAllQuery matchAllQuery = new MatchAllQuery.Builder().build();Query querybuid = new Query.Builder().matchAll(matchAllQuery).build();// Terms 聚合,按 price 字段聚合,获取前 2 个桶TermsAggregation termsAggregation = new TermsAggregation.Builder().field("price").size(2).build();// 将聚合添加到请求中Aggregation aggregation = new Aggregation.Builder().terms(termsAggregation).build();// 创建搜索请求SearchRequest searchRequest = new SearchRequest.Builder().index("product").query(querybuid).aggregations("price", aggregation)  // 设置聚合名称为 "price".build();// 执行搜索请求SearchResponse searchResponse = elasticsearchClient.search(searchRequest,Product.class);// 获取聚合结果Map<String, Aggregate> aggregations = searchResponse.aggregations();// 根据聚合名称 "price" 获取聚合结果Aggregate aggregate = aggregations.get("price");System.out.println("aggregate = " + aggregate);// 转换为 DoubleTermsAggregate(假设 price 是 double 类型)DoubleTermsAggregate o = (DoubleTermsAggregate) aggregate._get();// 获取聚合结果中的桶Buckets<DoubleTermsBucket> buckets = o.buckets();// 打印桶的信息List<DoubleTermsBucket> array = buckets.array();for (DoubleTermsBucket bucket : array) {System.out.println("bucket.key() = " + bucket.key());System.out.println("bucket.docCount() = " + bucket.docCount());}}
 @Testpublic void statsSearch() throws IOException {StatsAggregation statsAggregation = new StatsAggregation.Builder().field("price").build();Aggregation aggregation = new Aggregation.Builder().stats(statsAggregation).build();SearchRequest searchRequest = new SearchRequest.Builder().index("product").aggregations("stats",aggregation).build();// 执行搜索请求SearchResponse searchResponse = elasticsearchClient.search(searchRequest,Product.class);Map<String, Aggregate> aggregateMap = searchResponse.aggregations();Aggregate aggregate = aggregateMap.get("stats");StatsAggregate statsAggregate = (StatsAggregate) aggregate._get();double sum = statsAggregate.sum();System.out.println("sum = " + sum);double min = statsAggregate.min();System.out.println("min = " + min);double max = statsAggregate.max();System.out.println("max = " + max);double avg = statsAggregate.avg();System.out.println("avg = " + avg);long count = statsAggregate.count();System.out.println("count = " + count);System.out.println();}

9 .自动补全功能

9.1 自动补全说明

自动补全功能就是当用户输入搜索关键字以后,自动从ES索引库中搜索出来和当前关键字相匹配的数据,如下所示:

Completion Suggester实现自动补全功能,需要自动补全的字段类型一定是completion,参与补全查询的字段必须是completion类型。字段的内容可以是用

来补全的多个词条形成的数组。

GET /test/_search
{"suggest": {"suggestValue": {"prefix":"fo","completion":{"skip_duplicates":true,"field":"suggest","fuzzy":{"fuzziness":"auto"}}}}
}
  • suggest: 表示这是一个建议(suggestion)查询,用于提供基于用户输入的自动补全建议。

  • suggestValue: 是自定义的建议查询名称,你可以根据需要随意命名。

  • prefix: 查询前缀,用于匹配建议的起始字符串。在这个例子中,任何以"fos"开头的建议都会被返回。

  • completion: 表示这是一个完成建议查询,它是Elasticsearch中用于实现自动补全功能的一种查询类型。

    • skip_duplicates: 当设置为true时,会跳过结果中的重复项,确保每个建议都是唯一的。

    • field: 指定在哪个字段上执行完成建议查询。在这个例子中,字段名为"suggest"。

    • fuzzy: 启用模糊匹配,允许返回与用户输入相近但不完全匹配的建议。

      • fuzziness: 指定模糊匹配的程度。"auto"表示Elasticsearch会根据术语的长度自动选择一个合适的模糊值。例如,对于短的术语,它可能会允许更多的编辑距离。

总的来说,这段代码的目的是在Elasticsearch的test索引中,查找字段suggest包含以"fos"为前缀的项,并且返回唯一的、可能模糊匹配的建议列表。这通常用于实现搜索框的自动补全功能,帮助用户在输入查询时快速找到他们可能想要搜索的完整术语。

        @Testpublic void suggestReserach() throws IOException {CompletionSuggester completionSuggester = new CompletionSuggester.Builder().field("suggest").skipDuplicates(true).fuzzy(fuzzy1->fuzzy1.fuzziness("auto")).build();FieldSuggester fieldSuggester = new FieldSuggester.Builder().prefix("fo").completion(completionSuggester).build();Suggester suggester = new Suggester.Builder().suggesters("Suggester",fieldSuggester).build();SearchRequest searchRequest = new SearchRequest.Builder().index("test").suggest(suggester).build();// 执行搜索请求SearchResponse searchResponse = elasticsearchClient.search(searchRequest,Object.class);Map suggest = searchResponse.suggest();}
}

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

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

相关文章

java八股-jvm入门-程序计数器,堆,元空间,虚拟机栈,本地方法栈,类加载器,双亲委派,类加载执行过程

文章目录 PC Register堆虚拟机栈方法区(Metaspace元空间双亲委派机制类加载器 类装载的执行过程 PC Register 程序计数器&#xff08;Program Counter Register&#xff09;是 Java 虚拟机&#xff08;JVM&#xff09;中的一个组件&#xff0c;它在 JVM 的内存模型中扮演着非常…

Docker 篇-Docker 详细安装、了解和使用 Docker 核心功能(数据卷、自定义镜像 Dockerfile、网络)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Docker 概述 1.1 Docker 主要组成部分 1.2 Docker 安装 2.0 Docker 常见命令 2.1 常见的命令介绍 2.2 常见的命令演示 3.0 数据卷 3.1 数据卷常见的命令 3.2 常见…

恶意PDF文档分析记录

0x1 PDF是什么 PDF&#xff08;便携式文件格式&#xff0c;Portable Document Format&#xff09;是由Adobe Systems在1993年用於文件交换所发展出的文件格式。 因为PDF的文件格式性质广泛用于商业办公&#xff0c;引起众多攻击者对其开展技术研究&#xff0c;在一些APT&#…

SpringBoot集成itext导出PDF

添加依赖 <!-- PDF导出 --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.11</version></dependency><dependency><groupId>com.itextpdf</groupId>&l…

不想后悔,混动车这样买

文 | AUTO芯球 作者 | 雷慢 不买一辆混动车&#xff0c; 你永远不知道自己有多抠&#xff01; 我有个跑滴滴的小伙伴&#xff0c; 他说近10年来最后悔的事&#xff0c; 就是没买个纯电续航长点的混动车&#xff0c; 怎么回事呢&#xff0c; 这个小伙伴今年买了辆纯电续航…

第一个C语言程序,带领我们进入C语言的大门!

第一个C语言程序&#xff0c;带领我们进入C语言的大门&#xff01; 我们有两种方式从计算机获得信息&#xff1a;一是看屏幕上的文字、图片、视频等&#xff0c;二是听从喇叭发出来的声音。让喇叭发出声音目前还比较麻烦&#xff0c;我们先来看看如何在屏幕上显示一些文字吧。p…

大模型到底是什么?小白也能看懂的科普贴,让你从大模型入门到大模型精通

&#xff08;图源网络&#xff09; 从去年到今年&#xff0c;大模型、chatGPT等概念和技术越来越火&#xff0c;但是像笔者一样的技术小白一直对大模型是一种似懂非懂的状态。鉴于最近在做基于大模型和Agent的上层AI应用&#xff0c;如若不了解底层概念&#xff0c;始终还是会…

qt QStandardPaths 详解

1、概述 QStandardPaths是Qt框架中的一个类&#xff0c;它提供了一种跨平台的方式来访问标准的位置&#xff0c;如应用程序的数据目录、配置目录、缓存目录、临时文件目录等。这些位置通常是用户特定的&#xff0c;并且遵循操作系统的标准和惯例。通过使用QStandardPaths&…

对node工程进行压力测试与性能分析

在系统上线前&#xff0c;为了看下系统能承受多大的并发和并发下的负载情况&#xff0c;进行了一轮压测。在压测过程中&#xff0c;发现服务器的cpu飚的的非常高&#xff0c;而tps&#xff0c;接口耗时、服务可用等都是正常的&#xff0c;卧槽&#xff0c;这就奇了怪了&#xf…

昆明华厦眼科医院在大观小学开展近视科普教育讲座

为响应全社会对青少年近视防控的号召&#xff0c;昆明华厦眼科医院组织了一场近视科普教育讲座&#xff0c;活动走进大观小学&#xff0c;旨在通过专业的眼科知识普及&#xff0c;提升小学生们对眼健康的认知&#xff0c;培养他们爱眼护眼的意识。讲座结束后还特地为教师群体进…

MPLS基本原理

Multiprotocol Label Switching 多标签交换 前言 MPLS位于TCP/IP协议栈中的链路层和网络层之间,用于向IP层提供连接服务,同时又从链路层达到服务.MPLS以标签交换代替IP转发. MPLS并不是一种业务或者应用,它实际上是一种隧道技术.这种技术不仅支持多种高层协议与业务,而且在一…

《MarsCode:编程领域的智能新势力》

《MarsCode&#xff1a;编程领域的智能新势力》 一、MarsCode 的诞生与发展&#xff08;一&#xff09;逐步崛起的历程&#xff08;二&#xff09;与各方的合作与影响 二、MarsCode 的独特魅力&#xff08;一&#xff09;强大的功能特点&#xff08;二&#xff09;多语言支持与…

PyInstaller未包含预编译引导程序

1 现象 在使用 PyInstaller 打包 Python 应用时&#xff0c;遇到了一个错误&#xff0c;错误信息如下&#xff1a; Fatal error: PyInstaller does not include a pre-compiled bootloader for your platform. For more details and instructions how to build the bootloade…

华为HCIP-openEuler考试内容大纲:备考必看!

华为HCIP-openEuler认证考试作为ICT领域的一项重要技术认证&#xff0c;已经成为越来越多IT从业者追求的目标。无论你是想提升自己的技术能力&#xff0c;还是为了未来的职业发展&#xff0c;HCIP-openEuler都是一个极具价值的认证。那么&#xff0c;如何高效备考&#xff0c;顺…

编程之路,从0开始:知识补充篇

Hello大家好&#xff0c;很高兴我们又见面了&#xff01; 给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 这一篇我们来补充一下在之前篇目没讲到的知识&#xff0c;并结合一些码友的私信提问和我在编程中遇到的问题&#xff0c;做一些易错点或易混点的讲解。 …

免费PC游戏加速器--慕讯公益加速器

百度网盘链接&#xff1a; 慕讯公益加速器 提取码: y54m 官网&#xff1a; 慕讯公益加速器 优点&#xff1a; 1.不像其他加速器假免费&#xff0c;但支持的话可以向软件捐款 2.加速游戏很全&#xff08;Nikke等游戏都可以选择它&#xff09;&#xff0c;可以自由选择节点 …

git 常用命令大全

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、git是什么&#xff1f;二、工作中常用git命令集合三、部分git命令注意事项四、git reset 的五种模式五、总结 前言 git命令 其实不管是服务端还是前端&am…

【JAVA毕业设计】基于Vue和SpringBoot的校园资料分享平台

博主说明&#xff1a;本文项目编号 T 059 &#xff0c;文末自助获取源码 \color{red}{T059&#xff0c;文末自助获取源码} T059&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

typedef 与 extern 的结合:一场误解的澄清

typedef 与 extern 的结合:一场误解的澄清 一、typedef 的基本用法二、extern 的基本用法三、typedef 与 extern 的结合:一场误解的澄清示例二:使用 extern 声明外部变量示例三:错误的用法:尝试在 typedef 中使用 extern四、总结在C语言编程的世界里,typedef和extern是两…

腾讯的AI困局

科技新知 原创作者丨林书 编辑丨蕨影 2024年已经逐渐步入了尾声&#xff0c;但国产大模型的内卷之战却还在继续着…… 最近&#xff0c;腾讯终于有了新动作&#xff0c;在开源模型上卯足了劲。11 月 5 日&#xff0c;腾讯宣布开源 MoE 大语言模型混元 Large&#xff0c;腾讯称…