Elasticsearch 关联关系处理:Nested Object和Parent_Child

关联关系处理

ES不擅长处理管理型数据库中的关联关系,比如文章表blog与评论表comment之间通过blog_id关联,在ES中可以通过如下两种手段变相解决:

  • Nested Object
  • Parent/Child

评论Comment:

文章Id blog_id
评论人 username
评论日期 date
评论内容 content    

Nested Object

关系型数据库中的关联关系:
这里写图片描述
在es中其中的一个实现方式如下所示:
把comment具体的内容直接整合进blog文档中,这样在获取blog的内容的时候可以直接取到文档的评论
这里写图片描述

现在对comments进行如下查询:
返回lee评论的,并且他的评论内容有thanks关键词的所有blog,结果如下图所示:
这里写图片描述

很明显查询结果并不符合条件,原因如下:

comments如果不设定其类型的话默认是Object Array,存储结构类似下面的形式:(一个object)
这里写图片描述

解决办法
Nested object可以解决这个问题:
mapping设置为如下所示:

PUT blog_index_nested
{
  "mappings": {
    "doc":{
      "properties": {
        "title":{
          "type":"text",
          "fields": {
            "keyword":{
              "type": "keyword"
            }
          }
        },
        "publish_date":{
          "type": "date"
        },
        "author":{
          "type": "keyword"
        },
        "abstract":{
          "type": "text"
        },
        "url":{
          "enabled":"false"
        },
        "comments":{
          "type": "nested",
          "properties": {
            "username":{
              "type":"keyword",
              "ignore_above":100
            },
            "data":{
              "type":"date"
            },
            "content":{
              "type":"text"
            }
          }
        }
      }
    }
  }
}

插入相同数据:

PUT blog_index_nested/doc/1
{
  "title":"Blog Number One",
  "auther":"alfred",
  "comments":[
    {
      "username":"lee",
      "date":"2017-01-02",
      "content":"awesome article!"
    },
    {
      "username":"fax",
      "date":"2017-04-02",
      "content":"thanks"
    }
    ]
}

使用如下方法进行查询:

GET blog_index_nested/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "comments.username": "lee"
              }
            },
            {
              "match": {
                "comments.content": "thanks"
              }
            }
          ]
        }
      }
    }
  }
}

返回结果为空(满足条件)
这里写图片描述

这是因为Nested Object Array的存储结构类似下面的形式:(nested object独立存在)

{
  "title":"Blog Number One",
  "auther":"alfred"
}
{
  "comments.username":"lee",
  "comments.date":"2017-01-02",
  "comments.content":"awesome article!"
}
{
  "comments.username":"fax",
  "comments.date":"2017-04-02",
  "comments.content":"thanks"
}       

Parent/Child

ES还提供了类似关系数据库中join的实现方式,使用join数据类型

PUT blog_index_parent_child
{
  "mappings": {
    "doc":{
      "properties": {
        "join":{
          "type": "join",
          "relations":{
            "blog":"comment"
          }
        }
      }
    }
  }
}

这里写图片描述

创建父子文档

#创建父文档
PUT blog_index_parent_child/doc/1
{
  "title":"blog",
  "join":"blog"
}       
#创建子文档
PUT blog_index_parent_child/doc/comment-1?routing=1
{
  "comment":"comment world",
  "join":{
    "name":"comment",
    "parent":1
  }
}       

这里写图片描述
这里写图片描述
常见query语法包括如下几种:

  • parent_id: 返回某父文档的子文档
  • has_child: 返回包含某子文档的父文档
  • has_parent: 返回包含某父文档的子文档

(1)parent_id查询:返回某父文档的子文档

GET blog_index_parent_child/_search
{
  "query": {
    "parent_id":{
      "type":"comment",
      "id":"1"
    }
  }
}       
#parent_id关键词,type指明子文档类型,id指明父文档id

(2)has_child查询: 返回包含某子文档的父文档

GET blog_index_parent_child/_search
{
  "query": {
    "has_child": {
      "type": "comment",
      "query": {
        "match": {
          "comment": "world"
        }
      }
    }
  }
}           

(3)has_parent查询: 返回包含某父文档的子文档

GET blog_index_parent_child/_search
{
  "query": {
    "has_parent": {
      "parent_type": "blog",
      "query": {
        "match": {
          "title": "blog"
        }
      }
    }
  }
}           

nested_vs_parent_child

这里写图片描述
建议尽量选择nested object来解决问题

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值