ElasticSearch查询中的must和should混合使用的行为解析

最近在做能力开放平台,其中的功能包含日志的查看,根据用户展示对应的日志信息,在根据用户权限查询相应的日志的时候发现同时使用mustshould查询日志时会查到一些本不符合条件的数据,特此记录。

img

在ElasticSearch中,我们可以使用mustshould子句来构建复杂的查询。must子句表示所有条件都必须满足才能匹配文档,而should子句表示其中至少一个条件满足即可匹配文档。

然而,当should子句下的所有条件都不满足时,仍然可能查询出结果的情况可能会让人感到困惑。这是由于ElasticSearch的查询机制中的一个特性所导致的。

查询机制解析

ElasticSearch在处理查询时,会计算每个文档的相关性得分(relevance score),并根据得分进行排序。而should子句下的条件并不是强制要求满足的条件,而是用于调整相关性得分的因素。

当一个文档的should子句下的条件都不满足时,这些条件不会导致文档被排除在结果之外。相反,ElasticSearch会根据其他条件和相关性得分来决定文档是否匹配,并将其包含在结果中。

解决方案

如果您希望确保should子句下的条件必须满足才能匹配文档,可以使用布尔查询(bool query)的minimum_should_match参数。该参数指定了should子句下至少需要满足的条件数量。

以下是一个示例布尔查询的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
{
"query":{
"bool":{
"filter":[
{
"range":{
"timeLocal.keyword":{
"from":"2023-11-23 00:00:00",
"to":"2023-11-23 23:59:59",
"include_lower":true,
"include_upper":true,
"boost":1
}
}
}
],
"should":[
{
"match_phrase":{
"appId.keyword":{
"query":"20231025001560",
"slop":0,
"zero_terms_query":"NONE",
"boost":1
}
}
},
{
"match_phrase":{
"appId.keyword":{
"query":"20231124009319",
"slop":0,
"zero_terms_query":"NONE",
"boost":1
}
}
}
],
"minimum_should_match": 1,
"must": [
{"exists": {"field": "appId"}}
],
"adjust_pure_negative":true,
"boost":1
}
},
"sort":[
{
"timeLocal.keyword":{
"order":"desc"
}
}
]
}

在上述示例中,minimum_should_match参数设置为1,表示should子句下至少需要满足1个条件才能匹配文档。

通过使用布尔查询和minimum_should_match参数,您可以更精确地控制查询结果,确保should子句下的条件满足的文档才被包含在结果中。

总结

在ElasticSearch中,同时使用mustshould查询时,should子句下的条件不是强制要求满足的条件,而是用于调整相关性得分的因素。如果需要确保should子句下的条件必须满足才能匹配文档,可以使用布尔查询的minimum_should_match参数来控制条件的最小满足数量。这样可以更精确地过滤查询结果,符合预期的逻辑。

希望本篇博客能够帮助您理解ElasticSearch中mustshould查询的行为,并提供解决方案来满足特定的查询需求。