java - ElasticSearch QueryBuilder must_not 子句的奇怪行为
问题描述
根据文档
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/smart/api/runtime/case/SC0000000000558648/record/generate/4327/by/SMOBVA002/as/true?espisRecordForm=ANALOG&accountNumber=2318031033/0800
2)
/smart/api/runtime/case/SC0000000000558648/record/generate/4327/by/SMOBVA002/as/true?espisRecordForm=ANALOG&accountNumber=2318031033/0800
当我通过ElasticSearchTemplate执行查询时
elasticsearchTemplate.getClient().search(searchRequest);
我得到0 条记录。当我在没有mustNot子句的情况下执行相同的查询时,我得到了2 条记录。
在 kibana 我可以写:
uri: "smart" NOT uri: "vip.vs.csin.cz"
并按预期获得1 条记录。
我期待来自 Java ElasticSearchClient 的相同行为。如何从 Java 中过滤包含“vip.vs.csin.cz”的记录,以及为什么它过滤了第二条记录,即使它不包含我指定的 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
}
解决方案
您提供的 Java 代码显示了使用must
andmust_not
子句的 bool 查询,其中您正在执行术语查询。关于术语查询的事情是它们受制于您在字段中拥有的分析器,标准分析器text
(这是您的uri
字段的数据类型,请在此处阅读更多内容)字段将删除所有标点符号(换句话说,您的word) 并把你的话分开。vip.vs.csin.cz
变成vip vs csin cz
. text
字段类型应仅保留用于全文搜索,在您的情况下,我会选择字段keyword
类型(在此处阅读更多内容)您的 Kibana 查询按预期工作的原因是因为该查询实际上并没有进行术语查询,而是请求参数包含 lucene 查询的查询:uri: "smart" NOT uri: "vip.vs.csin.cz"
。
所以你有几个选择来解决你的问题。您可以将您的术语查询更改为match_phrase
查询,这将允许您保留标记化术语的顺序并可能获得正确的结果。另一种方法是query_string
在您的 Java 代码中执行查询而不是术语查询,因为您已经确定这确实会为您提供正确的结果。
但是,我建议的解决方案是使用uri
field type重新索引keyword
,因为此字段类型不会导致将您的字段值不必要地标记为多个术语。您可以在此处阅读有关keyword
字段类型的默认分析器和标记器的更多信息。这将使您在将来避免头疼,因为您知道您的查询与您的字段值完全“原样”匹配。
推荐阅读
- javascript - Firebase web:将多个文件上传到存储,然后下载它们的 URL
- java - 如何修复相机 API?
- node.js - Docker-compose up 以代码 1 退出,但 docker-compose build 成功
- c# - 使用接口将通用规则应用于继承的接口
- database - 如何使用boto3在dynamodb中查询大于排序键
- litedb - 如果我的某些值为空,我如何填充 LiteDB 数据库
- c - 如何将数组称为函数?
- angular - 电容和离子原生状态栏
- python - youtube 上的那个人在 jupyter notebook 中做的 python 代码在 Visual Studio 中对我不起作用
- jenkins - gcloud中的Jenkinsfile管道阶段错误