ElasticSearch return 仅文档的特定部分

ElasticSearch return only specific part of the document

我有一个模仿以下结构的 JSON 文档。

{
"mydata": [
      {
        "Key1": "Hello",
        "Key2": "this",
        "Key3": "is",
        "Key4": "line one",
        "Key5": "of the file"
      },
      {
        "Key1": "Hello",
        "Key2": "this",
        "Key3": "is",
        "Key4": "line two",
        "Key5": "of the file"
      }]
}

我使用的索引本身没有任何特定的映射。我可以写一个自由文本的 Lucene 查询,比如

mydata.Key4:"line one"

结果是 return 整个文档。但是,就我而言,我只想检索 JSON 对象的第一部分作为结果。有办法实现吗?

{
        "Key1": "Hello",
        "Key2": "this",
        "Key3": "is",
        "Key4": "line one",
        "Key5": "of the file"
}

我发现我可以使用 _source_includes 检索特定字段并传递所需的键,但是,我无法找到与 return 的特定部分中的所有键等效的JSON 与查询匹配的文档。是因为文件的索引方式吗?有人可以在这里指导我吗?

编辑:

我删除了我的索引并更新了映射如下

{
"mappings" : {
     
  "properties" : {
   "data" : {
    "type" : "nested"
   }
  }
 }
}

我重新索引了文档,快速浏览了 ES 文档和 运行 以下嵌套查询。

{
"_source": false,
  "query": {
       "nested": {
          "path": "data",
          "query": {
          "match": { 
               "data.Key4": "line one" 
          }
       },
       "inner_hits": {} 
  }
 }
}

但是,这也是 return 我索引中的所有文档,除了现在 returned 结果在 inner_hits

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 0.52889514,
        "hits": [{
            "_index": "myindex",
            "_type": "_doc",
            "_id": "QAZJ-nMBi6fwNevjDQJy",
            "_score": 0.52889514,
            "inner_hits": {
                "data": {
                    "hits": {
                        "total": {
                            "value": 2,
                            "relation": "eq"
                        },
                        "max_score": 0.87546873,
                        "hits": [{
                            "_index": "myindex",
                            "_type": "_doc",
                            "_id": "QAZJ-nMBi6fwNevjDQJy",
                            "_nested": {
                                "field": "data",
                                "offset": 0
                            },
                            "_score": 0.87546873,
                            "_source": {
                                "Key1": "Hello",
                                "Key2": "this",
                                "Key3": "is",
                                "Key4": "line one",
                                "Key5": "of the file"
                            }
                        }, {
                            "_index": "myindex",
                            "_type": "_doc",
                            "_id": "QAZJ-nMBi6fwNevjDQJy",
                            "_nested": {
                                "field": "data",
                                "offset": 1
                            },
                            "_score": 0.18232156,
                            "_source": {
                                "Key1": "Hello",
                                "Key2": "this",
                                "Key3": "is",
                                "Key4": "line two",
                                "Key5": "of the file"
                            }
                        }]
                    }
                }
            }
        }]
    }
}

我是不是漏掉了什么?

因为您没有定义 mapping,这是主要问题。当您按照您提到的方式保存数据时,它将作为 text.

类型的单独属性保存

当您执行搜索时,它会带来整个文档。但是,如果您为 mydata 定义 nested 映射,那么您可以使用 inner_hits 来仅检索匹配的文档。

编辑:

要使用的查询:

{
  "_source": false,
  "query": {
    "nested": {
      "path": "data",
      "inner_hits": {        
      },
      "query": {
        "bool": {
          "must": [
            {
              "term": { //To look for exact match
                "data.Key4.keyword": "line one" //need to match line one not line two
              }
            }
          ]
        }
      }
    }
  }
}

当你使用 match 时会发生什么:

line one 将被标记如下

{
    "tokens": [
        {
            "token": "line",
            "start_offset": 0,
            "end_offset": 4,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "one",
            "start_offset": 5,
            "end_offset": 8,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

类似地,它创建了两个标记 linetwo

所以当你使用match时,它是全文搜索查询。它确实分析了索引时间和搜索时间。因此在搜索期间,line one 将被分析,ES 将查找 lineoneline two 包含标记 line 因此这也是结果的一部分。

要避免这种情况,您必须避免分析。所以必须使用term queries。它寻找完全匹配。