我必须使用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
。 / p>
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/*
过滤器。
我在这里犯错了吗?如何在同一字段上编写多个查询?
答案 0 :(得分:0)
在bool
查询中,您应该使用should
而不是must
。
您执行的第一个查询实际上要求两个url
值都出现在文档中:只有在同一文档中有url: http://localhost:8080/test/
和url: http://www.bbc.com/
时,它才会匹配
此行为对于bool
查询是正常的,并且不特定于我假设您正在使用的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模式匹配,并且如果它们也与内容匹配,则应提高结果。
要实现此目的,您应该使用两个嵌套的布尔查询,如下所示:
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 string query的参数:
default_operator
(可选,字符串)如果未指定运算符,则用于解释查询字符串中文本的默认布尔逻辑。
此参数实际上告诉Elasticsearch how to interpret the tokens在内部{em> 您通过的queryStringQuery()
。您可以将字符串查询视为Lucene query language中的查询。
希望有帮助!