我必须使用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));
如果我更改为以下内容,它将只给我匹配的记录urlhttp://localhost:8080/test/*
,因为我将Operator.AND
设置为该值,并将urlhttp://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/*
滤波器。
我在这里做错了吗?如何在同一字段上编写多个查询?
您应该在bool
查询中使用should
而不是must
。
原始查询中发生了什么
您执行的第一个查询实际上要求两个url
值都存在于文档中:当且仅当在同一文档中有url: http://localhost:8080/test/
和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中合并两个查询无关,而是查询字符串查询的一个参数:
默认操作员
(可选,字符串(如果未指定运算符,则用于解释查询字符串中的文本的默认布尔逻辑。
这个参数实际上告诉Elasticsearch如何解释您传递的queryStringQuery()
内部的令牌。您可以将字符串查询视为Lucene查询语言中的查询。
希望能有所帮助!