ES 聚合索引简介
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES 聚合索引简介相关的知识,希望对你有一定的参考价值。
参考技术A 本章会简单介绍es的聚合索引,通过分析bucket和metric和使用来进一步了解聚合索引。Bucket Aggregation通过字段term对field字段进行桶排序,以上语句含义为:划分到达不同目的地国家的统计。
以上我们看到搜索中hits是为空的,聚合下可以看到以目的地国家为划分的不同的桶
以上通过目的地国家进行分桶,并且对最大,最小,平均值进行了统计计算。
以上我们能看到不同的桶下对三种类型计算产生的输出结果。
本章介绍了聚合,通过两个demo简单介绍了Bucket和Metric两种聚合使用。
Spring Boot Elasticsearch7.6.2实现创建索引删除索引判断索引是否存在获取/添加/删除/更新索引别名单条/批量插入单条/批量更新删除数据递归统计ES聚合的数据
Spring Boot Elasticsearch7.6.2实现创建索引、根据索引名删除索引、根据索引名判断索引是否存在、获取索引对应的别名、为索引添加别名、为索引删除别名、为索引更换别名 旧的换为新的 不会判断旧的是否存在、单条数据插入、批量插入、单条数据更新、根据maps批量更新、根据id删除数据、根据id批量删除数据、递归统计ES聚合的数据
注意:我的版本是elasticsearch7.6.2、spring-boot-starter-data-elasticsearch-2.5.6
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
package com.mar.elasticsearchUtils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Preconditions;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasAction;
import org.springframework.data.elasticsearch.core.index.AliasActionParameters;
import org.springframework.data.elasticsearch.core.index.AliasActions;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.*;
/**
* @author mar
* @date 2021年10月28日 11:34
*/
@Component
@Slf4j
public class EsUtil
private static ElasticsearchRestTemplate elasticsearchRestTemplate;
@Autowired
public EsUtil(ElasticsearchRestTemplate elasticsearchRestTemplate)
EsUtil.elasticsearchRestTemplate = elasticsearchRestTemplate;
public static <T> boolean createIndex(Class<T> destinationClass, String indexName, String... withAliases)
if (ObjectUtil.isNull(destinationClass)) throw new RuntimeException("参数类不能为空");
if (StrUtil.isEmpty(indexName)) throw new RuntimeException("参数名不能为空");
if (withAliases == null || withAliases.length <= 0) throw new RuntimeException("索引别名至少有一个");
for (String withAlias : withAliases)
if (!withAlias.endsWith("_search"))
throw new RuntimeException("索引别名只能以‘_search’结尾");
return createIndex(destinationClass, indexName, 3, 2, Integer.MAX_VALUE, withAliases);
/**
* 创建索引
*
* @param destinationClass 映射对象
* @param withAliases 别名 必须如:"***_search"用来搜索
* @author mar
* @date 2021/10/28 14:54
*/
public static <T> boolean createIndex(Class<T> destinationClass, String indexName, Integer shards, Integer replicas, Integer maxResult, String... withAliases)
if (ObjectUtil.isNull(destinationClass)) throw new RuntimeException("参数类不能为空");
if (StrUtil.isEmpty(indexName)) throw new RuntimeException("参数名不能为空");
if (withAliases == null || withAliases.length <= 0) throw new RuntimeException("索引别名至少有一个");
for (String withAlias : withAliases)
if (!withAlias.endsWith("_search"))
throw new RuntimeException("索引别名只能以‘_search’结尾");
IndexCoordinates of = IndexCoordinates.of(indexName);
IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(of);
boolean exists = indexOperations.exists();
if (exists)
indexOperations.delete();
Map<String, Object> settings = new HashMap<>();
settings.put("index.number_of_shards", shards > 0 ? shards : 3);
settings.put("index.number_of_replicas", replicas > 0 ? replicas : 2);
settings.put("index.max_result_window", maxResult > 0 ? maxResult : Integer.MAX_VALUE);
Document mapping = indexOperations.createMapping(destinationClass);
indexOperations.create(settings, mapping);
AliasAction.Add add = new AliasAction.Add(AliasActionParameters.builder()
.withIndices(indexName).withAliases(withAliases).build());
return indexOperations.alias(new AliasActions(add));
/**
* 根据索引名删除索引
*
* @param indexName 索引名称
* @author mar
* @date 2021/10/28 16:29
*/
public static boolean deleteIndexByName(String indexName)
return elasticsearchRestTemplate.indexOps(IndexCoordinates.of(indexName)).delete();
/**
* 根据索引名判断索引是否存在
*
* @param indexName
* @return boolean
* @author mar
* @date 2021/11/29 16:39
*/
public static boolean isExists(String indexName)
IndexCoordinates of = IndexCoordinates.of(indexName);
return elasticsearchRestTemplate.indexOps(of).exists();
/**
* 获取索引对应的别名
*/
public static Set<String> getAlias(String index)
if (StrUtil.isEmpty(index)) throw new RuntimeException("索引名不能为空");
Map<String, Set<AliasData>> aliasesForIndex = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(index)).getAliasesForIndex();
Set<String> set = new HashSet<>();
aliasesForIndex.forEach((key, value) ->
value.forEach(data -> set.add(data.getAlias()));
);
return set;
/**
* 为索引添加别名
*
* @param index 真实索引
* @param alias 别名
*/
public static boolean addAlias(String index, String... alias)
Preconditions.checkNotNull(index);
Preconditions.checkNotNull(alias);
final IndexOperations indexOps = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(index));
AliasActions aliasActions = new AliasActions(new AliasAction.Add(
AliasActionParameters.builder().withIndices(index).withAliases(alias).build()
));
return indexOps.alias(aliasActions);
/**
* 为索引删除别名
*
* @param index 真实索引
* @param alias 别名
*/
public static boolean delAlias(String index, String... alias)
Preconditions.checkNotNull(index);
Preconditions.checkNotNull(alias);
final IndexOperations indexOps = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(index));
AliasActions aliasActions = new AliasActions(new AliasAction.Remove(
AliasActionParameters.builder().withIndices(index).withAliases(alias).build()
));
return indexOps.alias(aliasActions);
/**
* 为索引更换别名 旧的换为新的 不会判断旧的是否存在
*
* @param index 真实索引
* @param oldAlias 要删除的别名
* @param newAlias 要新增的别名
*/
public static boolean replaceAlias(String index, String oldAlias, String newAlias)
Preconditions.checkNotNull(index);
Preconditions.checkNotNull(oldAlias);
Preconditions.checkNotNull(newAlias);
final IndexOperations indexOps = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(index));
final AliasAction.Add add = new AliasAction.Add(AliasActionParameters.builder().withIndices(index).withAliases(newAlias).build());
final AliasAction.Remove remove = new AliasAction.Remove(AliasActionParameters.builder().withIndices(index).withAliases(oldAlias).build());
AliasActions aliasActions = new AliasActions(add, remove);
return indexOps.alias(aliasActions);
/**
* 单条数据插入
*
* @param t 待插入的数据实体
* @param indexName 索引名
* @return java.lang.String 返回文档id
*/
public static <T> void saveByEntity(T t, String indexName)
//这里的操作就是指定文档id
String id = getFieldId(t);
IndexQuery build = new IndexQueryBuilder()
.withId(id)
.withObject(t).build();
elasticsearchRestTemplate.index(build, IndexCoordinates.of(indexName));
public static <T> void saveBatchByEntities(Map<String, List<T>> map)
if (map != null && map.size() > 0)
map.forEach((key, value) -> saveBatchByEntities(value, key));
/**
* 批量插入
*
* @param sourceList 待插入的数据实体集合
* @param indexName 索引名
* @return java.util.List<java.lang.String> 返回idList
*/
public static <T> void saveBatchByEntities(List<T> sourceList, String indexName)
List<IndexQuery> queryList = new ArrayList<>();
for (T source : sourceList)
String id = getFieldId(source);
IndexQuery build = new IndexQueryBuilder().withId(id).withObject(source).build();
queryList.add(build);
elasticsearchRestTemplate.bulkIndex(queryList, IndexCoordinates.of(indexName));
/**
* 单条数据更新
*
* @param entity 待更新的数据实体
* @param indexName 索引名
* @return void
*/
public static <T> void updateByEntity(T entity, String indexName)
String id = getFieldId(entity);
Map<String, String> map = null;
try
map = BeanUtils.describe(entity);
catch (Exception e)
e.printStackTrace();
Document document = Document.from(map);
document.setId(id);
// 这里的UpdateQuery需要构造一个Document对象,但是Document对象不能用实体类转化而来
//(可见Document的源码,位于:org.springframework.data.elasticsearch.core.document
// 包下),因此上面才会BeanUtils.describe(entity),将实体类转化成一个map,由map转化
// 为Document对象。
//不加默认false。true表示更新时不存在就插入
UpdateQuery build = UpdateQuery.builder(id)
.withDocAsUpsert(false)
.withDocument(document)
.build();
elasticsearchRestTemplate.update(build, IndexCoordinates.of(indexName));
/**
* 根据maps批量更新
*
* @param list 待更新的数据实体集合
* @param indexName 索引名
* @return void
* @author Innocence
*/
public static <T> void updateByMaps(List<T> list, String indexName)
List<Map<String, Object>> maps = listToMap(list);
List<UpdateQuery> updateQueries = new ArrayList<>();
maps.forEach(item ->
Document document = 以上是关于ES 聚合索引简介的主要内容,如果未能解决你的问题,请参考以下文章