Получение точного соответствия с Elastic Search 6 и php ClientBuilder - PullRequest
0 голосов
/ 01 мая 2019

Я создаю многоуровневый навигационный модуль с эластичным поиском для сайта 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] - это поле упругого поиска ref для 'FINISHES', а $ 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] => '\\-']];
}

1 Ответ

1 голос
/ 01 мая 2019

По умолчанию стандартный анализатор применяется ко всем полям.Так что в вашем случае 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
    }
  ]
}
...