以 模拟电商商品数据 为例,介绍如何使用 Elasticsearch 进行聚合查询和多维度数据统计。

准备工作

生成index

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PUT /test
{
"mappings": {
"properties": {
"brand": {
"type": "keyword"
},
"color": {
"type": "keyword"
},
"price": {
"type": "float"
},
"sold": {
"type": "integer"
}
}
}
}

插入数据

1
2
3
4
5
6
7
8
9
10
11
POST /_bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "brand" : "A", "color" : "red", "price" : 100, "sold" : 10 }
{ "index" : { "_index" : "test", "_id" : "2" } }
{ "brand" : "B", "color" : "blue", "price" : 200, "sold" : 20 }
{ "index" : { "_index" : "test", "_id" : "3" } }
{ "brand" : "C", "color" : "green", "price" : 300, "sold" : 30 }
{ "index" : { "_index" : "test", "_id" : "4" } }
{ "brand" : "D", "color" : "yellow", "price" : 400, "sold" : 40 }
{ "index" : { "_index" : "test", "_id" : "5" } }
{ "brand" : "E", "color" : "black", "price" : 500, "sold" : 50 }

聚合查询

求和

1
2
3
4
5
6
7
8
9
10
11
POST /test/_search
{
"size": 0,
"aggs": {
"total_sales": {
"sum": {
"field": "sold"
}
}
}
}

平均值

1
2
3
4
5
6
7
8
9
10
11
POST /test/_search
{
"size": 0,
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}

根据字段分组求和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /test/_search
{
"size": 0,
"aggs": {
"group_by_brand": {
"terms": {
"field": "brand"
},
"aggs": {
"total_sales": {
"sum": {
"field": "sold"
}
}
}
}
}
}

根据颜色分组求平均值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST /test/_search
{
"size": 0,
"aggs": {
"group_by_color": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}

多ranges分组求对应数量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /test/_search
{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{
"from": 0,
"to": 200
},
{
"from": 200,
"to": 400
},
{
"from": 400
}
]
}
}
}
}

多维度查询数据

查询价格在0到1999之间,销量在0到99之间,颜色为蓝色,品牌为2的产品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /test/_search
{
"query": {
"bool": {
"must": [
{ "range": { "price": { "gte": 0, "lt": 1999 } } },
{ "range": { "sold": { "gte": 0, "lt": 100 } } },
{ "term": { "color": "blue" } },
{ "term": { "brand": "2" } }
]
}
},
"_source": ["price", "color", "brand"]
}

查询到的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"took": 13,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 4.7725887,
"hits": [
{
"_index": "test",
"_id": "2",
"_score": 4.7725887,
"_source": {
"brand": "B",
"color": "blue",
"price": 200
}
}
]
}
}

字段解释

  1. "took": 13: 表示该请求的处理时间为13毫秒。

  2. "timed_out": false: 表示请求没有超时,即成功执行。

  3. "_shards": 是有关Elasticsearch分片的信息。

    • "total": 1: 总共有1个分片。
    • "successful": 1: 所有分片操作都成功。
    • "skipped": 0: 没有跳过的分片操作。
    • "failed": 0: 没有失败的分片操作。
  4. "hits": 包含搜索结果的信息。

    • "total": 搜索匹配的文档总数。

      • "value": 1: 有1个文档匹配查询条件。
      • "relation": "eq": 关系为等于,表示确切匹配了1个文档。
    • "max_score": 4.7725887: 最高匹配得分为4.7725887。

    • "hits": 实际文档匹配结果的数组。

      • "index": "test": 文档所在的索引名称。
      • "id": "2": 文档的唯一标识符。
      • "_score": 4.7725887: 文档的匹配得分。
      • "_source": 文档的原始内容,包含以下字段:
        • "brand": "B": 产品品牌为B。
        • "color": "blue": 产品颜色为蓝色。
        • "price": 200: 产品价格为200。