查询嵌套和父属性查询的弹性搜索

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