【问题标题】:ElasticSearch: Exact match on Keyword datatype field with array of valuesElasticSearch:关键字数据类型字段与值数组的完全匹配
【发布时间】:2020-11-10 05:56:21
【问题描述】:

在 ElasticSearch 中,我有一个电子邮件字段和标题字段的映射,如下所示:

  {
  "person": {
    "mappings": {
      "_doc": {
         "email": {
           "type": "keyword",
           "boost": 80
          },
          "title": {
          "type": "text",
           "boost": 70
          }
       }
     }
   }
 

每个人可以拥有多个电子邮件地址和职位。所以,我将值存储在数组中。 我使用 query_string 来搜索具有电子邮件地址和/或头衔的人。电子邮件地址需要完全匹配。

我已使用以下数据为文档编制索引。在 Kibana 中调用 GET person/_search 将在结果中生成以下文档。

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "person",
        "_type": "_doc",
        "_id": "101",
        "_score": 1,
        "_source": {
          "title": """["Actor", "Hero", "Model"]""",
          "email": """["jdepp@hotmail.com", "johnny@hollywood.com", "jdepp@gmail.com", "johnny.depp@yahoo.com"]""",
          "SEARCH_ENTITY": "PERSON"
        }
      }
    ]
  }
}

现在,当我添加一些电子邮件搜索参数时,我不会在结果中返回文档。记住电子邮件是关键字类型。

请求:

GET person/_search
{
  "query" : {
    "query_string" : {
      "query" : "SEARCH_ENTITY:PERSON AND (email: (johnny.depp@yahoo.com))"
    }
  }
}

回复:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

但同样的查询也适用于文本类型的标题字段。

请求:

GET person/_search
{
  "query" : {
    "query_string" : {
      "query" : "SEARCH_ENTITY:PERSON AND (title: ((actor)))"
    }
  }
}

回复:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 20.137747,
    "hits": [
      {
        "_index": "person",
        "_type": "_doc",
        "_id": "101",
        "_score": 20.137747,
        "_source": {
           "ID": "101",
           "title": """["Actor", "Hero", "Model"]""",
           "email": """["jdepp@hotmail.com", "johnny@hollywood.com", "jdepp@gmail.com", "johnny.depp@yahoo.com"]"""
         }
      }
    ]
  }
}
       

有人可以告诉我我需要做什么才能使这项工作适用于关键字类型的电子邮件字段吗?

注意:如果我只存储一个电子邮件地址而不使用数组,它可以正常工作。

谢谢。

【问题讨论】:

    标签: elasticsearch kibana elasticsearch-6.5


    【解决方案1】:

    确保在索引文档之前像这样解析 titleemail 中的 json 数组字符串:

    POST person/_doc/101
    {
      "title": [
        "Actor",
        "Hero",
        "Model"
      ],
      "email": [
        "jdepp@hotmail.com",
        "johnny@hollywood.com",
        "jdepp@gmail.com",
        "johnny.depp@yahoo.com"
      ],
      "SEARCH_ENTITY": "PERSON"
    }
    

    无需更改映射,只需更改字段值即可。

    【讨论】:

    • 当我从 ElasticSearch 中检索文档时,我看到的标题和电子邮件字段如下所示: "title": """["Actor", "Hero", "Model"]""", "email": """["jdepp@hotmail.com", "johnny@hollywood.com", "jdepp@gmail.com", "johnny.depp@yahoo.com"]""" 这让我觉得数组值的索引正确,我不对吗?我不明白为什么数组的开头和结尾都有3个双引号。
    • 这就是你索引它们的方式。三重引号是提高可读性的 Kibana 约定,因为通常,在严格有效的 JSON 中,您必须转义像 "[\"Actor\"... 这样的引号。长话短说,您已经索引了应该是字符串数组的字符串。
    • 感谢您对三引号的解释。我用转义的双引号和数组传递值。还是不行。 "[\"演员\"、\"英雄\"、\"模特\"]"
    • 还是不行。按照我的回答中提到的那样通过它。没有前导引号...
    • 如果我按照您在示例中列出的那样传递数组,它就可以工作。但我需要使用 PUT API 将 JSON 正文传递给 ElasticSearch。在正文中,我将这些电子邮件作为 JSONArray 对象传递。在这种情况下,这是行不通的。看起来 ElasticSearch 认为整个数组是一个字符串值。任何想法如何将数组作为 JSON 传递?谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 2022-06-12
    • 1970-01-01
    • 2022-10-05
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多