聚合 aggregationedit 可以让我们极其方便的实现对数据的统计、分析、运算。例如:
实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。
聚合种类
聚合常见的有三类
桶(Bucket)
聚合:桶(Bucket)聚合: 用来对文档做分组
按照文档字段值分组,例如按照品牌值分组、按照国家分组
按照日期阶梯分组,例如一周为一组,或者一月为一组
度量(Metric)
聚合:度量(Metric)聚合用: 以计算一些值,比如:最大值、最小值、平均值等
管道(pipeline)
聚合:管道(pipeline)聚合:其它聚合的结果为基础做聚合
**注意:**参加聚合的字段必须是keyword、日期、数值、布尔类型
语法
GET /索引库名/_search
{
"size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
"aggs": { // 定义聚合
"NAME": { //给聚合起个名字
"AGG_TYPE": { // 聚合的类型
"field": "brand", // 参与聚合的字段
"size": 20 // 希望获取的聚合结果数量
}
}
}
}
默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。
语法
GET /索引库名/_search
{
"size": 0,
"aggs": { // 定义聚合
"NAME": { //给聚合起个名字
"AGG_TYPE": { // 聚合的类型
"field": "brand", // 参与聚合的字段
"size": 20, // 希望获取的聚合结果数量
"order": {
"_count": "asc" // asc升序排列 desc降序排序
}
}
}
}
}
默认情况下,Bucket聚合是对索引库的所有文档做聚合,但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。
语法
GET /索引库名/_search
{
"query": {
"range": {
"price": {
"lte": 200 // 只对200元以下的文档聚合
}
}
},
"size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
"aggs": { // 定义聚合
"NAME": { //给聚合起个名字
"AGG_TYPE": { // 聚合的类型
"field": "brand", // 参与聚合的字段
"size": 20 // 希望获取的聚合结果数量
}
}
}
}
语法
GET /索引/_search
{
"size": 0,
"aggs": {
"NAME": {
"AGG_TYPE": {
"field": "fieldName",
"size":10
},
"aggs": {
"NAME": {
"AGG_TYPE": {
"field": "fieldName",
}
}
}
}
}
}
GET /hotel/_search
{
"size": 0,
"aggs": {
"brandAgg": {
"terms": {
"field": "brand",
"size": 20,
"order": {
"rating_stats.avg": "desc"
}
},
"aggs": {
"rating_stats": {
"stats": {
"field": "rating"
}
}
}
}
}
}
aggs代表聚合,与query同级,此时query的作用是?
聚合必须的三要素:
聚合可配置属性有:
ElasticsearchClient
聚合查询EsClient
添加aggregationsTerms
方法实现Bucket聚合语法, term文档聚合public Map<String, Aggregate> aggregationsTerms(String indexName, String aggName, String field, int aggSize) {
SearchResponse<Void> response = null;
try {
response = elasticsearchClient.search(s -> s
.index(indexName)
.size(0)
.aggregations(aggName, a -> a
.terms(t -> t
.field(field)
.size(aggSize)
)
),
Void.class
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return response.aggregations();
}
ESAggregationeditTest
测试类中,测试Bucket聚合语法, term文档聚合@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApplication.class)
public class ESAggregationeditTest {
@Autowired
private EsClient esClient;
@Resource
private ElasticsearchClient elasticsearchClient;
@Test
public void bucketTest01() {
Map<String, Aggregate> aggregateMap = esClient.aggregationsTerms("hotel","brandAgg","brand",20);
for (String key : aggregateMap.keySet()) {
List<StringTermsBucket> termsBucketList = aggregateMap.get(key).sterms().buckets().array();
for (StringTermsBucket stringTermsBucket : termsBucketList) {
System.out.println(key +" = " + stringTermsBucket);
}
}
}
}
EsClient
添加aggregationsTermsSort
方法实现Bucket聚合语法, 聚合排序public Map<String, Aggregate> aggregationsTermsSort(String indexName,String aggName,String field,int aggSize,Map<String, SortOrder> sort, Map<String, SortOrder>... sorts){
SearchResponse<Void> response = null;
try {
response = elasticsearchClient.search(s -> s
.index(indexName)
.size(0)
.aggregations(aggName, a -> a
.terms(t -> t
.field(field)
.size(aggSize)
.order(sort,sorts)
)
),
Void.class
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return response.aggregations();
}
ESAggregationeditTest
测试类中,测试Bucket聚合语法, term文档聚合@Test
public void aggregationsTermsSortTest() {
HashMap<String, SortOrder> sortMap = new HashMap<>();
sortMap.put("_count", SortOrder.Asc);
Map<String, Aggregate> aggregateMap = esClient.aggregationsTermsSort("hotel", "brandAgg", "brand", 20, sortMap);
for (String key : aggregateMap.keySet()) {
List<StringTermsBucket> termsBucketList = aggregateMap.get(key).sterms().buckets().array();
for (StringTermsBucket stringTermsBucket : termsBucketList) {
System.out.println(key +" = " + stringTermsBucket);
}
}
}
EsClient
添加queryRangeAggregationsTerms
方法实现Bucket聚合语法, 限定聚合范围 public Map<String, Aggregate> queryRangeAggregationsTerms(String indexName,Query query,String aggName,String aggField,int aggSize) {
SearchResponse<Void> response = null;
try {
response = elasticsearchClient.search(s -> s
.query(query)
.index(indexName)
.size(0)
.aggregations(aggName, a -> a
.terms(t -> t
.field(aggField)
.size(aggSize)
)
),
Void.class
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return response.aggregations();
}
ESAggregationeditTest
测试类中,测试Bucket聚合语法, 限定聚合范围@Test
public void bucketTest03() {
Query rangeQuery = QueryBuilders.range(r -> r.field("price").lte(JsonData.of(200)));
Map<String, Aggregate> aggregateMap =esClient.queryRangeAggregationsTerms("hotel",rangeQuery ,"brandAgg", "brand", 20);
for (String key : aggregateMap.keySet()) {
List<StringTermsBucket> termsBucketList = aggregateMap.get(key).sterms().buckets().array();
for (StringTermsBucket stringTermsBucket : termsBucketList) {
System.out.println(key +" = " + stringTermsBucket);
}
}
}
EsClient
添加queryAggregations
方法实现通用聚合语法-1 public Map<String, Aggregate> queryAggregations(String indexName,Query query,Map<String, Aggregation> aggregationMap) {
SearchResponse<Void> response = null;
try {
response = elasticsearchClient.search(s -> s
.query(query)
.index(indexName)
.size(0)
.aggregations(aggregationMap),
Void.class
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return response.aggregations();
}
ESAggregationeditTest
测试类中,测试通用聚合语法-1 @Test
public void queryAggregationsTest() {
Map<String, Aggregation> aggregationMap = new HashMap<>();
Aggregation brandAggregation = AggregationBuilders.terms(t -> t.field("brand").size(20));
aggregationMap.put("brandAgg", brandAggregation);
Query rangeQuery = QueryBuilders.range(r -> r.field("price").lte(JsonData.of(200)));
Map<String, Aggregate> aggregateMap = esClient.queryAggregations("hotel", rangeQuery, aggregationMap);
for (String key : aggregateMap.keySet()) {
List<StringTermsBucket> termsBucketList = aggregateMap.get(key).sterms().buckets().array();
for (StringTermsBucket stringTermsBucket : termsBucketList) {
System.out.println(key +" = " + stringTermsBucket);
}
}
}
EsClient
添加queryAggregations
方法实现通用聚合语法-2 public Map<String, Aggregate> queryAggregations(String indexName,Map<String, Aggregation> aggregationMap) {
SearchResponse<Void> response = null;
try {
response = elasticsearchClient.search(s -> s
.index(indexName)
.size(0)
.aggregations(aggregationMap),
Void.class
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return response.aggregations();
}
ESAggregationeditTest
测试类中,测试通用聚合语法-2 @Test
public void aggregationsTest() {
Map<String, Aggregation> aggregationMap = new HashMap<>();
Aggregation brandAggregation = AggregationBuilders.terms(t -> t.field("brand").size(20));
aggregationMap.put("brandAgg", brandAggregation);
Map<String, Aggregate> aggregateMap = esClient.queryAggregations("hotel", aggregationMap);
for (String key : aggregateMap.keySet()) {
List<StringTermsBucket> termsBucketList = aggregateMap.get(key).sterms().buckets().array();
for (StringTermsBucket stringTermsBucket : termsBucketList) {
System.out.println(key +" = " + stringTermsBucket);
}
}
}