ElasticSearch join连接查询
特别说明:文章所有内容基于ElasticSerch 5.5.3版本
ElasticSerch 的连接查询有两种方式实现
- nested
- parent和child关联查询
nested
- 存储结构
nested的方式和其他字段一样,在同一个type里面存储,以数组的方式存储在
type里,格式如下:
PUT index_test/type_info/1000
{
"userId": 1000,
"mobile": "13301020202",
"nick": "梅西",
"vipType": 1,
"vipPoints": 1200,
"regTime": "2018-06-18 12:00:31",
"order": [
{
"status": 1,
"payMethod": 2,
"amount": 100,
"productCount": 3
},
{
"status": 2,
"payMethod": 2,
"amount": 230,
"productCount": 1
}
]
}
order
则为 nested
- API查询方式
直接用.
连接对象的属性,如要要查找订单中状态=2的用户,直接使用order.status
GET index_test/type_info/_search
{
"query": {
"term": {
"order.status": 2
}
}
}
parent / child 关联的方式
-
存储结构
parent / child 的存储结果跟nested不一样,是存储在不同的type里,通过parent来关联父子type关系PUT index_test { "mappings": { "type_info": { "properties": { "userId": { "type": "integer" }, "mobile": { "type": "keyword" }, "nick": { "type": "keyword" }, "vipType": { "type": "integer" }, "vipPoints": { "type": "integer" }, "regTime": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" } } }, "type_order": { "_parent": { "type": "type_info" }, "properties": { "amount": { "type": "scaled_float", "scaling_factor": 100 }, "payMethod": { "type": "integer" }, "status": { "type": "integer" }, "productCount": { "type": "integer" } } } } }
通过
_parent
来指定父type -
造点数据
添加几条用户数据,和普通的type一样,没有任何区别PUT index_test/type_info/1000 { "userId": 1000, "mobile": "13301020202", "nick": "梅西", "vipType": 1, "vipPoints": 1200, "regTime": "2018-06-18 12:00:31" }
PUT index_test/type_info/1001 { "userId": 1001, "mobile": "151232223", "nick": "C罗", "vipType": 1, "vipPoints": 300, "regTime": "2018-05-18 12:00:00" }
PUT index_test/type_info/1002 { "userId": 1002, "mobile": "181829282", "nick": "内马尔", "vipType": 2, "vipPoints": 1300, "regTime": "2018-09-09 12:00:00" }
添加几条订单数据,通过parent来指定type_info
PUT index_test/type_order/100?parent=1000 { "userId": 1000, "amount": 300, "payMethod": 2, "status": 3, "productCount": 2 }
PUT index_test/type_order/101?parent=1000 { "userId": 1000, "amount": 250, "payMethod": 1, "status": 2, "productCount": 1 }
PUT index_test/type_order/102?parent=1001 { "userId": 1001, "amount": 56, "payMethod": 1, "status": 2, "productCount": 1 }
PUT index_test/type_order/103?parent=1002 { "userId": 1002, "amount": 78, "payMethod": 2, "status": 1, "productCount": 2 }
-
API查询方式
- 通过子type查询父type,返回父type信息
查询下单金额大于60的用户,通过has_child
查询,返回用户信息
GET index_test/type_info/_search { "query": { "has_child": { "type": "type_order", "query": { "range": { "amount": { "gte": 60 } } } } } }
- 通过父type查子type,返回子type信息
查询vip等级为1的用户下的订单,通过has_parent
查询,返回订单信息
- 通过子type查询父type,返回父type信息
GET index_test/type_order/_search
{
"query": {
"has_parent": {
"parent_type": "type_info",
"query": {
"term": {
"vipType": {
"value": 1
}
}
}
}
}
}
nested 和 parent-child的区别以及使用场景
-
主要区别:
由于存储结构的不同,nested和parent-child的方式有不同的应用场景
nested 所有实体存储在同一个文档,parent-child模式,子type和父type存储在不同的文档里。
所以查询效率上nested要高于parent-child,但是更新的时候nested模式下,es会删除整个文档再创建,而parent-child只会删除你更新的文档在重新创建,不影响其他文档。所以更新效率上parent-child要高于nested。 -
使用场景:
nested:在少量子文档,并且不会经常改变的情况下使用。
比如:订单里面的产品,一个订单不可能会有成千上万个不同的产品,一般不会很多,并且一旦下单后,下单的产品是不可更新的。
parent-child:在大量文档,并且会经常发生改变的情况下使用。
比如:用户的浏览记录,浏览记录会很大,并且会频繁更新
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tuposky/article/details/80988915