ES 中Join的使用
引出问题
在mysql中,可以使用join
来实现表与表之间的数据连接,在es中如何实现这个问题?
相对于mysql来说,es有几个不同的地方
- 不支持跨index的join
- 一个index只能包含一个类型
- 分布式的存储方式,对于数据的搜寻造成障碍
对于上面的几个问题,es的解决方案是**在一个索引下,借助父子关系,实现类似Mysql中多表关联的操作**
定义类型和join索引
1 | PUT myorder |
定义join关系为order_join
,其中order
是父文档,suborder
是子文档。
1 | put myorder/_mapping/_doc |
插入主单数据
1 | PUT myorder/_doc/10001 |
order_join
定义为order
类型
插入子单数据
使用自定义ID用PUT方法
1 | POST myorder/_doc?routing=1 |
1 |
|
建立父子关系索引,
routing
参数是必须的,因为父子文档必须在同一个分片上
查询主单
1 | GET myorder/_search |
查询子单
1 | GET myorder/_search |
聚合查询
主单聚合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24GET myorder/_search
{
"query": {
"parent_id": {
"type": "suborder",
"id": "10001"
}
},
"aggs": {
"parents12312": {
"terms": {
"field": "order_join#order"
},
"aggs": {
"sumAmount": {
"stats": {
"field": "amount"
}
}
}
}
}
}子单聚合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET myorder/_search
{
"size": 0,
"aggs": {
"parent": {
"children": {
"type": "suborder"
},
"aggs": {
"sumAmount": {
"stats": {
"field": "amount"
}
}
}
}
}
}
聚合加筛选:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45GET myorder/_search
{
"query": {
"has_child" : {
"type" : "suborder",
"query" : {
"match_all" : {
}
}
}
},
"aggs": {
"parent": {
"children": {
"type": "suborder"
},
"aggs": {
"fields": {
"terms": {
"field": "orderId"
},
"aggs": {
"sumAmount": {
"sum": {
"field": "amount"
}
},
"having": {
"bucket_selector": {
"buckets_path": {
"orderCount": "_count",
"sumAmount": "sumAmount"
},
"script": {
"source": "params.sumAmount >= 100 && params.orderCount >=0"
}
}
}
}
}
}
}
}
}
定义一对多的索引
一对一的索引模型很难满足日常业务的数据处理,es也支持一对多的join
1 | PUT myorder |
上面的索引的关联的关系如下:
1 | order |