ElasticSearch начинается с запроса на автозаполнение - PullRequest
1 голос
/ 30 января 2020

Я хочу создать функцию автозаполнения, используя ElasticSearch и C#. Но я не получаю желаемого результата. Для демонстрации это то, что я сделал.

1) Создан индекс под названием "names":

PUT names?pretty

2) Добавлено 20 записей с использованием команды POST:

POST names/_doc/1
{
  "name" : "John Smith"
}

3) Список имен:

[ "John Smith", "John Smitha", "John Smithb", "John Smithc", "John Smithd", "John Smithe", "John Smithf",
  "John Smithg", "John Smithh", "John Smithi", "Smith John", "Smitha John", "Smithb John", "Smithc John",
  "Smithd John", "Smithe John", "Smithf John", "Smithg John", "Smithh John", "Smithi John",]

4) Когда я запускаю запрос префикса:

GET names/_search
{
  "query": {
    "prefix": {
      "name": {
        "value": "Smith"
      }
    }
  }
}

Я ожидаю получить обратно "Smith John", "Smitha John" ... Но я получаю назад "John Smith", "John Smitha" ...

Что я делаю не так? Что мне нужно изменить и где?

Ответы [ 2 ]

2 голосов
/ 30 января 2020

Вы определяете свое поле name как поле text, которое по умолчанию использует стандартный анализатор и преобразует токены в нижний регистр. Вы можете проверить это, используя анализ API из ES.

Пример токенов для анализатора ключевых слов

URL: - http: // {{hostname}}: {{ port}} / {{index}} / _ анализ

{
  "text": "John Smith",
  "analyzer" : "keyword"
}

Вывод вышеуказанного API

{
    "tokens": [
        {
            "token": "John Smith",
            "start_offset": 0,
            "end_offset": 10,
            "type": "word",
            "position": 0
        }
    ]
}

Обратите внимание, что он не ломает text и сохраняет его в том виде, как объяснено в официальный ES do c.

Токены со стандартным анализатором

{
  "text": "Smith John",
  "analyzer" : "standard"
}

Вывод вышеуказанного API:

{
    "tokens": [
        {
            "token": "john",
            "start_offset": 0,
            "end_offset": 4,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "smith",
            "start_offset": 5,
            "end_offset": 10,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

Теперь, когда префиксный запрос не анализируется, отправьте его как есть. ES, поэтому Smith уведомление с заглавной буквы S будет отправлено в ES для сопоставления токенов, теперь с обновленным сопоставлением, только документы, начинающиеся с Smith, будут иметь этот префикс, и только они будут появляться в результатах поиска.

Отображение

{
    "mappings": {
        "properties": {
            "name": {
                "type": "text",
                "analyzer": "keyword"
            }
        }
    }
}

Поисковый запрос

{
    "query": {
        "prefix": {
            "name": {
                "value": "Smith"
            }
        }
    }
}

РЕДАКТИРОВАТЬ: : - ** Обновлен параметр на основе комментариев OP и на основе вышеуказанных параметров и поиска запрос, он получает только результаты, начинающиеся с Smith, как показано ниже:

{
  "took": 811,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "59977669",
        "_type": "_doc",
        "_id": "6",
        "_score": 1.0,
        "_source": {
          "name": "Smith John"
        }
      },
      {
        "_index": "59977669",
        "_type": "_doc",
        "_id": "7",
        "_score": 1.0,
        "_source": {
          "name": "Smithb John"
        }
      },
      {
        "_index": "59977669",
        "_type": "_doc",
        "_id": "8",
        "_score": 1.0,
        "_source": {
          "name": "Smithc John"
        }
      },
      {
        "_index": "59977669",
        "_type": "_doc",
        "_id": "9",
        "_score": 1.0,
        "_source": {
          "name": "Smithd John"
        }
      },
      {
        "_index": "59977669",
        "_type": "_doc",
        "_id": "10",
        "_score": 1.0,
        "_source": {
          "name": "Smithe John"
        }
      }
    ]
  }
}

Примечание: Этот блог охватывает различные способы реализации автозаполнения с компромиссами.

1 голос
/ 31 января 2020

Вам необходимо выполнить запрос префикса в поле name.keyword, а не в поле name.

GET names/_search
{
  "query": {
    "prefix": {
      "name.keyword": {
        "value": "Smith"
      }
    }
  }
}

Причина в том, что поле name.keyword имеет тип keyword и не анализируется (т. Е. Один токен John Smith проиндексирован), и, следовательно, вы можете выполнить и запрос на точное совпадение с ним. Поле name имеет тип типа text и анализируется (т. Е. Два токена john и smith проиндексированы), и, следовательно, ваш запрос на точное совпадение (или совпадение префикса) не работает.

Подробнее об этом можно прочитать здесь

...