ElasticSearch QueryBuilder must_not клаузула странное поведение - PullRequest
0 голосов
/ 15 сентября 2018

Согласно документации

must_not Предложение (запрос) не должно появляться в соответствующих документах.

У меня такой запрос:

// searching for URI which contains smart and doesn't contain vip.vs.csin.cz
BoolQueryBuilder builder = QueryBuilders.boolQuery();
builder.must(QueryBuilders.termQuery(URI, "smart")));
builder.mustNot(QueryBuilders.termQuery(URI, "vip.vs.csin.cz")));

В моем хранилище эластичных поисковых запросов есть два URI

1)

/ smart-int-vip.vs.csin.cz: 5080 / умный / API / выполнения / корпус / SC0000000000558648 / запись / генерировать / 4327 / по / SMOBVA002 / а / верно espisRecordForm = ANALOG & ACCOUNTNUMBER = 2318031033/0800

2)

* * Тысяча двадцать-два / смарт / API / выполнение / случай / SC0000000000558648 / запись / генерировать / 4327 / с / SMOBVA002 / а / правда? EspisRecordForm = АНАЛОГ & AccountNumber = 2318031033/0800 * * тысячи двадцать-три

Когда я выполняю запрос через ElasticSearchTemplate

elasticsearchTemplate.getClient().search(searchRequest);

Возвращаюсь 0 записей . Когда я выполняю тот же запрос без предложения mustNot , я получаю 2 записи.
В кибане я могу написать:

uri: "smart" NOT uri: "vip.vs.csin.cz"

И получите 1 запись , как и ожидалось.

Я ожидал такого же поведения от Java ElasticSearchClient. Как я могу отфильтровать записи, которые содержат «vip.vs.csin.cz» из Java и почему он отфильтровал вторую запись, даже если она не содержит ничего из указанного в mustNot предложения?

Редактировать вот мое отображение

@Document(indexName = "audit-2018", type = "audit")
public class Trace {

    @Id
    private String id;
    @Field(type = FieldType.Text)
    private String uri;

    // more columns, getter & setters
}

1 Ответ

0 голосов
/ 16 сентября 2018

Код Java, который вы указали, показывает запрос bool, используя предложения must и must_not, в которых вы выполняете запрос термина.Что касается запросов к терминам, то они подчиняются анализатору, имеющемуся на ваших полях, стандартному анализатору для полей text (тип данных вашего поля uri, подробнее здесь ).удалит все знаки препинания (другими словами, точки в вашем слове) и разделит ваше слово на части.vip.vs.csin.cz становится vip vs csin cz.Тип поля text должен быть зарезервирован только для полнотекстового поиска, в вашем случае я бы выбрал тип поля keyword ( Подробнее здесь ). Причина, по которой ваш запрос в Kibana работает, как и ожидалось, заключается в том, чтокаждый на самом деле не выполняет запрос терминов, а скорее запрос query_string , содержащий запрос lucene: uri: "smart" NOT uri: "vip.vs.csin.cz".

Итак, у вас есть несколько вариантов решения вашей проблемы.Вы можете изменить запрос к терминам на match_phrase запросов, что позволит вам сохранить порядок ваших токенизированных терминов и, возможно, получить правильный результат.Альтернативой может быть выполнение запроса query_string вместо запроса условий в вашем Java-коде, поскольку вы уже определили, что это дает правильный результат.

Мое предлагаемое решение, однако, состояло бы в том, чтобы переиндексировать uri с типом поля keyword, так как этот тип поля не приведет к нежелательному токенизации значений ваших полей в несколько терминов.Вы можете прочитать больше об анализаторе и токенизаторе по умолчанию для поля типа keyword здесь .Это избавит вас от головной боли в будущем, поскольку вы знаете, что ваши запросы соответствуют значениям вашего поля в точности «как есть».

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