关于后端:Join字段类型超容易上手的好吧Elasticsearch

75次阅读

共计 4341 个字符,预计需要花费 11 分钟才能阅读完成。

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

浏览本文须要肯定的 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-index
GET my-index-000001/_stats/fielddata?human&fields=join_field#goods

# Per-node per-index
GET _nodes/stats/indices/fielddata?human&fields=join_field#goods

父子文档

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

    DELETE my-index-000001
    PUT 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-000001
    PUT 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-000001
PUT 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 多平台公布

正文完
 0