запрос к тому же полю с несколькими значениями, используя RestHighLevelClient - PullRequest
0 голосов
/ 15 апреля 2020

Мне нужно отфильтровать / запросить несколько URL-адресов в поле «url», используя Elasticsearch RestHighLevelClient. Я сформировал свой запрос, как показано ниже, но он дает 0 записей.

query.must(QueryBuilders.queryStringQuery("http://localhost:8080/test/*")
                         .field("url")
                        .lenient(true)
                        .escape(true)
                        .analyzeWildcard(true)
                        .fuzziness(Fuzziness.ZERO)
                        .defaultOperator(Operator.AND)
                        .boost(1.0f));
query.must(QueryBuilders.queryStringQuery("http://www.bbc.com/*")
                     .field("url")
                    .lenient(true)
                    .escape(true)
                    .analyzeWildcard(true)
                    .fuzziness(Fuzziness.ZERO)
                    .defaultOperator(Operator.AND)
                    .boost(1.0f));

Если я переключусь на ниже, он даст мне только соответствующие записи url http://localhost:8080/test/*, так как я задаю Operator.AND для этого и для запроса на URL http://www.bbc.com/* до Operator.OR.

query.must(QueryBuilders.queryStringQuery("http://localhost:8080/test/*")
                         .field("url")
                        .lenient(true)
                        .escape(true)
                        .analyzeWildcard(true)
                        .fuzziness(Fuzziness.ZERO)
                        .defaultOperator(Operator.AND)
                        .boost(1.0f));
query.must(QueryBuilders.queryStringQuery("http://www.bbc.com/*")
                     .field("url")
                    .lenient(true)
                    .escape(true)
                    .analyzeWildcard(true)
                    .fuzziness(Fuzziness.ZERO)
                    .defaultOperator(Operator.OR)
                    .boost(1.0f));

Таким образом, игнорируется http://www.bbc.com/* фильтр.

Я здесь ошибаюсь? Как написать несколько запросов на одно поле?

1 Ответ

0 голосов
/ 15 апреля 2020

Вы должны использовать should вместо must в своем запросе bool.

Что происходит в исходном запросе?

Первый запрос, который вы Выполнение фактически запрашивает оба значения url, которые должны присутствовать в документе: оно будет совпадать, если и только если в том же документе у вас есть url: http://localhost:8080/test/ и url: http://www.bbc.com/.

Это нормальное поведение для bool запрос и не указан c до BoolQueryBuilder, который, как я предполагаю, вы используете.

Как выполнить логическое ИЛИ двух запросов ?

Фактически, вы должны использовать BoolQueryBuilder.should(), чтобы поместить эти два запроса в логическое ИЛИ:

query.should(QueryBuilders.queryStringQuery("http://localhost:8080/test/*")
                     .field("url")
                    .lenient(true)
                    .escape(true)
                    .analyzeWildcard(true)
                    .fuzziness(Fuzziness.ZERO)
                    .defaultOperator(Operator.AND)
                    .boost(1.0f));
query.should(QueryBuilders.queryStringQuery("http://www.bbc.com/*")
                 .field("url")
                .lenient(true)
                .escape(true)
                .analyzeWildcard(true)
                .fuzziness(Fuzziness.ZERO)
                .defaultOperator(Operator.AND)
                .boost(1.0f));

Как я могу объединить это с другими частями мой запрос?

Как вы указали в комментарии, ваш запрос на самом деле более сложный: он должен соответствовать одному из шаблонов URL, и результаты должны быть увеличены, если они также соответствуют содержимому.

Чтобы достичь этого, вы должны использовать два вложенных запроса типа bool:

BoolQueryBuilder urlQuery = BoolQueryBuilder();

urlQuery.should(QueryBuilders.queryStringQuery("http://localhost:8080/test/*")
                         .field("url")
                        .lenient(true)
                        .escape(true)
                        .analyzeWildcard(true)
                        .fuzziness(Fuzziness.ZERO)
                        .defaultOperator(Operator.AND)
                        .boost(1.0f));

urlQuery.should(QueryBuilders.queryStringQuery("http://www.bbc.com/*")
                     .field("url")
                    .lenient(true)
                    .escape(true)
                    .analyzeWildcard(true)
                    .fuzziness(Fuzziness.ZERO)
                    .defaultOperator(Operator.AND)
                    .boost(1.0f));

WildcardQueryBuilder wildcardQuery = QueryBuilderswildcardQuery("content", "anyt*");


// here `query` is your original bool query
query.must(urlQuery);
query.should(wildcardQuery);

Elasticsearch будет интерпретировать этот запрос выглядит примерно так:

выборка документов, которые должны соответствовать либо url query #1 или url query #2, и ранжирование выше тех, которые соответствуют wildcardQuery

Какое отношение defaultOperator имеет ко всему этому?

.defaultOperator(Operator.OR) на самом деле просто Elasticsearch, пытающийся сбить вас с толку: он не имеет ничего общего с объединением двух запросов в логическом ИЛИ, но вместо этого является параметром строка запроса :

default_operator

(Необязательно, строка) Логические значения по умолчанию c, используемые для интерпретации текст в строке запроса, если операторы не указаны.

Этот параметр фактически указывает Elasticsearch , как интерпретировать токены внутри queryStringQuery(), которые вы передаете , Вы можете думать о строковом запросе как о запросе на языке запросов Lucene .

Надеюсь, это поможет!

...