0

我必须使用 Elasticsearch RestHighLevelClient 过滤/查询“url”字段上的多个 url。我形成了如下查询,但它给出了 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/*过滤器。

我在这里做错了吗?如何在同一字段上编写多个查询?

4

1 回答 1

0

您应该在查询中使用should而不是。mustbool

原始查询中会发生什么?

您执行的第一个查询实际上要求两个url值都存在于文档中:当且仅当在同一个文档中您拥有url: http://localhost:8080/test/and时,它才会匹配url: http://www.bbc.com/

这种行为对于bool查询来说是正常的,并不是BoolQueryBuilder我假设您正在使用的特定行为。

如何对两个查询进行逻辑或?

实际上,您应该使用BoolQueryBuilder.should()将这两个查询放在逻辑 OR 中:

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 试图让您感到困惑:它与在逻辑 OR 中合并两个查询无关,而是查询字符串 query的参数:

default_operator

(可选,字符串)如果未指定运算符,则用于解释查询字符串中的文本的默认布尔逻辑。

这个参数实际上告诉 Elasticsearch如何解释 你传递的令牌。queryStringQuery()您可以将字符串查询视为Lucene 查询语言中的查询。

希望有帮助!

于 2020-04-15T12:30:17.393 回答