Получение точного соответствия с помощью Elastic Search 6 и php ClientBuilder

Я создаю многоуровневый навигационный модуль с поддержкой elasticsearch для сайта ecomm. Все отлично работает, я могу получить параметры из внешнего источника и отобразить их. Их выбор тоже работает, но я столкнулся с проблемой, когда один из параметров фильтра имеет эти варианты;

FINISHES:

Finished (1)

Semi-Finished (16)

Semi Finished (1)

Ясно, что 2 варианта с дефисом и без него следует привести в порядок, но на мгновение игнорируя это, когда я применяю следующее к своей коллекции;

$client = $this->clientBuilder;
$params .... etc
$params['body']['query']['bool']['must'][] = ['match_phrase' => [$split[0] => "$selected"]];
$response = $client->search($params);

Где $split[0] — ссылка на поле elasticsearch для «ОТДЕЛКИ», а $selected — выбранное значение. Если вы нажмете на любой из вариантов, я верну все 18 записей. Несомненно, потому что все они содержат одно из искомых слов «завершено».

Как сделать этот поиск только по точному термину? Я пытался избежать дефиса с помощью \-, что не помогло, я также пытался проверить, есть ли в искомом термине пробелы или дефисы, и попытался принудительно добавить их в «must_not», но это тоже не сработало;

if(!$space) {
    $params['body']['query']['bool']['must_not'][] = ['match' => [$split[0] => ' ']];
}
if(!$hyphen) {
    $params['body']['query']['bool']['must_not'][] = ['match' => [$split[0] => '\\-']];
}

person PixieMedia    schedule 01.05.2019    source источник
comment
Вы проанализировали поле? если нет, то стандартный анализатор пропустит дефисы при индексации. Вы пробовали искать с помощью .keyword?   -  person Polynomial Proton    schedule 01.05.2019
comment
все поля являются стандартными, мы будем использовать их для нечеткого поиска в других контекстах, только для многоуровневого поиска мы хотим возвращать результаты буквального 100% совпадения. Как работает .keyword?   -  person PixieMedia    schedule 01.05.2019
comment
.keyword выполняет поиск по исходному тексту, т. е. не проанализированному. по умолчанию ко всем полям применяется стандартный анализатор. Таким образом, в вашем случае Semi-Finished является ключевым словом, а инвертированный индекс будет содержать два слова semi и finished, поэтому каждый раз, когда вы ищете finished, он соответствует синусоидальному стандартному анализатору, разбивает его на дефис. Я не знаю php-код, который вы написали, однако синтаксис fieldname.keyword, и я уверен, что его можно включить сюда.   -  person Polynomial Proton    schedule 01.05.2019
comment
гений! Это отлично работает - вставьте это в ответ, и я приму это за вас. Спасибо за чаевые   -  person PixieMedia    schedule 01.05.2019
comment
Нет проблем. Я рад, что это помогло   -  person Polynomial Proton    schedule 01.05.2019


Ответы (1)


По умолчанию ко всем полям применяется стандартный анализатор. Итак, в вашем случае Semi-Finished - это keyword, а инвертированный индекс будет содержать два слова semi и finished, поэтому каждый раз, когда вы ищете готовое, оно совпадает, поскольку стандартный анализатор разбивает его на дефис.

POST _analyze
{
  "analyzer": "standard",
  "text": ["Semi-Finished"]
}

##Result
{
  "tokens" : [
    {
      "token" : "semi",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "finished",
      "start_offset" : 5,
      "end_offset" : 13,
      "type" : "<ALPHANUM>",
      "position" : 1
    }
  ]
}

.keyword выполняет поиск по исходному тексту, т. е. не проанализированному. В вашем случае fieldname.keyword должно работать.

POST _analyze
{
  "analyzer": "keyword",
  "text": ["Semi-Finished"]
}

##Result
{
  "tokens" : [
    {
      "token" : "Semi-Finished",
      "start_offset" : 0,
      "end_offset" : 13,
      "type" : "word",
      "position" : 0
    }
  ]
}
person Polynomial Proton    schedule 01.05.2019
comment
отлично, в php я изменил имя поля следующим образом; $field = $split[0].'.keyword'; а затем назвал это так; $params['body']['query']['bool']['must'][] = ['match_phrase' =› [$field =› $selected]]; - задача решена - person PixieMedia; 01.05.2019