最近因为工作起因吗,比较忙,而后集体也比拟懒,输入又慢下来了,前面会缓缓复原的,定期保障周更吧,并且保证质量输入。

浏览本文须要肯定的Elasticsearch根底哦,本文深度有,然而不深

概述

Elasticsearch中Join数据类型的字段置信大家也都用过,也就是口中常谈的父子文档。在Elasticsearch中Join不能跨索引和分片,所以保存文档信息时要保障父子文档应用雷同的路由参数来保障父文档与子文档保留在同一个索引的同一个分片,那么都有哪些限度呢?

父子关系的限度

  • 每个索引中只能有一个关系字段
  • 父文档与子文档必须在同一个索引分片中,所以咱们在对父子文档减少、删除、批改时要设置路由值,保证数据都在同一分片
  • 一个父文档能够蕴含多个子文档,然而一个子文档只能有一个父文档
  • 只能在Join类型的字段上建设关系
  • 在保障以后文档是父文档的前提下能够减少子文档

Global ordinals

翻译过去就是全局序数。什么是全局序数呢,官网文档中阐明了,这就是一个减速查问的一个货色,应用了全局序数之后能够让数据更紧凑;具体的就不开展了,前面有机会再具体阐明一下全局序数,具体的目前能够查看一下官网文档

对于咱们本章节内容来说,咱们晓得父子文档Join类型是应用全局序数来减速查问的就能够了。默认状况下,全局序数根本是实时构建的,当索引发生变化,全局序数会从新构建。这个过程会减少refresh的工夫,当然这个配置也是能够敞开的,然而敞开之后会在咱们接下来遇到的第一个父连贯或者聚合的查问时从新构建全局序数,这样这一部分的工夫就反馈给了用户,官网也是不倡议咱们这样做的,感觉对用户来说不是那么的敌对,次要还是在一个衡量。最坏的状况就是同时有多个写入,也就是同时有多个全局序数须要从新构建,也就会造成在单个refresh的工夫距离内要从新构建多个全局序数

当然如果关联字段应用的不是很频繁并且写入事件很多,禁用掉是值得举荐的,禁用形式如下

PUT my-index-000001{  "mappings": {    "properties": {      "join_field": {        "type": "join",        "relations": {           "goods": ["details","evaluate"],           "evaluate":"vote"        },        "eager_global_ordinals": false      }    }  }}

当然,对于全局序数占用的堆大小状况能够应用如下语句查看

# Per-indexGET my-index-000001/_stats/fielddata?human&fields=join_field#goods# Per-node per-indexGET _nodes/stats/indices/fielddata?human&fields=join_field#goods

父子文档

  • 首先咱们还是创立一个失常的父子关系索引,商品作为父文档,详情作为子文档

    DELETE my-index-000001PUT my-index-000001{  "mappings": {    "properties": {      "id": {        "type": "keyword"      },      "join_field": {         "type": "join",        "relations": {          "goods": "details"         }      }    }  }}
    • my-index-000001:索引名称
    • id:文档主键
    • join_field:父子关系字段,type标记为Join为父子文档
    • relations: 定义父子关系,goods为父文档类型名称,details为子文档类型名称,前面插入数据,查问都会应用
  • 插入几条测试数据,商品有iphonmac,详情为色彩外观与内存配置等

    PUT my-index-000001/_doc/1?refresh{  "id": "1",  "text": "iphone 14 pro max",  "join_field": {    "name": "goods"   }}PUT my-index-000001/_doc/2?refresh{  "id": "2",  "text": "macbook pro ",  "join_field": {    "name": "goods"  }}PUT my-index-000001/_doc/3?routing=1&refresh {  "id": "3",  "text": "512G 16核",  "join_field": {    "name": "details",     "parent": "1"   }}PUT my-index-000001/_doc/4?routing=1&refresh{  "id": "4",  "text": "粉/银/黑/抹茶绿",  "join_field": {    "name": "details",    "parent": "1"  }}PUT my-index-000001/_doc/5?routing=1&refresh {  "id": "5",  "text": "1T 32G",  "join_field": {    "name": "details",     "parent": "2"   }}PUT my-index-000001/_doc/6?routing=1&refresh{  "id": "6",  "text": "银/黑",  "join_field": {    "name": "details",    "parent": "2"  }}
  • 应用parent_id查问父子文档,以下面插入的测试数据查问,查找mac的详情信息语句如下,前提是晓得父文档的id

    GET my-index-000001/_search{  "query": {    "parent_id": {      "type": "details",      "id":"2"    }  },  "sort":["id"]}
  • 大部分状况下面是不能满足咱们的查问申请的,所以咱们还能够应用has_parent或者has_child查问

    • 应用has_parent查问:父文档goods中所有蕴含macbook的子文档(后文的孙子文档也能够查问)

      GET my-index-000001/_search{  "query": {    "has_parent": {      "parent_type": "goods",      "query": {        "match": {          "text": "macbook"        }      }    }  }}
  • 应用hash_child查看details子文档中有1T关键字的所有父文档

    GET my-index-000001/_search{  "query": {    "has_child": {      "type": "details",      "query": {        "match": {          "text": "1T"        }      }    }  }}
  • 应用parent-join 查问或者聚合

    Elasticsearch在应用Join类型数据类型时,会主动创立一个附加的字段,构造为Join的字段名加#号加父类型,以上文为例,创立一个附加字段(join_field#goods),如下是应用parent-join字段查问聚合的一个例子,参考自官网,利用了8.1版本的新个性运行时字段

    GET my-index-000001/_search{  "query": {    "parent_id": {       "type": "details",      "id": "1"    }  },  "aggs": {    "parents": {      "terms": {        "field": "join_field#goods",         "size": 10      }    }  },  "runtime_mappings": {    "my_parent_field": {      "type": "long",      "script": """        emit(Integer.parseInt(doc['join_field#goods'].value))       """    }  },  "fields": [    { "field": "my_parent_field" }  ]}
  • Join类型的父子文档,下面咱们演示了一个父文档对应一种子文档类型的例子,Join类型也反对一个父类型有多个子类型,以上文为根底,退出上面语句测试

    DELETE my-index-000001PUT my-index-000001{  "mappings": {    "properties": {      "id": {        "type": "keyword"      },      "join_field": {         "type": "join",        "relations": {          "goods": ["details","evaluate"]         }      }    }  }}PUT my-index-000001/_doc/7?routing=1&refresh{  "id": "7",  "text": "运行流程,无卡顿,待机时间长",  "join_field": {    "name": "evaluate",    "parent": "1"  }}PUT my-index-000001/_doc/8?routing=1&refresh{  "id": "8",  "text": "体重轻,携带方便,编码利器",  "join_field": {    "name": "evaluate",    "parent": "2"  }}
  • 同样的,仔细的同学曾经看到了,上文曾经标记了孙子文档,对的,你没看错就是孙子文档,三级的层级,级别能够更深,然而Elasticsearch不倡议很深的档次,毕竟Join很耗费性能的,层级再深点没法用了,上面就是多级别的语句测试,此时他们三者的关系就如下所示

DELETE my-index-000001PUT my-index-000001{  "mappings": {    "properties": {      "id": {        "type": "keyword"      },      "join_field": {         "type": "join",        "relations": {          "goods": ["details","evaluate"],          "evaluate":"vote"        }      }    }  }}PUT my-index-000001/_doc/9?routing=1&refresh{  "id": "9",  "text": "这是投票信息:我买iphone是因为性价比高,保值",  "join_field": {    "name": "vote",    "parent": "1"  }}PUT my-index-000001/_doc/10?routing=1&refresh{  "id": "10",  "text": "这是投票信息:我买mac是因为轻,携带方便,没有流氓软件",  "join_field": {    "name": "vote",    "parent": "2"  }}

总结

置信大家也看进去了,官网都不倡议应用父子文档的,毕竟性能是一大问题,置信大家用Elasticsearch必定大部分都是图速度快,用了Join字段变慢了,这谁能批准呢是吧,有利有弊吧,看大家抉择,下一篇带给大家的算是Elasticsearch举荐Join字段代替类型Nested

本文由mdnice多平台公布