Elasticsearch实战:从简单查询到聚合统计的完整指南(附代码示例)
在数据驱动的时代,Elasticsearch(简称ES)已经成为处理海量数据的首选工具之一。无论是电商平台的商品搜索、日志分析系统,还是金融领域的风控模型,ES都能提供高效的查询和聚合能力。本文将带你从基础查询出发,逐步深入到复杂的聚合统计,通过实际代码示例展示如何在不同业务场景中灵活运用ES的核心功能。
1. 基础查询:快速定位目标数据
ES的基础查询是每个开发者必须掌握的技能。与传统的数据库查询不同,ES提供了更灵活、更强大的查询方式。让我们从一个简单的订单查询开始:
POST order_index/_search { "query": { "term": { "user": "liubei" } } }这个查询会返回所有user字段精确匹配"liubei"的文档。在实际应用中,我们通常还需要控制返回结果的数量和偏移量:
POST order_index/_search { "query": { "term": { "user": "liubei" } }, "from": 0, "size": 10 }注意:from和size参数对于分页查询至关重要,但当数据量非常大时,深分页可能会影响性能。
1.1 查询类型对比
ES提供了多种查询类型,适用于不同场景:
| 查询类型 | 适用场景 | 特点 |
|---|---|---|
| term | 精确匹配 | 不分析查询词,完全匹配 |
| match | 全文搜索 | 会分析查询词,支持模糊匹配 |
| prefix | 前缀匹配 | 匹配以指定词开头的文档 |
| wildcard | 通配符匹配 | 支持*和?等通配符 |
| range | 范围查询 | 适用于数字、日期等范围查询 |
2. 排序与分页:优化结果展示
查询结果的排序直接影响用户体验。ES支持对单个或多个字段进行排序:
POST order_index/_search { "sort": [ { "createTime": { "order": "desc" } } ], "from": 0, "size": 10 }在实际项目中,我们可能需要更复杂的排序逻辑。例如,电商平台可能希望优先展示库存充足的商品,同时考虑销量和评分:
POST product_index/_search { "sort": [ { "inStock": { "order": "desc" } }, { "sales": { "order": "desc" } }, { "rating": { "order": "desc" } } ] }提示:对于文本字段排序,建议使用
keyword类型而非text类型,因为text类型会被分析,可能导致排序结果不符合预期。
3. 组合查询:构建复杂搜索条件
现实业务中的查询需求往往比简单的单条件查询复杂得多。ES的bool查询允许我们组合多个查询条件:
POST order_index/_search { "query": { "bool": { "must": { "match": { "title": "quick" } }, "must_not": { "match": { "title": "lazy" } }, "should": [ { "match": { "title": "brown" } }, { "match": { "title": "dog" } } ] } } }这个查询的含义是:
- 必须包含"quick"
- 不能包含"lazy"
- 最好包含"brown"或"dog"
在实际的电商搜索中,我们可能需要这样的查询逻辑:
POST product_index/_search { "query": { "bool": { "must": [ { "match": { "category": "electronics" } }, { "range": { "price": { "gte": 100, "lte": 1000 } } } ], "should": [ { "match": { "name": "wireless" } }, { "match": { "description": "bluetooth" } } ], "minimum_should_match": 1 } } }4. 聚合统计:从数据中提取洞察
聚合是ES最强大的功能之一,它允许我们对数据进行统计分析。让我们从简单的聚合开始:
POST order_index/_search { "aggs": { "sum_amount": { "sum": { "field": "amount" } } } }这个查询会计算所有订单金额的总和。我们还可以结合查询条件进行聚合:
POST order_index/_search { "query": { "term": { "user": "liubei" } }, "aggs": { "max_amount": { "max": { "field": "amount" } } } }4.1 分组统计
分组统计是业务分析中最常用的功能之一。例如,统计各产品在一季度的销量:
POST order_index/_search { "query": { "range": { "create_time": { "gte": "2020-01-01", "lt": "2020-04-01" } } }, "aggs": { "max_eday": { "terms": { "field": "product_id", "order": { "_key": "asc" } } } } }对于更复杂的分组需求,可以使用脚本进行多字段聚合:
POST order_index/_search { "query": { "range": { "create_time": { "gte": "2020-01-01", "lt": "2020-04-01" } } }, "aggs": { "max_eday": { "terms": { "script": "doc['code'].values[0] + '/' + doc['name'].values[0]", "order": { "_key": "asc" }, "size": 2000 } } } }4.2 高级聚合函数
ES提供了丰富的高级聚合函数,可以一次性获取多个统计指标:
POST order_index/_search { "aggs": { "age_count": { "stats": { "field": "age" } } } }这个查询会返回count、max、min、avg和sum五个统计值。如果需要更详细的统计信息,可以使用extended_stats:
POST order_index/_search { "aggs": { "age_count": { "extended_stats": { "field": "age" } } } }4.3 自定义脚本聚合
对于特殊的业务需求,我们可以使用脚本进行自定义聚合计算:
POST order_index/_search { "aggs": { "sum_amount": { "sum": { "field": "amount", "script": { "source": "_value * 1.03" } } } } }这个查询会在计算金额总和时,对每个值乘以1.03(例如考虑3%的税费)。