Elasticsearch字段类型聚合排序指南

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、数值或日期类型。

相关推荐
盖世英雄酱581364 小时前
不是所有的this调用会导致事务失效
java·后端
少许极端4 小时前
Redis入门指南(五):从零到分布式缓存-其他类型及Java客户端操作redis
java·redis·分布式·缓存
宠..5 小时前
优化文件结构
java·服务器·开发语言·前端·c++·qt
sheji34165 小时前
【开题答辩全过程】以 疫情物资捐赠系统为例,包含答辩的问题和答案
java
sinat_255487815 小时前
InputStream/OutputStream小讲堂
java·数据结构·算法
乌日尼乐5 小时前
【Java基础整理】java数组详解
java·后端
tkevinjd5 小时前
IO流6(转换流、序列化与反序列化流)
java
虫小宝5 小时前
导购类电商平台搜索推荐融合:基于用户行为的个性化导购系统
java
微露清风6 小时前
系统性学习C++-第十六讲-AVL树实现
java·c++·学习
Hui Baby6 小时前
saga json文件阅读
java·前端·数据库