您的当前位置:首页正文

ElasticSearch之父子文档

2024-11-28 来源:个人技术集锦

写在前面

对于父子关系的文档,我们可以使用数据类型来实现,但是这种方式每次更新都需要更新整个文档,想要解决这个问题,可以使用本文要分析的类型为join的父子文档。

1:父子文档

1.1:定义

想要使用父子文档,需要经过如下的步骤:

  • mapping格式:
{
    "mappings": {
        "properties": {
            "关联属性的名称": {
                "type": "join",
                "relations": {
                    "父文档的名称": "子文档的名称"
                }
            }
        }
    }
}

  • 索引父文档格式:
PUT 索引名称/_doc/文档id
{
    "普通属性1": “普通属性值1”,
    "普通属性2": “普通属性值2”,
    "关联属性名称":{
        "name": "父文档名称"
    }
}

  • 索引子文档格式:
PUT 索引名称/_doc/文档id
{
    "普通属性1": “普通属性值1”,
    "普通属性2": “普通属性值2”,
    "关联属性名称":{
        ”parent“: "关联的父文档id"
        "name": "子文档名称"
    }
}

1.2:实例

  • 创建映射
DELETE my_blogs

PUT my_blogs
{
    "settings": {
        "number_of_shards": 2
    },
    "mappings": {
        "properties": {
            "blog_comment_relation": {
                "type": "join",
                "relations": {
                    "blog": "comment"
                }
            },
            "conent": {
                "type": "text"
            },
            "title": {
                "type": "keyword"
            }
        }
    }
}

  • 索引几条parent数据
    注意设置name:"blog"标记其为parent。
PUT my_blogs/_doc/blog1
{
  "title": "Learning Elasticsearch",
  "content": "learning ELK $ geektime",
  "blog_comment_relation": {
    "name": "blog"
  }
}

PUT my_blogs/_doc/blog2
{
  "title": "Learning Hadoop",
  "content": "offline calculation system",
  "blog_comment_relation": {
    "name": "blog"
  }
}
  • 索引几条child数据
    注意:
1:parent属性中设置要关联的parent 
2:设置name:"comment"标记其为child
3:通过将routing值设置为要关联的文档id,保证和parent在同一个分片
# comment1关联parent blog1
PUT my_blogs/_doc/comment1?routing=blog1
{
  "comment": "I am learning ElK",
  "username": "Jakc",
  "blog_comment_relation": {
    "name": "comment",
    "parent": "blog1"
  }
}


# comment2关联parent blog2
PUT my_blogs/_doc/comment2?routing=blog2
{
  "comment": "I like hadoop",
  "username": "jack",
  "blog_comment_relation": {
    "name": "comment",
    "parent": "blog2"
  }
}

# comment3关联parent blog2
PUT my_blogs/_doc/comment3?routing=blog2
{
  "comment": "hello hadoop",
  "username": "Bob",
  "blog_comment_relation": {
    "name": "comment",
    "parent": "blog2"
  }
}
  • 查询所有数据
    parent和child都会返回:
GET my_blogs/_search

  • 直接查询父文档,此时不会带出child
# 直接查询父文档,此时不会带出child
GET my_blogs/_doc/blog1

  • 使用parent_id方式查询,可以带出child
# 通过parent_id方式查询,此时会带出child
POST my_blogs/_search
{
  "query": {
    "parent_id": {
      "type": "comment",
      "id": "blog1"
    }
  }
}

  • 使用has_child,通过child查询parent
# 使用has_child,通过child查询parent
POST my_blogs/_search
{
  "query": {
    "has_child": {
      "type": "comment",
      "query": {
        "match": {
          "username": "jack"
        }
      }
    }
  }
}

  • 使用has_parent,查询关联的子文档
# 使用has_parent,查询关联的子文档
POST my_blogs/_search
{
  "query": {
    "has_parent": {
      "parent_type": "blog",
      "query": {
        "match": {
          "title": "Learning Hadoop"
        }
      }
    }
  }
}

  • 直接通过子文档id查询(查询不到)
  • 通过指定parent 路由查询子文档(可以查询到)

2:嵌套对象 VS 父子文档

嵌套对象适用于读多更新少的场景,父子文档适用于读少更新多的场景:

写在后面

显示全文