Elasticsearch Join字段类型简单快速上手教程

2023-05-16 0 1,219

目录

阅读本文需要一定的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很消耗性能的,层级再深点没法用了,下面就是多级别的语句测试,此时他们三者的关系就如下所示

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,更多关于Elasticsearch Join字段类型的资料请关注其它相关文章!

资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 Elasticsearch Join字段类型简单快速上手教程 http://www.20zxx.cn/704874/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务