十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合

Elasticsearch 8.x 分布式搜索引擎 -数据聚合

    • 一、聚合简介
    • 二、`聚合种类`
      • 1、`桶(Bucket)`聚合:
        • 1)**TermAggregation:**
        • 2)**Date Histogram:**
      • 2、`度量(Metric)`聚合:
        • 1)**Avg**:求平均值
        • 2)**Max**:求最大值
        • 3)**Min**:求最小值
        • 3)**Stats**:同时求max、min、avg、sum等
      • 3、`管道(pipeline)`聚合:
    • 三、DSL实现聚合
      • 1、Bucket聚合语法
      • 2、聚合结果排序
      • 3、限定聚合范围
      • 4、Metric聚合语法
      • 5、Metric聚合语法,嵌套聚合排序
      • 6、小结
    • 四、`ElasticsearchClient`聚合查询
      • 1、Bucket聚合语法, term文档聚合
        • 1)在`EsClient`添加`aggregationsTerms`方法实现Bucket聚合语法, term文档聚合
        • 2) `ESAggregationeditTest`测试类中,测试Bucket聚合语法, term文档聚合
      • 2、Bucket聚合语法, 聚合排序
        • 1)在`EsClient`添加`aggregationsTermsSort`方法实现Bucket聚合语法, 聚合排序
        • 2) `ESAggregationeditTest`测试类中,测试Bucket聚合语法, term文档聚合
      • 3、Bucket聚合语法, 限定聚合范围
        • 1)在`EsClient`添加`queryRangeAggregationsTerms`方法实现Bucket聚合语法, 限定聚合范围
        • 2) `ESAggregationeditTest`测试类中,测试Bucket聚合语法, 限定聚合范围
      • 4、聚合查询优化
        • 1)在`EsClient`添加`queryAggregations`方法实现通用聚合语法-1
        • 2) `ESAggregationeditTest`测试类中,测试通用聚合语法-1
        • 3)在`EsClient`添加`queryAggregations`方法实现通用聚合语法-2
        • 2) `ESAggregationeditTest`测试类中,测试通用聚合语法-2

一、聚合简介

聚合 aggregationedit 可以让我们极其方便的实现对数据的统计、分析、运算。例如:

  • 什么品牌的手机最受欢迎?
  • 这些手机的平均价格、最高价格、最低价格?
  • 这些手机每月的销售情况如何?

实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

二、聚合种类

聚合常见的有三类

1、桶(Bucket)聚合:

桶(Bucket)聚合: 用来对文档做分组

1)TermAggregation:

按照文档字段值分组,例如按照品牌值分组、按照国家分组

2)Date Histogram:

按照日期阶梯分组,例如一周为一组,或者一月为一组

2、度量(Metric)聚合:

度量(Metric)聚合用: 以计算一些值,比如:最大值、最小值、平均值等

1)Avg:求平均值

2)Max:求最大值

3)Min:求最小值

3)Stats:同时求max、min、avg、sum等

3、管道(pipeline)聚合:

管道(pipeline)聚合:其它聚合的结果为基础做聚合

**注意:**参加聚合的字段必须是keyword、日期、数值、布尔类型

三、DSL实现聚合

1、Bucket聚合语法

语法

GET /索引库名/_search
{
  "size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
  "aggs": {  // 定义聚合
    "NAME": {  //给聚合起个名字
      "AGG_TYPE": {  // 聚合的类型
        "field": "brand", // 参与聚合的字段
        "size": 20  // 希望获取的聚合结果数量
      }
    }
  }
}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第1张图片

2、聚合结果排序

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。
语法

GET /索引库名/_search
{
  "size": 0, 
  "aggs": {  // 定义聚合
    "NAME": {  //给聚合起个名字
      "AGG_TYPE": {  // 聚合的类型
        "field": "brand", // 参与聚合的字段
        "size": 20,  // 希望获取的聚合结果数量
        "order": {
          "_count": "asc" // asc升序排列 desc降序排序
        }
      }
    }
  }
}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第2张图片

3、限定聚合范围

默认情况下,Bucket聚合是对索引库的所有文档做聚合,但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。
语法

GET /索引库名/_search
{
  "query": {
    "range": {
      "price": {
        "lte": 200 // 只对200元以下的文档聚合
      }
    }
  }, 
  "size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
  "aggs": {  // 定义聚合
    "NAME": {  //给聚合起个名字
      "AGG_TYPE": {  // 聚合的类型
        "field": "brand", // 参与聚合的字段
        "size": 20  // 希望获取的聚合结果数量
      }
    }
  }
}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第3张图片

4、Metric聚合语法

语法

GET /索引/_search
{
  "size": 0,
  "aggs": {
    "NAME": {
      "AGG_TYPE": {
        "field": "fieldName",
        "size":10
      },
      "aggs": {
        "NAME": {
          "AGG_TYPE": {
            "field": "fieldName",
          }
        }
      }
    }
  }
}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第4张图片

5、Metric聚合语法,嵌套聚合排序

GET /hotel/_search
{
  "size": 0,
  "aggs": {
    "brandAgg": {
      "terms": {
        "field": "brand",
        "size": 20,
        "order": {
          "rating_stats.avg": "desc"
        }
      },
      "aggs": {
        "rating_stats": {
          "stats": {
            "field": "rating"
          }
        }
      }
    }
  }
}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第5张图片

6、小结

aggs代表聚合,与query同级,此时query的作用是?

  • 限定聚合的的文档范围

聚合必须的三要素:

  • 聚合名称
  • 聚合类型
  • 聚合字段

聚合可配置属性有:

  • size:指定聚合结果数量
  • order:指定聚合结果排序方式
  • field:指定聚合字段

四、ElasticsearchClient聚合查询

1、Bucket聚合语法, term文档聚合

1)在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();
	}

2) 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);
			}
		}
	}
}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第6张图片

2、Bucket聚合语法, 聚合排序

1)在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();
	}

2) 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);
			}
		}
	}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第7张图片

3、Bucket聚合语法, 限定聚合范围

1)在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();
	}

2) 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);
			}
		}

	}

十一、Elasticsearch 8.x 分布式搜索引擎 -3-数据聚合_第8张图片

4、聚合查询优化

1)在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();
	}

2) 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);
			}
		}
	}

3)在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();
	}

2) 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);
			}
		}
	}

你可能感兴趣的:(#,搜索引擎,搜索引擎,elasticsearch,分布式,全文检索)