Elasticsearch join type
https://blog.csdn.net/laoyang360/article/details/79774481
join数据类型是一个特殊字段,可在相同索引的文档中创建父/子关系。
relations属性定义了一组可能的关系,每个关系都是父名称和子名称。
创建join类型的文档必须在源文档中通过name指定关系。
PUT my_index
{
"mappings": {
"properties": {
"my_join_field": {
"type": "join",
"relations": { //定义关系
"question": "answer" //question为父文档,answer为子文档
}
}
}
}
}
创建父文档question
PUT my_index/_doc/1?refresh
{
"text": "This is a question",
"my_join_field": {
"name": "question" //name指定关系,当前为question文档
}
}
PUT my_index/_doc/2?refresh
{
"text": "This is another question",
"my_join_field": {
"name": "question" //name指定关系
}
}
简化方式,直接指定关系名称
PUT my_index/_doc/1?refresh
{
"text": "This is a question",
"my_join_field": "question"
}
PUT my_index/_doc/2?refresh
{
"text": "This is another question",
"my_join_field": "question"
}
创建子文档,name属性指定关系,parent指定父id
路由值是强制性的,因为父文档和子文档必须在同一分片上建立索引
PUT my_index/_doc/3?routing=1&refresh //必须指定路由
{
"text": "This is an answer",
"my_join_field": {
"name": "answer", //指定关系
"parent": "1" //父文档id
}
}
PUT my_index/_doc/4?routing=1&refresh
{
"text": "This is another answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
}
join类型的字段不应像关系数据库中的那样使用,has_child或has_parent查询都会对您的查询性能造成很大的负担
join类型索引约束
- 每个索引只允许一个Join类型Mapping定义;
- 父文档和子文档必须在同一个分片上编入索引;这意味着,当进行删除、更新、查找子文档时候需要提供相同的路由值
- 一个文档可以有多个子文档,但只能有一个父文档。
- 可以为已经存在的Join类型添加新的关系
- 当一个文档已经成为父文档后,可以为该文档添加子文档
join类型搜索
全量检索
GET my_index/_search
{
"query": {
"match_all": {}
},
"sort": ["_id"]
}
{
...,
"hits": {
"total" : {
"value": 4,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": null,
"_source": {
"text": "This is a question",
"my_join_field": "question"
},
"sort": [
"1"
]
},
{
"_index": "my_index",
"_id": "2",
"_score": null,
"_source": {
"text": "This is another question",
"my_join_field": "question"
},
"sort": [
"2"
]
},
{
"_index": "my_index",
"_id": "3",
"_score": null,
"_routing": "1",
"_source": {
"text": "This is an answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
},
"sort": [
"3"
]
},
{
"_index": "my_index",
"_id": "4",
"_score": null,
"_routing": "1",
"_source": {
"text": "This is another answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
},
"sort": [
"4"
]
}
]
}
}
has_child基于子文档查找父文档
用于查询包含特定子文档的父文档
type :必须,指定关系名称
query :必须,查询
ignore_unmapped :没有匹配的类型不返回文档而不是返回错误,默认false
max_children:与返回的父文档允许的查询相匹配的子文档的最大数量。 如果父文档超出此限制,则将其排除
min_children:与查询相匹配的子文档的最小数量,如果父文档不符合此限制,则将其从搜索结果中排除。
score_mode :指示匹配子文档的分数如何影响根父文档的相关性分数,min,max,sum,avg或者none.默认none
DELETE my_index
PUT my_index
{
"mappings": {
"properties": {
"text":{
"type":"text"
},
"my-join-field":{
"type":"join",
"relations":{
"parent":"child"
}
}
}
}
}
PUT my_index/_doc/1
{
"text":"this is 1 parent",
"my-join-field":"parent"
}
PUT my_index/_doc/2
{
"text":"this is 2 parent",
"my-join-field":"parent"
}
PUT my_index/_doc/3?routing=1
{
"text":"this is 3 child",
"my-join-field":{
"name":"child",
"parent":1
}
}
PUT my_index/_doc/4?routing=1
{
"text":"this is 4 child",
"my-join-field":{
"name":"child",
"parent":1
}
}
PUT my_index/_doc/5?routing=1
{
"text":"this is 5 child",
"my-join-field":{
"name":"child",
"parent":1
}
}
GET my_index/_search
{
"query": {
"has_child": {
"type": "child",
"query": {
"match_all": {}
},
"max_children": 3,
"min_children": 1,
"score_mode": "none"
}
}
}
排序
查询查出的结果不能直接用用sort进行排序
如果需要按子文档中的字段对返回的文档进行排序,请使用function_score查询并按_score进行排序。
例如以下查询按其子文档的click_count字段对返回的文档进行排序
PUT my_index
{
"mappings": {
"properties": {
"text":{
"type":"text"
},
"my-join-field":{
"type":"join",
"relations":{
"parent":"child"
}
}
}
}
}
PUT my_index/_doc/1
{
"text":"this is 1 parent",
"my-join-field":"parent"
}
PUT my_index/_doc/2
{
"text":"this is 2 parent",
"my-join-field":"parent"
}
PUT my_index/_doc/3
{
"text":"this is 3 parent",
"my-join-field":"parent"
}
PUT my_index/_doc/4?routing=1
{
"text":"this is 4 child",
"click_count":10.0,
"my-join-field":{
"name":"child",
"parent":1
}
}
PUT my_index/_doc/5?routing=2
{
"text":"this is 5 child",
"click_count":20.0,
"my-join-field":{
"name":"child",
"parent":2
}
}
PUT my_index/_doc/6?routing=3
{
"text":"this is 6 child",
"click_count":30.0,
"my-join-field":{
"name":"child",
"parent":3
}
}
GET my_index/_search
{
"query": {
"has_child": {
"type": "child",
"query": {
"function_score" : {
"script_score": { //按子文档的click_count值排序
"script": "_score * doc['click_count'].value"
}
}
},
"max_children": 3,
"min_children": 0,
"score_mode": "max"
}
}
}
has_parent 基于父文档查找子文档
has_parent参数:
type :必须,指定关系名称
query :必须,查询
ignore_unmapped :可选,默认false,没有匹配的类型不返回文档而不是返回错误,
score :可选,默认false, 如果为false,ES将忽略父文档的相关性得分。如果为true,则将匹配的父文档的相关性分数汇总到其子文档的相关性分数中
GET my_index/_search
{
"query": {
"has_parent": {
"parent_type": "parent",
"query": {
"match": {
"text":"this is "
}
}
}
}
}
排序
GET /_search
{
"query": {
"has_parent" : {
"parent_type" : "parent",
"score" : true,
"query" : {
"function_score" : {
"script_score": {
"script": "_score * doc['view_count'].value"
}
}
}
}
}
}
parent_id查询
parent_id参数
type:子文档类型
id:父文档ID
ignore_unmapped :可选,默认false,没有匹配的类型不返回文档而不是返回错误
GET my_index/_search
{
"query": {
"parent_id": {
"type": "child",
"id": 1
}
}
}
多层级父子关系
PUT my_index
{
"mappings": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"question": ["answer", "comment"], //question为answer与comment父节点
"answer": "vote" //answer为vote父节点
}
}
}
}
}
PUT my_index/_doc/3?routing=1&refresh
{
"text": "This is a vote",
"my_join_field": {
"name": "vote",
"parent": "2"
}
}