美文网首页
Elasticsearch系列(15)Query之连接查询

Elasticsearch系列(15)Query之连接查询

作者: 正义的杰克船长 | 来源:发表于2020-09-17 20:17 被阅读0次

    1. 前言

    在Elasticsearch这种分布式系统上执行完全类似SQL风格的连接查询代价比较高,作为替代,Elasticsearch提供了两种可水平伸缩的连接(Join)形式的查询。

    • 嵌套查询(nested query)
    • has_child和has_parent查询

    2. 嵌套查询

    嵌套查询(nested query)搜索嵌套(nested)类型的字段对象,就好像它们被索引为单独的文档一样。如果一个对象匹配搜索条件,嵌套查询将返回对象所在的父文档。
    首先创建包含嵌套类型的映射的索引,示例如下:

    PUT /my_index_01
    {
        "mappings" : {
            "properties" : {
                "my_object" : {
                    "type" : "nested"
                }
            }
        }
    }
    PUT /my_index_01/_doc/1
    {
        "my_object" : [
          {"name": "blue", "count": 10},
          {"name": "red", "count": 1},
          {"name": "yellow", "count": 20}
        ]
    }
    

    通过嵌套查询,示例如下:

    GET /my_index_01/_search
    {
        "query":  {
            "nested" : {
                "path" : "my_object",
                "query" : {
                    "bool" : {
                        "must" : [
                          { "match" : {"my_object.name" : "blue"} },
                          { "range" : {"my_object.count" : {"gt" : 5}} }
                        ]
                    }
                },
                "score_mode" : "avg"
            }
        }
    }
    
    nested查询顶级参数
    • path:(必需的,string)要搜索的嵌套对象的路径。
    • query:(必需的,查询object)
      (1)在路径中的嵌套对象上运行的查询。
      (2)可以使用包含完整路径(带点符号)搜索嵌套字段,比如my_object.name。
      (3)自动支持并检测多层嵌套,内部嵌套查询自动匹配相关嵌套级别。
    • score_mode:(可选的,string)表示匹配子对象的分数如何影响父文档的相关性分数。参数有效值如下:
      (1)avg(默认):使用所有匹配子对象的相关性得分的平均值。
      (2)max:使用所有匹配子对象中相关性得分最高值。
      (3)min:使用所有匹配子对象中相关性得分最低值。
      (4)none:不使用匹配子对象的相关性得分,设置父文档相关性得分为0。
      (5)sum:将所有匹配子对象的相关性得分相加。
    • ignore_unmapped:(可选的,boolean)表示是否忽略未映射的path字段。如果设置为true,那么Elasticsearch遇到未映射的path字段输入值将会忽略错误,并且不返回任何文档。默认值为false,默认情况下,如果path字段输入值未映射,Elasticsearch将返回一个错误。
    多级嵌套查询

    首先定义一个多级嵌套索引并索引数据,示例如下:

    PUT /my_index_02
    {
      "mappings": {
        "properties": {
          "driver": {
            "type": "nested",
            "properties": {
              "last_name": {
                "type": "text"
              },
              "vehicle": {
                "type": "nested",
                "properties": {
                  "make": {
                    "type": "text"
                  },
                  "model": {
                    "type": "text"
                  }
                }
              }
            }
          }
        }
      }
    }
    PUT /my_index_02/_doc/1
    {
      "driver": {
        "last_name": "McQueen",
        "vehicle": [
          {
            "make": "Powell Motors",
            "model": "Canyonero"
          },
          {
            "make": "Miller-Meteor",
            "model": "Ecto-1"
          }
        ]
      }
    }
    PUT /my_index_02/_doc/2?refresh
    {
      "driver": {
        "last_name": "Hudson",
        "vehicle": [
          {
            "make": "Mifune",
            "model": "Mach Five"
          },
          {
            "make": "Miller-Meteor",
            "model": "Ecto-1"
          }
        ]
      }
    }
    

    多级嵌套查询,示例如下:

    GET /my_index_02/_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查询

    如果连接(join)的子文档与所输入的查询匹配,那么返回父文档,可以使用连接(join)字段映射在同一个索引的文档之间创建父子关系,如果要使用has_child查询,索引必须包含一个连接(join)字段映射。
    使用has_child查询,首先创建包含连接(join)类型字段的索引,示例如下:

    PUT /my_index_03
    {
      "mappings": {
        "properties": {
          "my_num": {
            "type": "keyword"
          },
          "view_count": {
            "type": "integer"
          },
          "my-join-field": {
            "type": "join",
            "relations": {
              "parent": "child"
            }
          }
        }
      }
    }
    

    然后索引父文档和子文档,示例如下:

    # 创建父文档
    PUT /my_index_03/_doc/1
    {"my_num":"001", "view_count": 10, "my-join-field":{"name":"parent"}}
    # 创建子文档,parent指定父文档id
    PUT /my_index_03/_doc/2?routing=1&refresh
    {
      "my_num": "002",
      "view_count": 5,
      "my-join-field": {
        "name": "child",
        "parent": "1"
      }
    }
    

    使用has_child查询来查询文档中子文档匹配条件的文档,示例如下:

    GET my_index_03/_search
    {
      "query": {
        "has_child": {
          "type": "child",
          "query": {
            "match_all": {}
          },
          "max_children": 10,
          "min_children": 1,
          "score_mode": "min"
        }
      }
    }
    
    has_child查询顶级参数
    • type:(必需的,string)指定连接子关系的名称。
    • query:(必需的,查询object)在type字段指定名称的子文档上运行的查询。如果其子文档与搜索匹配,查询将返回父文档。
    • max_children:(可选的,integer)父文档中匹配的最大子文档数。如果父文档超过了这个限制,则从搜索结果中排除它。
    • min_children:(可选的,integer)父文档中匹配所需的最小子文档数。如果父文档不满足此限制,则从搜索结果中排除它。
    • score_mode:(可选的,string)表示匹配子文档的分数如何影响父文档的相关性分数。参数有效值如下:
      (1)none(默认):不使用匹配子文档的相关性得分,查询返回的父文档相关性得分为0。
      (2)max:使用所有匹配子文档中相关性得分最高值。
      (3)min:使用所有匹配子文档中相关性得分最低值。
      (4)avg:使用所有匹配子文档的相关性得分的平均值。
      (5)sum:将所有匹配子文档的相关性得分相加。
    • ignore_unmapped:(可选的,boolean)表示是否忽略未映射的type字段。默认值为false,默认情况下,如果type字段输入值未映射,Elasticsearch将返回一个错误。
    排序
    • 不支持标准排序选项对has_child查询的结果进行排序。
    • 如果需要对返回的文档进行排序,可以使用function_score查询并按_score排序。例如,下面的查询根据子文档的view_count字段对返回的文档进行排序,示例如下:
    GET my_index_03/_search
    {
      "query": {
        "has_child": {
          "type": "child",
          "query": {
            "function_score": {
              "script_score": {
                "script": "_score * doc['view_count'].value"
              }
            }
          },
          "score_mode": "max"
        }
      }
    }
    

    4. has_parent查询

    如果连接(join)的父文档与所输入的查询匹配,那么返回子文档,可以使用连接(join)字段映射在同一个索引的文档之间创建父子关系。如果要使用has_parent查询,索引必须包含一个连接(join)字段映射。(与has_child查询用法类似)
    使用has_parent查询,查询my_index_03索引中,文档的父文档中字段“my_num”值为“001”的子文档,示例如下:

    GET /my_index_03/_search
    {
      "query": {
        "has_parent": {
          "parent_type": "parent",
          "query":{"term":{"my_num":{"value":"001"}}}
        }
      }
    }
    

    返回匹配的子文档,结果片段如下:

    has_parent查询顶级参数
    • parent_type:(必需的,string)指定连接父关系的名称。
    • query:(必需的,查询object)在type字段指定名称的父文档上运行的查询。如果其父文档与搜索匹配,查询将返回子文档。
    • score:(可选的,boolean)表示是否将匹配父文档的相关性分数聚合到子文档中。默认值为false,默认情况下,Elasticsearch将忽略父文档的相关性得分。如果为true,则将匹配父文档的相关性得分聚合到子文档的相关性得分中。
    • ignore_unmapped:(可选的,boolean)表示是否忽略未映射的parent_type字段。默认值为false,默认情况下,如果parent_type字段输入值未映射,Elasticsearch将返回一个错误。
    排序
    • 不支持标准排序选项对has_parent查询的结果进行排序。
    • 如果需要对返回的文档进行排序,可以使用function_score查询并按_score排序。例如,下面的查询根据父文档的view_count字段对返回的文档进行排序,示例如下:
    GET /my_index_03/_search
    {
      "query": {
        "has_parent": {
          "parent_type": "parent",
          "score" : true,
          "query" : {
              "function_score" : {
                  "script_score": {
                      "script": "_score * doc['view_count'].value"
                  }
              }
          }
        }
      }
    }
    

    5. 父ID查询

    parent_id查询返回匹配指定父ID的子文档。
    例如,在my_index_03索引中,查询父ID等于1的子文档,示例如下:

    GET /my_index_03/_search
    {
      "query": {
        "parent_id": {
          "type": "child",
          "id": "1"
        }
      }
    }
    
    parent_id查询顶级参数
    • type:(必需的,string)指定连接子关系的名称。
    • id:(必需的,string)父文档的ID。查询将返回这个父文档的子文档。。
    • ignore_unmapped:(可选的,boolean)表示是否忽略未映射的type字段。默认值为false,默认情况下,如果type字段输入值未映射,Elasticsearch将返回一个错误。

    相关文章

      网友评论

          本文标题:Elasticsearch系列(15)Query之连接查询

          本文链接:https://www.haomeiwen.com/subject/mjhhyktx.html