Как включить prefixLength в запрос Elasticsearch, созданный с использованием HibernateSearch QueryDSL - PullRequest
0 голосов
/ 28 марта 2019

Мы используем Hibernate Search 5.10.3. Финал с сервером Elasticsearch 5.6.6.

При создании нечеткого запроса для передачи FullTextSession :: createFullTextQuery я устанавливаю editDistance и prefixLength, но яиз журналов заметил, что фактический запрос, отправляемый в Elasticsearch, НЕ содержит prefixLength.

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

QueryBuilder qb = fts.getSearchFactory()
    .buildQueryBuilder()
    .forEntity(Vendor.class)
    .get();

BooleanJunction namesBool = qb.bool();

String field = "vendorNames.vendorName";
String token = "rooster";

int editDistance = getEditDistance(token); //returns 1 for "rooster"
int prefixLength = getPrefixLength(token); //returns 1 for "rooster"

namesBool.must(
    qb.keyword()
        .fuzzy() //returns FuzzyContext
        .withEditDistanceUpTo(editDistance)
        .withPrefixLength(prefixLength)
        .onField(field)
        .matching(token)
        .createQuery()
);


// ...
// calling FullTextSession::createFullTextQuery

Когда термин «петух» отправляется через этот метод, он имеет editDistance (нечеткость) 1 и префикс длины 1 1.

Изучая журналы и просматривая то, что отправляется в ES, я ожидаю увидеть«prefix_length» прямо под «fuzziness», но его там нет:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "vendorNames.vendorName": {
            "query": "rooster",
            "fuzziness": 1
          }
        }
      }
    }
  }
  1. Почему FuzzyContext позволяет устанавливать prefixLength, но не использовать его?
  2. Действительно ли это стоитПовышение производительности ES, чтобы попытаться включить prefixLength (я тестировал вызовы REST-запросов напрямую к ES как с, так и без prefixLength, и не заметилразница во времени ответа)?
  3. Как получить префиксLength для включения в фактический запрос, отправляемый в ES?

1 Ответ

1 голос
/ 29 марта 2019

Почему FuzzyContext позволяет устанавливать префиксLength, но не использовать его?

Это ошибка интеграции Elasticsearch, но до сих пор об этом не сообщалось: спасибо!Мы попытаемся исправить это в следующем цикле разработки: HSEARCH-3545

Действительно ли стоит повышение производительности ES, чтобы попытаться включить prefixLength (я проверял вызовы запросов RESTнепосредственно к ES как с префиксом Length, так и без него и не заметил разницу во времени отклика)?

prefixLength больше касается значимости результатов, чем производительности.Идея в том, что если пользователь даст нам слово длиной 10 символов, мы, скорее всего, получим множество нечетких совпадений, большинство из которых, вероятно, не имеют значения.Игнорируя первые 5 символов (например), мы сосредоточим размытость в конце слова, что, вероятно, менее актуально (например, «теория» / «теории», «составление» / «составление» и т. Д.):таким образом, мы получим меньше нечетких совпадений, но они будут более релевантными.

По крайней мере, это теория:)

Как я могу получить prefixLength для включения в реальный запросотправлено в ES?

Если вам не нужна поддержка нескольких токенов, вы можете создать FuzzyQuery напрямую:

BooleanJunction namesBool = qb.bool();
String field = "vendorNames.vendorName";
String token = "rooster";
int editDistance = getEditDistance(token); //returns 1 for "rooster"
int prefixLength = getPrefixLength(token); //returns 1 for "rooster"

namesBool.must(
    new FuzzyQuery(new Term(field, token), editDistance, prefixLength)
);

Этот запрос будет переведен правильно.

Если вам нужна поддержка нескольких токенов (т.е. вам нужен нечеткий match запрос , а не просто fuzzy запрос ), тогда ваше единственное решение будетнаписать запрос целом в формате JSON и использовать org.hibernate.search.elasticsearch.ElasticsearchQueries#fromJson:

String field = "vendorNames.vendorName";
String token = "rooster";
int editDistance = getEditDistance(token); //returns 1 for "rooster"
int prefixLength = getPrefixLength(token); //returns 1 for "rooster"

QueryDescriptor queryDescriptor = ElasticsearchQueries.fromJson(
"{"
  + "\"query\": {"
    + "\"bool\": {"
      + "\"must\": {"
        + "\"match\": {"
          + "\"" + field + "\": {"
            + "\"query\": \"" + token + "\","
            + "\"fuzziness\": " + editDistance + ","
            + "\"prefix_length\": " + prefixLength
          + "}"
        + "}"
      + "}"
    + "}"
  + "}"
+ "}"
);

List<?> result = session.createFullTextQuery( queryDescriptor, MyEntity.class )
                .list();

Да, это глоток ... Мы улучшаем вещи в Hibernate Search 6.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...