当前位置:网站首页>es-object vs nested vs has_child and has_parent

es-object vs nested vs has_child and has_parent

2022-06-22 01:35:00 童小绿

1.object类型

增加object类型的索引

PUT /joining_query_object_test/_doc/1
{
    
  "obj1": {
    
    "name": "blue",
    "count": 5
  },
  "tags": [
    "龙虎榜",
    "金牛奖"
  ],
  "comments": [
    {
    
      "name": "司马懿",
      "comment": "智务其实,愚争虚名",
      "age": 28,
      "stars": 4,
      "date": "2022-05-01"
    },
    {
    
      "name": "刘伯温",
      "comment": "平而后清,清而后明",
      "age": 31,
      "stars": 5,
      "date": "2022-05-11"
    }
  ],
  "group" : "fans",
  "user" : [ 
    {
    
      "first" : "John",
      "last" :  "Smith"
    },
    {
    
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

PUT /joining_query_object_test/_doc/2
{
    
  "obj1": {
    
    "name": "red",
    "count": 3
  },
    "tags": [
    "1h热股",
    "24h热股"
  ],
  "comments": [
    {
    
      "name": "刘基",
      "comment": "有酒且尽欢,听我薤露歌",
      "age": 42,
      "stars": 3,
      "date": "2022-05-02"
    },
    {
    
      "name": "袁天罡",
      "comment": "兴也洛水,衰也洛水",
      "age": 32,
      "stars": 4,
      "date": "2022-05-12"
    }
  ],
  "group" : "fans",
  "user" : [ 
    {
    
      "first" : "xiaoping",
      "last" :  "liu"
    },
    {
    
      "first" : "tianji",
      "last" :  "li"
    }
  ]
}

查看mapping


GET /joining_query_object_test/_mapping/

##查询年龄是32岁的刘基评论
##理论上应该hit 1,结果 hit 2
##刘基时42岁,32岁的是袁天罡,根本不是同一条评论
##原因:object类型底层数据结构,会将一个json数组中的数据,进行扁平化
GET /joining_query_object_test/_search
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
    
          "match": {
    
            "comments.name": "刘基"
          }
        },
        {
    
          "match": {
    
            "comments.age": 32
          }
        }
      ]
    }
  }
}

## 验证:
##+(+(comments.name:刘 comments.name:) +comments.age:[32 TO 32]) #MatchNoDocsQuery("")
GET /joining_query_object_test/_mapping/_validate/query?explain
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
    
          "match": {
    
            "comments.name": "刘基"
          }
        },
        {
    
          "match": {
    
            "comments.age": 32
          }
        }
      ]
    }
  }
}

##查询first=Alice and last=Smith 出现数据不准的问题
GET joining_query_object_test/_search
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
     "match": {
     "user.first": "Alice" }},
        {
     "match": {
     "user.last":  "Smith" }}
      ]
    }
  }
}

2.nested query

  • doc必须是nested类型。
  • nested类型就是为了解决object类型在对象数组上丢失关联性的问题的

(1)nested query

##设置mapping
DELETE joining_query_nested_test
PUT /joining_query_nested_test
{
    
  "mappings": {
    
    "properties": {
    
      "obj1": {
    
        "type": "nested"
      },
      "comments": {
    
          "type": "nested", 
          "properties": {
    
            "name":    {
     "type": "text"  },
            "comment": {
     "type": "text"  },
            "age":     {
     "type": "short"   },
            "stars":   {
     "type": "short"   },
            "date":    {
     "type": "date"    }
          }
      },
      "user": {
    
        "type": "nested" 
      }
    }
  }
}

##增加doc
PUT /joining_query_nested_test/_doc/1
{
    
  "obj1": {
    
    "name": "blue",
    "count": 5
  },
  "tags": [
    "龙虎榜",
    "金牛奖"
  ],
  "comments": [
    {
    
      "name": "司马懿",
      "comment": "智务其实,愚争虚名",
      "age": 28,
      "stars": 4,
      "date": "2022-05-01"
    },
    {
    
      "name": "刘伯温",
      "comment": "平而后清,清而后明",
      "age": 31,
      "stars": 5,
      "date": "2022-05-11"
    }
  ],
  "group" : "fans",
  "user" : [ 
    {
    
      "first" : "John",
      "last" :  "Smith"
    },
    {
    
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

PUT /joining_query_nested_test/_doc/2
{
    
  "obj1": {
    
    "name": "red",
    "count": 3
  },
    "tags": [
    "1h热股",
    "24h热股"
  ],
  "comments": [
    {
    
      "name": "刘基",
      "comment": "有酒且尽欢,听我薤露歌",
      "age": 42,
      "stars": 3,
      "date": "2022-05-02"
    },
    {
    
      "name": "袁天罡",
      "comment": "兴也洛水,衰也洛水",
      "age": 32,
      "stars": 4,
      "date": "2022-05-12"
    }
  ],
  "group" : "fans",
  "user" : [ 
    {
    
      "first" : "xiaoping",
      "last" :  "liu"
    },
    {
    
      "first" : "tianji",
      "last" :  "li"
    }
  ]
}


##查询mapping(object nested)
GET /joining_query_object_test/_mapping/
GET /joining_query_nested_test/_mapping/


##查询年龄是32岁的刘基评论
##解决object的扁平化问题,刘基时42岁,32岁的是袁天罡,根本不是同一条评论
##结果:hit 0 符合预期
GET /joining_query_nested_test/_search
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
    
          "match": {
    
            "comments.name": "刘基"
          }
        },
        {
    
          "match": {
    
            "comments.age": 32
          }
        }
      ]
    }
  }
}

##_validate验证一下
##+(+(comments.name:刘 comments.name:) +comments.age:[32 TO 32]) #MatchNoDocsQuery("") #DocValuesFieldExistsQuery [field=_primary_term]
GET /joining_query_nested_test/_mapping/_validate/query?explain
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
    
          "match": {
    
            "comments.name": "刘基"
          }
        },
        {
    
          "match": {
    
            "comments.age": 32
          }
        }
      ]
    }
  }
}

##查询first=Alice and last=Smith 
##hit: 0 符合预期
GET joining_query_nested_test/_search
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
     "match": {
     "user.first": "Alice" }},
        {
     "match": {
     "user.last":  "Smith" }}
      ]
    }
  }
}

##查询name=blue,count>4的记录
## hit:1
GET /joining_query_object_test/_search
{
    
  "query": {
    
        "bool": {
    
          "must": [
            {
     "match": {
     "obj1.name": "blue" } },
            {
     "range": {
     "obj1.count": {
     "gt": 4 } } }
          ]
        }
      }
}

(2)查询+聚合

## 查询name=blue,count>4的记录,并聚合求avg
## hit:1
GET /joining_query_nested_test/_search
{
    
  "query": {
    
    "nested": {
    
      "path": "obj1",
      "query": {
    
        "bool": {
    
          "must": [
            {
     "match": {
     "obj1.name": "blue" } },
            {
     "range": {
     "obj1.count": {
     "gt": 4 } } }
          ]
        }
      },
      "score_mode": "avg"
    }
  }
}

(3) Multi-level nested queries 多级嵌套查询


PUT /drivers
{
    
  "mappings": {
    
    "properties": {
    
      "driver": {
    
        "type": "nested",
        "properties": {
    
          "last_name": {
    
            "type": "text"
          },
          "vehicle": {
    
            "type": "nested",
            "properties": {
    
              "make": {
    
                "type": "text"
              },
              "model": {
    
                "type": "text"
              }
            }
          }
        }
      }
    }
  }
}

PUT /drivers/_doc/1
{
    
  "driver" : {
    
        "last_name" : "McQueen",
        "vehicle" : [
            {
    
                "make" : "Powell Motors",
                "model" : "Canyonero"
            },
            {
    
                "make" : "Miller-Meteor",
                "model" : "Ecto-1"
            }
        ]
    }
}

PUT /drivers/_doc/2?refresh
{
    
  "driver" : {
    
        "last_name" : "Hudson",
        "vehicle" : [
            {
    
                "make" : "Mifune",
                "model" : "Mach Five"
            },
            {
    
                "make" : "Miller-Meteor",
                "model" : "Ecto-1"
            }
        ]
    }
}

##使用多级嵌套查询根据 make 和 model 字段匹配文档
GET /drivers/_search
{
    
  "query": {
    
    "nested": {
    
      "path": "driver",
      "query": {
    
        "nested": {
    
          "path": "driver.vehicle",
          "query": {
    
            "bool": {
    
              "must": [
                {
     "match": {
     "driver.vehicle.make": "Powell Motors" } },
                {
     "match": {
     "driver.vehicle.model": "Canyonero" } }
              ]
            }
          }
        }
      }
    }
  }
}

3.has_child and has_parent

##单个索引内的文档之间可以存在连接字段关系。
##插入子文档注意:子文档必须和父文档在同一分片上,父文档,有路由存在时,插入子文档必须也填上和父文档相同的路由。
##查询文档的时候注意:
##has_child 查询返回其子文档与指定查询匹配的父文档,
##has_parent 查询返回其父文档与指定查询匹配的子文档。

Parent/child VS nested

父-子关系文档 在实质上类似于 nested model :允许将一个对象实体和另外一个对象实体关联起来。
(1)nested objects ,所有对象都是在同一个文档中,读取性能高
(2)Parent/child,父对象和子对象都是完全独立的文档,父子更新互不影响

  • 修改索引的时候的影响范围(场景)
  • (1)nested,更新父子文档的时候需要更新整个文档
  • (2)Parent/child,创建,修改或删除子文档时,不会影响父文档或其他子文档,但是为了维护join的关系,需要占用部分内存,读取性能较差
##设置父子结构的mapping ,join + relations
PUT /joining_query_child_test
{
    
  "mappings": {
    
    "properties": {
    
      "my-join-field": {
    
        "type": "join",
        "relations": {
    
          "parent": "child"
        }
      },
      "tag": {
    
        "type": "keyword"
      }
    }
  }
}

##使用has_child查询
GET /joining_query_child_test/_search
{
    
  "query": {
    
    "has_child": {
    
      "type": "child",
      "query": {
    
        "match_all": {
    }
      },
      "max_children": 10,
      "min_children": 2,
      "score_mode": "min"
    }
  }
}

PUT  /joining_query_father_test
{
    
  "mappings": {
    
    "father":{
    
      "properties": {
    
        "id":{
    
          "type": "integer"
        },
        "name":{
    
          "type": "keyword"
        }
      }
    },
    "childers":{
    
      "_parent": {
    
        "type": "father"
      }, 
      "properties": {
    
        "age":{
    
          "type": "integer"
        },
        "name":{
    
          "type": "keyword"
        }
      }
    }
  }
}

PUT three_tree_index
{
    
  "mappings": {
    
    "properties": {
    
      "name": {
    
        "type": "text"
      },
      "age": {
    
        "type": "keyword"
      },
      "my_join_field": {
    
        "type": "join",
        "relations": {
    
          "user_base": "article",
          "article": "vote"
        }
      },
      "stars": {
    
        "type": "short"
      },
      "article_desc": {
    
        "type": "text"
      }
    }
  }
}

#插入6条数据
PUT three_tree_index/_doc/1?routing=1&refresh
{
    
  "name":"xiaoming",
  "age":29,
  "my_join_field":"user_base"
}

PUT three_tree_index/_doc/2?routing=2&refresh
{
    
  "name":"xiaohong",
  "age":32,
  "my_join_field":"user_base"
}
 
PUT three_tree_index/_doc/3?routing=1&refresh
{
    
  "article_desc":"xiaoming,article_desc_1",
  "my_join_field":{
    
    "name":"article",
    "parent":"1"
  }
}
 
PUT three_tree_index/_doc/4?routing=2&refresh
{
    
  "article_desc":"xiaohong,article_desc_1",
  "my_join_field":{
    
    "name":"article",
    "parent":"2"
  }
}
 
PUT three_tree_index/_doc/5?routing=1&refresh
{
    
  "stars":5,
  "my_join_field":{
    
    "name":"vote",
    "parent":"3"
  }
}
 
PUT three_tree_index/_doc/6?routing=2&refresh
{
    
  "stars":3,
  "my_join_field":{
    
    "name":"vote",
    "parent":"4"
  }
}

## three_tree_index 
## hits : 6
GET /three_tree_index/_search

##查询文章内容有“xiaoming”的用户信息
##通过查询has_child查询到parent信息
GET three_tree_index/_search
{
    
  "query": {
    
    "has_child": {
    
      "type": "article",
      "query": {
    
        "match": {
    
          "article_desc": "xiaoming"
        }
      }
    }
  }
}
 
##可以通过添加"inner_hits":{
    },将父和子文档都返回出来
##_source:父
##inner_hits:子
GET three_tree_index/_search
{
    
  "query": {
    
    "has_child": {
    
      "type": "article",
      "query": {
    
        "match": {
    
          "article_desc": "xiaoming"
        }
      },
      "inner_hits": {
    }
    }
  }
}
 
##查询有五星评价的文章对应的用户(嵌套两层has_child查询)
GET three_tree_index/_search
{
    
  "query": {
    
    "bool": {
    
      "must": [
        {
    
          "has_child": {
    
            "type": "article",
            "query": {
    
              "has_child": {
    
                "type": "vote",
                "query": {
    
                  "bool": {
    
                    "should": [
                      {
    
                        "term": {
    
                          "stars": 5 
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}


##has_parent的功能正好相反,比如我想搜索所有包含“xiaoming”的文章的平均星级
GET three_tree_index/_search
{
    
  "query": {
    
    "has_parent": {
    
      "parent_type": "article",
      "query": {
    
        "bool": {
    
          "should": [
            {
    
              "match": {
    
                "article_desc": "xiaoming"
              }
            }
          ]
        }
      },
       "inner_hits": {
    }
    }
  },
  "aggs": {
    
    "avg_star": {
    
      "avg": {
    
        "field": "stars"
      }
    }
  }
}


## 使用 has _ father 查询,索引必须包含连接字段映射
DELETE joining_parent_test_02
PUT /joining_parent_test_02
{
    
  "mappings": {
    
    "properties": {
    
      "my-join-field": {
    
        "type": "join",
        "relations": {
    
          "parent": "child"
        }
      },
      "tag": {
    
        "type": "keyword"
      }
    }
  }
}

GET /joining_parent_test_02/_search
{
    
  "query": {
    
    "has_parent": {
    
      "parent_type": "parent",
      "query": {
    
        "term": {
    
          "tag": {
    
            "value": "Elasticsearch"
          }
        }
      }
    }
  }
}


##Parent ID query 父母身份查询===================================================================================

##1.Create an index with a join field mapping.join + relations
DELETE my-index-000001
PUT /my-index-000001
{
    
  "mappings": {
    
    "properties": {
    
      "my-join-field": {
    
        "type": "join",
        "relations": {
    
          "my-parent": "my-child"
        }
      }
    }
  }
}

##2.父文档索引
PUT /my-index-000001/_doc/1?refresh
{
    
  "text": "This is a parent document.",
  "my-join-field": "my-parent"
}

##3.子文档索引
PUT /my-index-000001/_doc/2?routing=1&refresh
{
    
  "text": "This is a child document.",
  "my-join-field": {
    
    "name": "my-child",
    "parent": "1"
  }
}

##4.搜索返回 ID 为1的父文档的子文档。
## hit :1
GET /my-index-000001/_search
{
    
  "query": {
    
    "parent_id": {
    
          "type": "my-child",
          "id": "1"
      }
  }
}

原网站

版权声明
本文为[童小绿]所创,转载请带上原文链接,感谢
https://blog.csdn.net/tsj11514oo/article/details/125364044