面试题答案
一键面试实现步骤
- 桶聚合(Terms Aggregation):使用
terms
聚合按照brand
进行分组,即折叠操作。
{
"aggs": {
"by_brand": {
"terms": {
"field": "brand",
"size": 10000
}
}
}
}
这里 size
可根据实际品牌数量调整,确保能获取所有品牌。
- 子聚合 - 过滤(Filter Aggregation):在每个品牌桶内,使用
filter
聚合筛选评分大于4分的商品。
{
"aggs": {
"by_brand": {
"terms": {
"field": "brand",
"size": 10000
},
"aggs": {
"high_rating": {
"filter": {
"range": {
"rating": {
"gt": 4
}
}
}
}
}
}
}
}
- 子聚合 - Top Hits 结合 Percentiles Bucket Aggregation:
- 先使用
percentiles_bucket
聚合计算出价格前10% 的阈值。 - 再用
top_hits
聚合根据阈值筛选出价格前10% 的商品。
- 先使用
{
"aggs": {
"by_brand": {
"terms": {
"field": "brand",
"size": 10000
},
"aggs": {
"high_rating": {
"filter": {
"range": {
"rating": {
"gt": 4
}
}
},
"aggs": {
"price_threshold": {
"percentiles_bucket": {
"field": "price",
"percents": [90]
}
},
"top_products": {
"top_hits": {
"sort": [
{
"price": {
"order": "desc"
}
}
],
"size": 10000,
"script": {
"source": "doc['price'].value >= params.threshold",
"params": {
"threshold": 0
}
}
},
"aggs": {
"set_threshold": {
"bucket_script": {
"buckets_path": {
"threshold": "price_threshold>90.0"
},
"script": "params.threshold"
}
}
}
}
}
}
}
}
}
}
这里 top_hits
的 size
可根据实际情况调整,确保能获取足够多商品来筛选前10%。
可能用到的ElasticSearch特性
- 聚合(Aggregation):包括
terms
聚合用于分组,filter
聚合用于筛选条件,percentiles_bucket
聚合用于计算百分位数,top_hits
聚合用于获取符合条件的文档。 - 脚本(Scripting):在
top_hits
聚合中使用脚本,根据计算出的价格阈值筛选商品。
性能瓶颈及优化方向
-
性能瓶颈:
- 数据量过大:大量商品信息可能导致聚合计算量巨大,尤其是在计算百分位数和筛选文档时。
- 深分页问题:如果
top_hits
的size
设置过大,可能会导致深分页问题,影响性能。 - 脚本计算:脚本计算会增加额外的 CPU 开销。
-
优化方向:
- 数据预处理:在数据写入 ElasticSearch 时,可以对数据进行一些预处理,如计算并存储价格区间等信息,减少实时计算量。
- 分页优化:采用滚动(Scroll)或者搜索后下一页(Search After)的方式代替深分页,减少内存和性能消耗。
- 缓存:对于一些不经常变化的品牌数据,可以使用缓存来减少 ElasticSearch 的查询压力。
- 硬件优化:如果可能,增加服务器资源,如 CPU、内存等,以提高 ElasticSearch 的处理能力。