elasticsearch简介
elasticsearch一直以来受大众青睐,特别适用于大数据量、高频繁查询的业务逻辑。大家都知道ES的数据是以文档的形式保存的,在保存数据的时候ES的分词系统会将我们的数据通过倒排索引进行处理,以便于我们后续高效的查询。
多个实体对象关联
在实际业务过程中我们的各个实体对象都相互关联,那么在ES的世界里我们如何处理这些关联关系呢?ES中一般有普通文档、嵌套文档、父子文档,这些文档都能满足父子对象的关系。但是,普通一对多文档有子对象边界值问题,嵌套文档修改父文档必须修改整个文档,父子文档则可以任意修改文档且不影响其他关系文档。今天我们就来看看ES的父子文档。
什么是父子文档
父子文档就是将父文档和子文档关联起来,就如同关系数据库里面 join 一样。父子文档都绑定在同一个索引上,但是分属于两个独立的文档。
优势与劣势
优点:
1、父子文档相互独立
2、修改父文档索引不影响子文档;增删改任意的子文档,父文档和其他子文档不受影响
3、子文档可以从属于多个父文档
缺点:
1、索引结构复杂,封装操作脚本难度较大
2、为保证父子文档被分配到同一个分片,新增子文档必须添加和父文档一致的路由
小试牛刀
比如我们产品下有多个渠道
1、定义如下父子文档索引:
这里用到了 joinFiled 自定义字段进行过滤,此字段我们创建索引时可以自由声明,当前里面的父子文档标识( “product”: “channel”)也是自由声明。
PUT product
PUT product/_mapping
{
"properties":{
"name": {
"type":"keyword"
},
"productId": {
"type":"integer"
},
"joinFiled":{
"type":"join",
"relations":{
"product": "channel"
}
}
}
}
2、查看索引结构
GET product
3、新增父文档数据
#新增父文档
PUT product/_doc/11001
{
"name":"产品1",
"productId":11001,
"joinFiled":{
"name": "product"
}
}
4、新增子文档,注意路由取父文档id保证父子文档在同片。
#新增子文档
PUT product/_doc/12001?routing=11001
{
"name":"渠道1",
"joinFiled":{
"name": "channel",
"parent": 11001
}
}
“parent”: 11001 >> 将渠道子文档与产品父文档关联起来。
实际业务中一般子文档保存有父文档的id,那么这个父id就是关联的关键。
5、查询文档数量确定父子文档是否独立
#查询文档数据
GET product/_search
{
}
6、根据父文档查询子文档,
#根据子父档查询子文档
GET product/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"joinFiled": {
"value": "channel"
}
}
},{
"has_parent": {
"parent_type": "product",
"query": {
"bool": {
"must": [
{
"term": {
"name": {
"value": "产品1"
}
}
}
]
}
}
}
}
]
}
}
}
7、根据子文档查询父文档
#根据子文档查询父文档
GET product/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"joinFiled": {
"value": "product"
}
}
},{
"has_child": {
"type": "channel",
"query": {
"bool": {
"must": [
{
"term": {
"name": {
"value": "渠道1"
}
}
}
]
}
}
}
}
]
}
}
}
父子文档是将两个独立的文档关联起来,操作父子文档关系不会影响其他文档。父子文档关联是在创建索引时进行申明,他们同属于同一个索引却不是同一个文档。