Elasticsearch 支持对多种类型的字段进行分组(桶聚合)、指标聚合和排序,以下是详细分类:
一、适合聚合和排序的字段类型
1. 关键字类型
- keyword:最适合聚合和排序
java
{
"field": "status.keyword",
"size": 10,
"order": { "_count": "desc" }
}
- constant_keyword:恒定值关键词
- wildcard:通配符关键词(有限聚合支持)
2. 数值类型
- 整数型:byte, short, integer, long
- 浮点型:float, double, half_float, scaled_float
- 特殊数值:unsigned_long
3. 日期类型
- date:支持按时间间隔聚合
java
{
"date_histogram": {
"field": "created_at",
"calendar_interval": "month"
}
}
4. 布尔类型
- boolean:true/false 分组
5. IP类型
- ip:支持IP范围聚合
6. 范围类型
- integer_range, float_range, date_range, ip_range
7. 地理类型
- geo_point:地理距离聚合
- geo_shape:地理形状聚合
二、有限支持聚合和排序的字段类型
1. 文本类型(text)
- 默认不支持聚合和排序(分词后)
- 需要通过以下方式:
java
// 1. 使用keyword子字段
{
"aggs": {
"by_category": {
"terms": {
"field": "category.keyword" // 必须使用.keyword
}
}
}
}
// 2. 开启fielddata(不推荐,消耗大)
"mappings": {
"properties": {
"title": {
"type": "text",
"fielddata": true
}
}
}
2. 对象和嵌套类型
- object:可对子字段聚合
- nested:需要特殊处理,使用nested聚合
三、聚合类型分类
1. 桶聚合(分组)
java
{
"aggs": {
// 词项聚合
"by_status": {
"terms": { "field": "status.keyword" }
},
// 范围聚合
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100 },
{ "from": 100, "to": 500 },
{ "from": 500 }
]
}
},
// 直方图聚合
"price_histogram": {
"histogram": {
"field": "price",
"interval": 100
}
},
// 日期直方图
"by_date": {
"date_histogram": {
"field": "timestamp",
"calendar_interval": "day"
}
}
}
}
2. 指标聚合
java
{
"aggs": {
"avg_price": { "avg": { "field": "price" } },
"total_sales": { "sum": { "field": "sales" } },
"max_score": { "max": { "field": "score" } },
"min_price": { "min": { "field": "price" } },
"unique_users": { "cardinality": { "field": "user_id" } },
"stats_price": { "stats": { "field": "price" } }
}
}
四、排序支持
1. 排序字段类型
java
{
"sort": [
// 数值字段排序
{ "price": { "order": "desc" } },
// 日期字段排序
{ "created_at": { "order": "asc" } },
// 关键词字段排序
{ "category.keyword": { "order": "asc" } },
// 多级排序
{ "priority": "desc" },
{ "_score": "desc" }
]
}
2. 聚合结果排序
java
{
"aggs": {
"popular_categories": {
"terms": {
"field": "category.keyword",
"order": [
{ "_count": "desc" }, // 按文档数排序
{ "_key": "asc" } // 按关键词字母排序
]
}
}
}
}
五、实际应用示例
电商数据分析
java
{
"size": 0,
"aggs": {
"sales_by_category": {
"terms": {
"field": "category.keyword",
"size": 10,
"order": { "total_sales": "desc" }
},
"aggs": {
"total_sales": { "sum": { "field": "amount" } },
"avg_price": { "avg": { "field": "price" } },
"sales_trend": {
"date_histogram": {
"field": "order_date",
"calendar_interval": "month"
}
}
}
}
}
}
六、注意事项
1.文本字段 :必须使用 .keyword 子字段或开启 fielddata
2.内存限制 :大基数字段聚合可能消耗大量内存
3.精度问题:
- terms 聚合默认返回前10项
- 使用 "size": 100 获取更多结果
- 使用 "show_term_doc_count_error": true 检查精度
4.性能优化:- 对聚合字段使用 eager_global_ordinals
- 使用 keyword 替代 text 进行精确值聚合
总结建议
| 操作类型 | 推荐字段类型 | 注意事项 |
|---|---|---|
| 分组聚合 | keyword, integer, date | 文本字段需用 .keyword |
| 数值计算 | integer, float, double | 注意精度问题 |
| 时间分析 | date | 支持各种时间间隔 |
| 地理分析 | geo_point | 用于距离和地理聚合 |
| 精确排序 | keyword, 数值类型, date | 避免对 text 类型排序 |
选择字段类型时,应根据查询、聚合、排序的综合需求来设计映射,经常用于聚合和排序的字段应优先选择 keyword、数值或日期类型。