ElasticSearch 集成 SpringBoot
方法有这几种
1.9300:TCP
- spring-data-elasticsearch:transport-api.jar
- springboot 版本不同,transport-api.jar 不同,不能适配 es 版本
- 7.x 已经不建议使用,8以上就要废弃
- 9200:HTTP
- jestClient: 非官方,更新慢
- RestTemplate:模拟发送HTTP请求,ES很多操作都要自己封装
- HttpClient:同上
- ElasticSearch-Rest-Client: 官方 RestClient,封装了 ES 操作,API层次分明,上手简单
官方文档
1、找到原生的依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.9.2</version>
</dependency>
2、找对象
3、分析这个类中的方法
配置基本的项目
问题:一定要保证我们导入的依赖和我们使用的一致
相关源码
具体的API测试
1、创建索引
2、判断索引是否存在
3、删除索引
4、创建文档
5、CRUD文档
配置文件
@Configuration
public class ElasticSearchClientConfig {
// spring <beans id="restHighLevelClient" class="RestHighLevelClient">
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1", 9200,"http")));
return client;
}
}
@SpringBootTest
class HuduEsApiApplicationTests {
//面向对象来操作
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
// 测试索引的创建 Request请求 PUT hudu_index
@Test
void testCreateIndex() throws IOException {
//1、创建索引请求
CreateIndexRequest request = new CreateIndexRequest("hudu_index");
//2、客户端执行创建请求
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
//测试获取索引,只能判断其是否存在
@Test
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("hudu_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//测试删除索引
@Test
void deleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("hudu_index");
//删除
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
//测试添加文档
@Test
void testAddDocument() throws IOException {
//创建对象
User user = new User("hudu", 3);
//创建请求
IndexRequest request = new IndexRequest("hudu_index");
//规则 PUT /hudu_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
//将我们的数据放入请求
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求,获取响应结果
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());//
System.out.println(indexResponse.status());//对应命令行的状态
}
//获取文档,判断是否存在 get /index/_doc/1
@Test
void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("hudu_index", "1");
//不获取返回的_source 的上下文
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
//获得文档的信息
@Test
void testGetDocument() throws IOException {
GetRequest getRequest = new GetRequest("hudu_index", "1");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());//打印文档的内容
System.out.println(getResponse);//返回的全部内容和命令是一样的
}
//更新文档信息
@Test
void testUpdateDocument() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("hudu_index", "1");
updateRequest.timeout("1s");
User user = new User("Alex", 20);
updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
//删除文档记录
@Test
void testDeleteRequest() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("hudu_index","3");
deleteRequest.timeout("1s");
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
//特殊的,真实的项目一般都会批量插入数据!
@Test
void testBulkRequest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("hudu1",20));
userList.add(new User("hudu2",21));
userList.add(new User("hudu3",22));
userList.add(new User("hudu4",23));
userList.add(new User("hudu5",24));
//批处理请求
for (int i = 0; i < userList.size(); i++) {
//批量更新和批量删除,就在这里修改对应的请求即可
bulkRequest.add(
new IndexRequest("hudu_index")
.id(""+(i+1))
.source(JSON.toJSONString(userList.get(i)),XContentType.JSON)
);
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures());//是否失败,返回false表示成功
}
}
//查询
//SearchRequest搜索请求
//SearchSourceBuilder 条件构造
//HighlightBuilder 构建高亮
//termQueryBuilder 构建精确查询
// MatchAllQueryBuilder
// xxxQueryBuilder 对应我们刚才看到的命令
@Test
void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("hudu_index");
//构建搜索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//查询条件,我们可以使用QueryBuilders 工具类来实现
//QueryBuilders.termQuery 精确匹配
//QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "hudu1");
// MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse.getHits());
System.out.println("=====================================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
通过 SpringData 整合
添加依赖
根据自己的需求来选择需要的版本
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
常用注解
// 标识映射到 Elasticsearch 文档上的领域对象
public @interface Document {
// 索引名称,mysql中数据库概念
String indexName();
// 文档类型,mysql 中表的概念
String type() defalut "";
// 默认分片数
short shards() defalut 5;
// 默认副本数量
short replicas() default 1;
}
// 表示是文档的id,文档可以认为mysql主键概念
public @interface Field {
// 文档字段的类型
FieldType type() defalut FieldType.Auto;
// 是否建立倒排索引
boolean index() defalut true;
// 是否进行存储
boolean storeI() defalut false;
// 分词器名称
String analyzer() default "";
}
// 为文档自动指定元数据类型
public enum FieldType {
Text, // 会进行分词并建立索引的字符串类型
Integer,
Long,
Date,
Float,
Double,
Boolean,
Object,
Auto, // 自动判断字段类型
Nested, // 嵌套对象类型
Ip,
Attachment,
Keyword // 不会进行分词建立索引
}
写配置
# es 配置
# es reposity配置
elasticsearch:
rest:
uris: http://192.168.33.61:9200
# template
data:
elasticsearch:
repositories:
enabled: true
client:
reactive:
endpoints: 192.168.33.61:9200
ElasticsearchRepository
关键字 | 使用示例 | 等同于 ES 查询 |
---|---|---|
And |
findByNameAndPrice | “bool”: {“must”: [{“field”: {“name”:”?”}},{“field”: {“price”:”?”}}]} |
Or |
findByNameOrPrice | “bool”: {“should”: [{“field”: {“name”:”?”}},{“field”: {“price”:”?”}}]} |
Is |
findByName | “bool”: {“must”: [{“field”:{“name”:”?”}}]} |
Not |
findByNameNot | “bool”: {“must_not”: [{“field”:{“name”:”?”}}]} |
整合应用
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置客户端
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
客户端对象
- ElasticsearchOperations
- RestHighLevelClient 推荐
ElasticsearchOperations
- 特点:始终使用面向对象的方式操作 ES
- 索引:用来存放相似文档集合
- 映射:用来决定放入文档中的每个字段以什么样的方式存入 ES 中,例如字段类型、分词器。。。
- 文档:可以被索引的最小单元 json 数据格式
相关注解
// 用在类上 indexName 索引名称,createIndex 是否创建索引
@Document(indexName = "products", createIndex = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
// 用在属性上 将对象 id 字段与 ES 中文档的 _id 对应
@Id
private Integer id;
// 用在属性上,用来描述属性在 ES 中存储类型以及分词情况
@Field(type = FieldType.Keyword)
private String title;
@Field(type = FieldType.Double)
private Double price;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String description;
@Field(type = FieldType.Date,format = {},pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
}
索引文档
@Test
public void testCreate() {
Product product = new Product();
product.setId(1); // 存在id指定id,不存在id自动生成id
product.setTitle("面包");
product.setPrice(15.5);
product.setDescription("面包真好吃");
product.setCreatedAt(LocalDateTime.now());
elasticsearchOperations.save(product);
}
查询文档
@Test
public void testSearch() {
Product product = elasticsearchOperations.get("1", Product.class);
System.out.println(product);
}
删除文档
@Test
public void testDelete() {
Product product = new Product();
product.setId(1);
String delete = elasticsearchOperations.delete(product);
System.out.println(delete);
}
删除所有
@Test
public void testDeleteAll() {
ByQueryResponse delete = elasticsearchOperations.delete(Query.findAll(), Product.class);
System.out.println(delete.getDeleted());
}
查询所有
@Test
public void testFindAll() {
SearchHits<Product> productSearchHits = elasticsearchOperations.search(Query.findAll(), Product.class);
productSearchHits.forEach(productSearchHit -> {
System.out.println("id:" + productSearchHit.getId());
System.out.println("score:" + productSearchHit.getScore());
System.out.println("product:" + productSearchHit.getContent());
});
}
RestHighLevelClient
创建索引和映射
@Test
public void indexTest() throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest("products");
//指定映射
// 参数 1:指定映射 json 结构,参数 2:指定数据类型
createIndexRequest.mapping("{\n" +
" \"properties\": {\n" +
" \"id\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"title\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"price\":{\n" +
" \"type\": \"double\"\n" +
" },\n" +
" \"created_at\":{\n" +
" \"type\": \"text\"\n" +
" },\n" +
" \"description\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" }", XContentType.JSON);
// 参数 1:创建索引的请求对象 参数 2:请求配置对象
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println("创建状态:"+createIndexResponse.isAcknowledged());
restHighLevelClient.close(); // 关闭资源
}
对比 kibana 创建索引语句
PUT /products
{
"mappings": {
"properties": {
"id":{
"type": "integer"
},
"title":{
"type": "keyword"
},
"price":{
"type": "double"
},
"created_at":{
"type": "text"
},
"description":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
删除索引
@Test
public void testDeleteIndex() throws IOException {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("products");
// 参数 1:删除索引对象,参数 2:请求配置
AcknowledgedResponse response = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
}
对比 kibana
DELETE /products
索引文档
@Test
public void testCreate() throws IOException {
// 参数 1:索引请求对象,2:请求配置对象
IndexRequest indexRequest = new IndexRequest("products");
indexRequest.id("1") // 手动指定文档 id
.source("{\n" +
" \"id\":1,\n" +
" \"title\":\"iphone 13\",\n" +
" \"price\":5599.99,\n" +
" \"created_at\":\"2022-05-17\",\n" +
" \"description\":\"iphone 14 屏幕采用 6.1 英寸 OLED 屏幕\"\n" +
"}", XContentType.JSON); // 指定文档数据
IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
对比 kibana
POST /products/_doc/1
{
"id":1,
"title":"iphone 14",
"price":5599.99,
"created_at":"2022-05-17",
"description":"iphone 14 屏幕采用 6.2 英寸 OLED 屏幕"
}
更新文档
@Test
public void testUpdate() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("products","1");
updateRequest.doc("{\n" +
" \"title\":\"iphone 12\"\n" +
" }",XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
批量更新
@Test
public void updateByQuery() {
String[] ids = new String[]{"2","3"};
try {
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest("products");
HashMap<String, Object> map = new HashMap<>();
// 需要修改的数据
map.put("price",1);
// 需要执行的脚本
String code = "ctx._source.isEncrypt=params.price";
updateByQueryRequest
.setScript(new Script(Script.DEFAULT_SCRIPT_TYPE,Script.DEFAULT_SCRIPT_LANG,code,map))
.setQuery(QueryBuilders.idsQuery().addIds(ids));
System.out.println(updateByQueryRequest.toString());
restHighLevelClient.updateByQuery(updateByQueryRequest,RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
}
对比 kibana
将所有的牛奶价格都更新为 59。
POST /products/_update_by_query
{
"script": {
"source": "ctx._source.price=59",
"lang": "painless"
},
"query": {
"ids": {
"values": [2,3]
}
}
}
对比 kibana
POST /products/_doc/1/_update
{
"doc":{
"title":"iphone 12"
}
}
删除文档
@Test
public void testDelete() throws IOException {
DeleteResponse deleteResponse = restHighLevelClient.delete(new DeleteRequest("products", "1"), RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
对比 kibana
DELETE /product/_doc/1
基于 id 查询文档
@Test
public void testGet() throws IOException {
GetResponse getResponse = restHighLevelClient.get(new GetRequest("products", "1"), RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());
}
对比 kibana
GET /products/_doc/1
查询所有
@Test
public void testMatchAll() throws IOException {
// 指定查询索引
SearchRequest searchRequest = new SearchRequest("products");
// 指定条件对象
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 查询所有
sourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数" + searchResponse.getHits().getTotalHits().value);
System.out.println("最大得分" + searchResponse.getHits().getMaxScore());
// 获取结果
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
String id = hit.getId();
System.out.println("id" + id + "source:" + hit.getSourceAsString());
}
}
对比 kibana
GET /products/_search
{
"query": {
"match_all": {}
}
}
文档查询
@Test
public void testTermSearch() throws IOException {
// 1. term 查询
query(QueryBuilders.termQuery("description","iphone"));
// 2. range 查询
query(QueryBuilders.rangeQuery("price").gte(100).lte(9000));
// 3. prefix 前缀查询
query(QueryBuilders.prefixQuery("title","iphone"));
// 4. wildcard 通配符
query(QueryBuilders.wildcardQuery("title","iph*"));
// 5. ids 指定多个id
query(QueryBuilders.idsQuery().addIds("1"));
// 6. multi_match 多字段查询
query(QueryBuilders.multiMatchQuery("屏幕","description","title"));
}
public void query(QueryBuilder queryBuilder) throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 指定查询条件
sourceBuilder.query(queryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数" + searchResponse.getHits().getTotalHits().value);
System.out.println("最大得分" + searchResponse.getHits().getMaxScore());
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
}
}
@Test
public void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 创建高亮匹配
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false)
.field("description").field("title")
.preTags("<front style='color:red'>")
.postTags("</front>");
sourceBuilder.query(QueryBuilders.matchQuery("description","iphone"))
.from(0) // 起始位置 start = (page-1) * size
.size(10) // 每页显示条数,默认返回 10 条
.sort("price", SortOrder.ASC) // 排序
// .fetchSource(new String[]{"id","title"},new String[]{}); // 参数 1:包含字段数组 2:排除字段数组
.highlighter(highlightBuilder); // 高亮搜索
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数" + searchResponse.getHits().getTotalHits().value);
System.out.println("最大得分" + searchResponse.getHits().getMaxScore());
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
// 获取高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("description")) {
System.out.println(highlightFields.get("description").getFragments()[0]);
}
if (highlightFields.containsKey("title")) {
System.out.println(highlightFields.get("title").getFragments()[0]);
}
}
}
对比 kibana
GET /products/_search
{
"query": {
"match": {
"description": "iphone"
}
},
"from": 0,
"size": 10,
"sort": [
{
"price": {
"order": "asc"
}
}
],
"_source": ["id","title"],
"highlight": {
"require_field_match": "false",
"pre_tags": ["<span stype='color:red'>"],
"post_tags": ["</span>"],
"fields": {"description": {},"title":{}}
}
}
过滤查询
@Test
public void testFilterQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery())
.postFilter(QueryBuilders.rangeQuery("price").gte(10).lte(6000)); // 用来指定过滤条件
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数" + searchResponse.getHits().getTotalHits().value);
System.out.println("最大得分" + searchResponse.getHits().getMaxScore());
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
}
}
对比 kibana
GET /products/_search
{
"query": {
"match_all": {}
},
"post_filter": {
"range": {
"price": {
"gte": 10,
"lte": 6000
}
}
}
}
实际开发应用
/**
* 将对象放入 ES 中
*/
@Test
public void testIndex() throws IOException {
Product product = new Product();
product.setId(2);
product.setTitle("小浣熊干吃面");
product.setPrice(1.5);
product.setDescription("小浣熊干吃面真好吃!");
product.setCreatedAt(LocalDateTime.now());
IndexRequest indexRequest = new IndexRequest("products");
indexRequest.id(product.getId().toString())
.source(new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(product), XContentType.JSON);
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.status());
}
/**
* 查询数据
*/
@Test
public void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("title").preTags("<span style='color:red'>").postTags("<span>");
sourceBuilder.query(QueryBuilders.prefixQuery("title","小浣熊"))
.from(0)
.size(10)
.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
List<Product> products = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
Product product = new ObjectMapper().registerModule(new JavaTimeModule()).readValue(hit.getSourceAsString(), Product.class);
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("title")) {
product.setTitle(highlightFields.get("title").getFragments()[0].toString());
}
products.add(product);
}
products.forEach(System.out::println);
}
聚合查询
索引以及数据准备
PUT /products
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"id":{
"type": "integer"
},
"category":{
"type": "keyword"
},
"title":{
"type": "text"
},
"price":{
"type": "double"
},
"created_at":{
"type": "date"
},
"description":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
PUT /products/_bulk
{"index":{"_id":1}}
{"id":1,"category":"零食","title":"薯片","price":8.9,"created_at":"2022-05-21","description":"薯片真好吃"}
{"index":{"_id":2}}
{"id":2,"category":"零食","title":"糖","price":4.5,"created_at":"2022-05-21","description":"糖真甜"}
{"index":{"_id":3}}
{"id":3,"category":"饮料","title":"可乐","price":7.0,"created_at":"2022-05-21","description":"2L 可乐"}
{"index":{"_id":4}}
{"id":4,"category":"饮料","title":"椰汁","price":15.0,"created_at":"2022-05-21","description":"1.5L 椰汁"}
{"index":{"_id":5}}
{"id":5,"category":"生活用品","title":"抽纸","price":9.9,"created_at":"2022-05-21","description":"三连包抽纸"}
{"index":{"_id":6}}
{"id":6,"category":"生活用品","title":"电动牙刷","price":199.9,"created_at":"2022-05-21","description":"米家电动牙刷"}
{"index":{"_id":7}}
{"id":7,"category":"生活用品","title":"剃须刀","price":22.5,"created_at":"2022-05-21","description":"手动剃须刀"}
根据字段进行分组查询
GET /products/_search
{
"query": {
"match_all": {}
},
"aggs": {
"price_group": {
"terms": {
"field": "price"
}
}
}
}
public void testGroupAgg() throws IOException {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery()) // 查询条件
.aggregation(AggregationBuilders.terms("price_group").field("price")) // 用来设置聚合处理
.size(0);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
ParsedDoubleTerms parsedDoubleTerms = aggregations.get("price_group");
for (Terms.Bucket bucket : parsedDoubleTerms.getBuckets()) {
System.out.println(bucket.getKey() + " " + bucket.getDocCount());
}
}
GET /products/_search
{
"query": {
"match_all": {}
},
"size": 0,
"aggs": {
"price_sum": {
"sum": {
"field": "price"
}
}
}
}
/**
* max(ParsedMax) min(ParsedMin) sum(ParsedSum) avg(ParsedAvg) 聚合函数,桶中只有一个值
*/
@Test
public void testAggFunction() throws IOException {
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery()) // 查询条件
.aggregation(AggregationBuilders.sum("sum_price").field("price")) // 用来设置聚合处理
.size(0);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
ParsedSum parsedSum = aggregations.get("sum_price");
System.out.println(parsedSum.getValue());
}
本作品采用《CC 协议》,转载必须注明作者和本文链接