连接查询

edit

在像Elasticsearch这样的分布式系统中执行全SQL风格的连接操作是非常昂贵的。相反,Elasticsearch提供了两种形式的连接,这些连接设计为可以水平扩展。

nested query
文档可能包含类型为 nested 的字段。这些字段用于索引对象数组,其中每个对象都可以作为独立文档进行查询(使用 nested 查询)。
has_child and has_parent queries
一个join字段关系可以在单个索引中的文档之间存在。has_child查询返回其子文档匹配指定查询的父文档,而has_parent查询返回其父文档匹配指定查询的子文档。

另请参阅 terms 查询中的 terms-lookup 机制,该机制允许您从另一个文档中包含的值构建 terms 查询。

注释

edit
允许昂贵的查询
edit

如果 search.allow_expensive_queries 设置为 false,则不会执行连接查询。

嵌套查询

edit

包装另一个查询以搜索 嵌套 字段。

嵌套查询会像对待单独索引的文档一样搜索嵌套字段对象。如果一个对象匹配搜索条件,嵌套查询会返回根父文档。

示例请求

edit

索引设置

edit

要使用 nested 查询,您的索引必须包含一个 nested 字段映射。例如:

PUT /my-index-000001
{
  "mappings": {
    "properties": {
      "obj1": {
        "type": "nested"
      }
    }
  }
}

示例查询

edit
GET /my-index-000001/_search
{
  "query": {
    "nested": {
      "path": "obj1",
      "query": {
        "bool": {
          "must": [
            { "match": { "obj1.name": "blue" } },
            { "range": { "obj1.count": { "gt": 5 } } }
          ]
        }
      },
      "score_mode": "avg"
    }
  }
}

顶级参数用于嵌套

edit
path
(必需,字符串)您希望搜索的嵌套对象的路径。
query

(必需,查询对象) 您希望在 path 中的嵌套对象上运行的查询。 如果一个对象匹配搜索,nested 查询将返回根父文档。

您可以使用包含完整路径的点表示法来搜索嵌套字段,例如 obj1.name

多级嵌套是自动支持的,并且会被检测到,从而导致内部嵌套查询自动匹配相关的嵌套级别,而不是根级别,如果它存在于另一个嵌套查询中。

参见多级嵌套查询示例。

score_mode

(可选,字符串) 指示匹配子对象的分数如何影响根父文档的 相关性分数。有效值为:

avg (默认)
使用所有匹配子对象的平均相关性分数。
max
使用所有匹配子对象的最高相关性分数。
min
使用所有匹配子对象的最低相关性分数。
none
不使用匹配子对象的相关性分数。查询为父文档分配一个 0 的分数。
sum
将所有匹配子对象的相关性分数相加。
ignore_unmapped

(可选,布尔值) 指示是否忽略未映射的 path 并且不返回任何文档而不是错误。默认为 false

如果 false,Elasticsearch 会在 path 是未映射字段时返回错误。

您可以使用此参数查询可能不包含字段 path 的多个索引。

注释

edit

脚本查询的上下文

edit

如果你在嵌套查询中运行一个脚本查询, 你只能访问嵌套文档的doc值,而不能访问父文档或根文档。

多级嵌套查询

edit

要了解多级嵌套查询的工作原理,首先需要一个包含嵌套字段的索引。 以下请求为 drivers 索引定义了映射,其中包含嵌套的 makemodel 字段。

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

接下来,将一些文档索引到drivers索引中。

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"
            }
        ]
    }
}

您现在可以使用多级嵌套查询 来根据makemodel字段匹配文档。

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" } }
              ]
            }
          }
        }
      }
    }
  }
}

搜索请求返回以下响应:

{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 3.7349272,
    "hits" : [
      {
        "_index" : "drivers",
        "_id" : "1",
        "_score" : 3.7349272,
        "_source" : {
          "driver" : {
            "last_name" : "McQueen",
            "vehicle" : [
              {
                "make" : "Powell Motors",
                "model" : "Canyonero"
              },
              {
                "make" : "Miller-Meteor",
                "model" : "Ecto-1"
              }
            ]
          }
        }
      }
    ]
  }
}

must_not 子句和 nested 查询

edit

如果一个嵌套查询匹配到一个文档中的一个或多个嵌套对象,它会将该文档作为命中返回。即使文档中的其他嵌套对象不匹配查询,也是如此。在使用包含内部must_not子句嵌套查询时,请记住这一点。

使用 inner_hits 参数来查看哪些嵌套对象匹配了 nested 查询。

例如,以下搜索使用了一个带有内部must_not子句的外部nested查询。

PUT my-index
{
  "mappings": {
    "properties": {
      "comments": {
        "type": "nested"
      }
    }
  }
}

PUT my-index/_doc/1?refresh
{
  "comments": [
    {
      "author": "kimchy"
    }
  ]
}

PUT my-index/_doc/2?refresh
{
  "comments": [
    {
      "author": "kimchy"
    },
    {
      "author": "nik9000"
    }
  ]
}

PUT my-index/_doc/3?refresh
{
  "comments": [
    {
      "author": "nik9000"
    }
  ]
}

POST my-index/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "must_not": [
            {
              "term": {
                "comments.author": "nik9000"
              }
            }
          ]
        }
      }
    }
  }
}

搜索返回:

{
  ...
  "hits" : {
    ...
    "hits" : [
      {
        "_index" : "my-index",
        "_id" : "1",
        "_score" : 0.0,
        "_source" : {
          "comments" : [
            {
              "author" : "kimchy"
            }
          ]
        }
      },
      {
        "_index" : "my-index",
        "_id" : "2",
        "_score" : 0.0,
        "_source" : {
          "comments" : [
            {
              "author" : "kimchy"              
            },
            {
              "author" : "nik9000"             
            }
          ]
        }
      }
    ]
  }
}

这个嵌套对象匹配查询。因此,搜索返回对象的父文档作为命中结果。

这个嵌套对象不匹配查询。由于同一文档中的另一个嵌套对象匹配查询,搜索仍然返回父文档作为命中。

要排除任何与nested查询匹配的嵌套对象的文档,请使用外部的must_not子句。

POST my-index/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "nested": {
            "path": "comments",
            "query": {
              "term": {
                "comments.author": "nik9000"
              }
            }
          }
        }
      ]
    }
  }
}

搜索返回:

{
  ...
  "hits" : {
    ...
    "hits" : [
      {
        "_index" : "my-index",
        "_id" : "1",
        "_score" : 0.0,
        "_source" : {
          "comments" : [
            {
              "author" : "kimchy"
            }
          ]
        }
      }
    ]
  }
}

子查询

edit

返回其连接的子文档匹配所提供查询的父文档。您可以使用连接字段映射在同一索引中的文档之间创建父子关系。

因为它执行了一个连接操作,has_child 比其他查询要慢。 随着指向唯一父文档的匹配子文档数量的增加,其性能会下降。每次搜索中的 has_child 查询都会显著增加查询时间。

如果你关心查询性能,请不要使用此查询。如果你需要使用has_child查询,请尽可能少地使用它。

示例请求

edit

索引设置

edit

要使用 has_child 查询,您的索引必须包含一个 join 字段映射。例如:

PUT /my-index-000001
{
  "mappings": {
    "properties": {
      "my-join-field": {
        "type": "join",
        "relations": {
          "parent": "child"
        }
      }
    }
  }
}

示例查询

edit
GET /_search
{
  "query": {
    "has_child": {
      "type": "child",
      "query": {
        "match_all": {}
      },
      "max_children": 10,
      "min_children": 2,
      "score_mode": "min"
    }
  }
}

顶级参数为 has_child

edit
type
(必需,字符串) 为 join 字段映射的子关系的名称。
query
(必需,查询对象) 您希望在 type 字段的子文档上运行的查询。如果子文档匹配搜索条件,查询将返回父文档。
ignore_unmapped

(可选,布尔值) 指示是否忽略未映射的 type 并且不返回任何文档而不是错误。默认为 false

如果为false,当type未映射时,Elasticsearch会返回错误。

您可以使用此参数来查询可能不包含type的多个索引。

max_children
(可选,整数) 返回的父文档允许匹配 query 的子文档的最大数量。如果父文档超过此限制,它将从搜索结果中排除。
min_children
(可选, 整数) 匹配 query 的子文档的最小数量,要求返回的父文档满足此条件。如果父文档不满足此限制,则将其从搜索结果中排除。
score_mode

(可选,字符串) 指示匹配子文档的分数如何影响根父文档的 相关性分数。有效值为:

none (默认)
不使用匹配子文档的相关性分数。查询为父文档分配一个分数为 0
avg
使用所有匹配子文档的平均相关性分数。
max
使用所有匹配子文档中的最高相关性分数。
min
使用所有匹配子文档中的最低相关性分数。
sum
将所有匹配子文档的相关性分数相加。

注释

edit

排序

edit

您不能使用标准的排序选项has_child查询的结果进行排序。

如果您需要根据子文档中的字段对返回的文档进行排序,请使用function_score查询并按_score排序。例如,以下查询根据子文档的click_count字段对返回的文档进行排序。

GET /_search
{
  "query": {
    "has_child": {
      "type": "child",
      "query": {
        "function_score": {
          "script_score": {
            "script": "_score * doc['click_count'].value"
          }
        }
      },
      "score_mode": "max"
    }
  }
}

有父查询

edit

返回其连接的父文档与提供的查询匹配的子文档。您可以使用连接字段映射在同一索引中的文档之间创建父子关系。

由于它执行了一个连接操作,has_parent 查询相比其他查询速度较慢。 随着匹配的父文档数量的增加,其性能会下降。 每次搜索中的 has_parent 查询都会显著增加查询时间。

示例请求

edit

索引设置

edit

要使用 has_parent 查询,您的索引必须包含一个 join 字段映射。例如:

PUT /my-index-000001
{
  "mappings": {
    "properties": {
      "my-join-field": {
        "type": "join",
        "relations": {
          "parent": "child"
        }
      },
      "tag": {
        "type": "keyword"
      }
    }
  }
}

示例查询

edit
GET /my-index-000001/_search
{
  "query": {
    "has_parent": {
      "parent_type": "parent",
      "query": {
        "term": {
          "tag": {
            "value": "Elasticsearch"
          }
        }
      }
    }
  }
}

顶级参数用于 has_parent

edit
parent_type
(必需,字符串) 为 join 字段映射的父关系的名称。
query
(必需,查询对象) 您希望在 parent_type 字段的父文档上运行的查询。如果父文档匹配搜索,查询将返回其子文档。
score

(可选,布尔值) 指示是否将匹配的父文档的相关性得分聚合到其子文档中。默认为 false

如果为false,Elasticsearch 将忽略父文档的相关性得分。Elasticsearch 还会为每个子文档分配一个相关性得分,该得分等于queryboost值,默认值为1

如果 true,匹配的父文档的相关性分数会被聚合到其子文档的相关性分数中。

ignore_unmapped

(可选,布尔值) 指示是否忽略未映射的 parent_type 并且不返回任何文档而不是错误。默认为 false

如果为false,当parent_type未映射时,Elasticsearch会返回错误。

您可以使用此参数来查询可能不包含parent_type的多个索引。

注释

edit

排序

edit

您不能使用标准的排序选项has_parent查询的结果进行排序。

如果你需要根据父文档中的字段对返回的文档进行排序,请使用function_score查询并按_score排序。例如,以下查询根据父文档的view_count字段对返回的文档进行排序。

GET /_search
{
  "query": {
    "has_parent": {
      "parent_type": "parent",
      "score": true,
      "query": {
        "function_score": {
          "script_score": {
            "script": "_score * doc['view_count'].value"
          }
        }
      }
    }
  }
}

父ID查询

edit

返回与特定父文档连接的子文档。 您可以使用连接字段映射在同一索引中的文档之间创建父子关系。

示例请求

edit

索引设置

edit

要使用 parent_id 查询,您的索引必须包含一个 join 字段映射。要了解如何为 parent_id 查询设置索引,请尝试以下示例。

  1. 创建一个带有join字段映射的索引。

    PUT /my-index-000001
    {
      "mappings": {
        "properties": {
          "my-join-field": {
            "type": "join",
            "relations": {
              "my-parent": "my-child"
            }
          }
        }
      }
    }
  2. 索引一个ID为1的父文档。

    PUT /my-index-000001/_doc/1?refresh
    {
      "text": "这是一个父文档。",
      "my-join-field": "my-parent"
    }
  3. 索引父文档的子文档。

    PUT /my-index-000001/_doc/2?routing=1&refresh
    {
      "text": "这是一个子文档。",
      "my-join-field": {
        "name": "my-child",
        "parent": "1"
      }
    }

示例查询

edit

以下搜索返回ID为1的父文档的子文档。

GET /my-index-000001/_search
{
  "query": {
      "parent_id": {
          "type": "my-child",
          "id": "1"
      }
  }
}

顶级参数为 parent_id

edit
type
(必需,字符串) 为 join 字段映射的子关系的名称。
id
(必需,字符串) 父文档的ID。查询将返回此父文档的子文档。
ignore_unmapped

(可选,布尔值) 指示是否忽略未映射的 type 并且不返回任何文档而不是错误。默认为 false

如果为false,当type未映射时,Elasticsearch会返回错误。

您可以使用此参数来查询可能不包含type的多个索引。