连接查询
edit连接查询
edit在像Elasticsearch这样的分布式系统中执行全SQL风格的连接操作是非常昂贵的。相反,Elasticsearch提供了两种形式的连接,这些连接设计为可以水平扩展。
-
nestedquery -
文档可能包含类型为
nested的字段。这些字段用于索引对象数组,其中每个对象都可以作为独立文档进行查询(使用nested查询)。 -
has_childandhas_parentqueries -
一个
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"
}
}
}
}
示例查询
editGET /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要了解多级嵌套查询的工作原理,首先需要一个包含嵌套字段的索引。
以下请求为 drivers 索引定义了映射,其中包含嵌套的 make 和 model 字段。
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"
}
]
}
}
您现在可以使用多级嵌套查询
来根据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" } }
]
}
}
}
}
}
}
}
搜索请求返回以下响应:
{
"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"
}
}
}
}
}
示例查询
editGET /_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"
}
}
}
}
示例查询
editGET /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 还会为每个子文档分配一个相关性得分,该得分等于query的boost值,默认值为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 查询设置索引,请尝试以下示例。
-
创建一个带有join字段映射的索引。
PUT /my-index-000001 { "mappings": { "properties": { "my-join-field": { "type": "join", "relations": { "my-parent": "my-child" } } } } } -
索引一个ID为
1的父文档。PUT /my-index-000001/_doc/1?refresh { "text": "这是一个父文档。", "my-join-field": "my-parent" } -
索引父文档的子文档。
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"
}
}
}