ElasticSearch: точное совпадение поля типа данных ключевого слова с массивом значений

#elasticsearch #kibana #elasticsearch-6.5

#elasticsearch #kibana #elasticsearch-6.5

Вопрос:

В ElasticSearch у меня есть сопоставление для поля электронной почты и поля заголовка, как указано ниже:

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

У каждого пользователя может быть более одного адреса электронной почты и должности. Итак, я сохраняю значения в массивах.
Я использую query_string для поиска людей с адресом электронной почты и / или названием. Адрес электронной почты должен точно совпадать.

Я проиндексировал документ со следующими данными. Вызов GET person/_search в Kibana приведет к следующему документу в результате.

 {
  "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": []
  }
}
  

Но такой же запрос работает для поля заголовка, которое имеет тип text.

Запрос:

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

Может кто-нибудь сказать мне, что мне нужно сделать, чтобы это работало для поля электронной почты, которое имеет тип ключевого слова?

Примечание: если я сохраняю только один адрес электронной почты без использования массива, он работает нормально.

Спасибо.

Ответ №1:

Убедитесь, что вы проанализировали строки массива json title и email тому подобное, прежде чем индексировать свои документы:

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

Ничего не нужно менять в сопоставлении — только значения полей.

Комментарии:

1. Когда я извлекаю документ из ElasticSearch, я вижу поля заголовка и электронной почты следующим образом: «заголовок»: «»» [«Актер», «Герой», «Модель»] «»», «электронная почта»: «»» [«jdepp@hotmail.com «, «johnny@hollywood.com «, «jdepp@gmail.com», «johnny.depp@yahoo.com «]»»» Это заставляет меня думать, что значения массива проиндексированы правильно, разве я не прав? Я не понимаю, почему в начале и в конце массивов есть 3 двойные кавычки.

2. Ну, вот как вы их проиндексировали. Тройные кавычки — это соглашение Kibana, которое улучшает читаемость, потому что обычно, в строго допустимом JSON, вам нужно было бы избегать кавычек, подобных "["Actor"... . Короче говоря, вы проиндексировали строки, которые должны были быть массивами строк.

3. Спасибо за объяснение тройных кавычек. Я передаю значения с экранированными двойными кавычками и в массив. По-прежнему не работает. «[«Актер», «Герой», «Модель»]»

4. Все еще не это. Передайте его, как указано в моем ответе. Нет начальных кавычек…

5. Если я передам массив, как вы указали в вашем примере, это сработает. Но мне нужно передать тело JSON в ElasticSearch с помощью PUT API. Внутри тела я передаю эти электронные письма как объект JSONArray. В этом случае это не сработает. Похоже, ElasticSearch считает, что весь массив представляет собой одно строковое значение. Есть идеи, как я могу передать массив в формате JSON? Спасибо.