查询嵌套和父属性查询的弹性搜索
Elastic Search querying a nested and parent attribute query
我有一个弹性文件如下。
{
"process_id" : "123",
"user_info" : [{
"first_name":"A",
"last_name: "B"
}]
}
{
"process_id" : "123",
"user_info" : [{
"first_name":"C",
"last_name: "B"
},
{"first_name" : "A",
"last_name":"D"
} ]
}
场景 1:
我还没有为 "user_info" 字段设置嵌套类型。
我搜索 "process_id" 为 123,first_name 为 A,last_name 为
B,我得到了结果中的两个文档。
场景二:
搜索returns出错。看来我将无法搜索嵌套项和父项中的项。
查询如下:
{
"query": {
"query_string": {
"query": "process_id:123",
"nested": {
"path": "user_info",
"query": {
"query_string": {
"query": "(user_info.first_name:A AND user_info.last_name:B"
}
}
}
} } }
错误响应如下。
{
"error": {
"root_cause": [
{
"type": "parsing_exception",
"reason": "[query_string] unknown token [START_OBJECT] after [nested]",
"line": 1
}
],
"type": "parsing_exception",
"reason": "[query_string] unknown token [START_OBJECT] after [nested]",
"line": 1,
},
"status": 400
}
理想的响应应该是当我搜索 process_id 为 123,first_name 为 A 和 last_name 为 B 时,只需要返回第一个文档。
注意:属性名称特意保持通用,以便说明实际情况。
我可以在您的场景 2 中看到以下 2 个问题
- 要合并您需要使用
bool
-query 的查询
- 为了使
nested
-queries 工作,您需要将 "parent"-field 定义为 nested
-field
1.在您的映射中将字段 user_info
声明为 nested
类型:
PUT processes
{
"mappings": {
"properties": {
"process_id": {
"type": "keyword"
},
"user_info": {
"type": "nested",
"properties": {
"first_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"last_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
注意: user_info
的映射带有额外的行 "type": "nested"
2。索引您提供的 2 个示例文档
POST processes/_bulk
{"index":{"_id":1}}
{"process_id": "123", "user_info": [{"first_name": "A", "last_name": "B"}]}
{"index":{"_id":2}}
{"process_id": "123", "user_info": [{"first_name": "C", "last_name": "B"},{"first_name": "A", "last_name": "D"}]}
3。使用 nested
-query
查询 first_name
和 last_name
的组合
GET processes/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"process_id": {
"value": "123"
}
}
},
{
"nested": {
"path": "user_info",
"query": {
"bool": {
"must": [
{
"match": {
"user_info.first_name": "A"
}
},
{
"match": {
"user_info.last_name": "B"
}
}
]
}
}
}
}
]
}
}
}
注意: search_request 搜索匹配 process_id (123) 和 user_info.first_name
和 [= 的组合的所有文档25=] 对于一个特定用户(而不是跨用户)。在上面的设置中,查询只匹配文档 1。
如果您希望 Elasticsearch 还告诉您哪个 user_info 导致了匹配(如果一个进程有多个 user_info 对象),您可以将以下子句添加到您的嵌套查询中:"inner_hits": {}
。
您可能想知道为什么我将字段 process_id
映射到 keyword
字段。这是最佳做法,因为 keyword
是存储 ID 的最有效类型。
Elasticsearch 文档中的引用:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
2019 年 10 月 13 日更新: 添加了使用 queryString
-query
的版本
GET processes/_search
{
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "process_id:123"
}
},
{
"nested": {
"path": "user_info",
"query": {
"query_string": {
"query": "user_info.first_name:A AND user_info.last_name:B"
}
}
}
}
]
}
}
}
我有一个弹性文件如下。
{
"process_id" : "123",
"user_info" : [{
"first_name":"A",
"last_name: "B"
}]
}
{
"process_id" : "123",
"user_info" : [{
"first_name":"C",
"last_name: "B"
},
{"first_name" : "A",
"last_name":"D"
} ]
}
场景 1:
我还没有为 "user_info" 字段设置嵌套类型。 我搜索 "process_id" 为 123,first_name 为 A,last_name 为 B,我得到了结果中的两个文档。
场景二:
搜索returns出错。看来我将无法搜索嵌套项和父项中的项。
查询如下:
{
"query": {
"query_string": {
"query": "process_id:123",
"nested": {
"path": "user_info",
"query": {
"query_string": {
"query": "(user_info.first_name:A AND user_info.last_name:B"
}
}
}
} } }
错误响应如下。
{
"error": {
"root_cause": [
{
"type": "parsing_exception",
"reason": "[query_string] unknown token [START_OBJECT] after [nested]",
"line": 1
}
],
"type": "parsing_exception",
"reason": "[query_string] unknown token [START_OBJECT] after [nested]",
"line": 1,
},
"status": 400
}
理想的响应应该是当我搜索 process_id 为 123,first_name 为 A 和 last_name 为 B 时,只需要返回第一个文档。
注意:属性名称特意保持通用,以便说明实际情况。
我可以在您的场景 2 中看到以下 2 个问题
- 要合并您需要使用
bool
-query 的查询
- 为了使
nested
-queries 工作,您需要将 "parent"-field 定义为nested
-field
1.在您的映射中将字段 user_info
声明为 nested
类型:
PUT processes
{
"mappings": {
"properties": {
"process_id": {
"type": "keyword"
},
"user_info": {
"type": "nested",
"properties": {
"first_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"last_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
注意: user_info
的映射带有额外的行 "type": "nested"
2。索引您提供的 2 个示例文档
POST processes/_bulk
{"index":{"_id":1}}
{"process_id": "123", "user_info": [{"first_name": "A", "last_name": "B"}]}
{"index":{"_id":2}}
{"process_id": "123", "user_info": [{"first_name": "C", "last_name": "B"},{"first_name": "A", "last_name": "D"}]}
3。使用 nested
-query
first_name
和 last_name
的组合
GET processes/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"process_id": {
"value": "123"
}
}
},
{
"nested": {
"path": "user_info",
"query": {
"bool": {
"must": [
{
"match": {
"user_info.first_name": "A"
}
},
{
"match": {
"user_info.last_name": "B"
}
}
]
}
}
}
}
]
}
}
}
注意: search_request 搜索匹配 process_id (123) 和 user_info.first_name
和 [= 的组合的所有文档25=] 对于一个特定用户(而不是跨用户)。在上面的设置中,查询只匹配文档 1。
如果您希望 Elasticsearch 还告诉您哪个 user_info 导致了匹配(如果一个进程有多个 user_info 对象),您可以将以下子句添加到您的嵌套查询中:"inner_hits": {}
。
您可能想知道为什么我将字段 process_id
映射到 keyword
字段。这是最佳做法,因为 keyword
是存储 ID 的最有效类型。
Elasticsearch 文档中的引用:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
2019 年 10 月 13 日更新: 添加了使用 queryString
-query
GET processes/_search
{
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "process_id:123"
}
},
{
"nested": {
"path": "user_info",
"query": {
"query_string": {
"query": "user_info.first_name:A AND user_info.last_name:B"
}
}
}
}
]
}
}
}