思维导图
1 前言
在前几章,我们介绍了,如何创建 Mapping,以及常见的搜索。
接下来,我们将介绍开发中最最最常用的查询: Bool Query。
为什么常用呢?
因为 Bool Query 足够灵活,能够满足大部分业务开发。
Bool Query 一共有 4 个参数,我们也将介绍该 4 个参数。
mustfiltershouldmust_not
2 must
2.1 描述
文档必须满足 must 中声明的查询条件,并且贡献得分。
非常重要的一点:must 是贡献得分的。贡献得分也就意味着,ES 有额外的开销去计算得分。
2.2 demo
写入文档
PUT /test6/_doc/1
{
"name": "hello world",
"hobby": "basketball",
"company": "a",
"ctime": "2024/07/22 00:00:00"
}
PUT /test6/_doc/2
{
"name": "welcome my channel",
"hobby": "watch TV",
"company": "b",
"ctime": "2024/06/22 00:00:00"
}
PUT /test6/_doc/3
{
"name": "love apple",
"hobby": "pingpong",
"company": "C",
"ctime": "2024/05/22 00:00:00"
}
查询 ctime 大于等于 2024/06/22 00:00:00 且 hobby 是 watch TV 的文档。
GET /test6/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"ctime": {
"gte": "2024/06/22 00:00:00"
}
}
},
{
"term": {
"hobby.keyword": "watch TV"
}
}
]
}
}
}
must 参数是一个数组,可以包含多个子查询。
2.3 得分计算规则
must 得分计算规则 = sum(所有子查询的得分)
3 must_not
文档必须不能满足 must_not 中的子查询,不贡献得分。
GET /test6/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"hobby": "TV"
}
},
{
"range": {
"ctime": {
"gte": "2024/06/12 00:00:00",
"lte": "2024/06/23 00:00:00"
}
}
}
]
}
}
}
4 should
4.1 描述
与 Mysql 的 or 查询类似。默认只要满足 should 中一个子查询(在存在 must 或者 filter 的情况下,should 默认不生效)。
4.2 demo
GET /test6/_search?explain=true
{
"query": {
"bool": {
"should": [
{
"terms": {
"hobby.keyword": ["watch TV", "basketball"]
}
},
{
"match": {
"name": "hello"
}
}
]
}
}
}
4.3 最少匹配 minimum_should_match
minimum_should_match 可以修改至少要被满足的子查询个数。
GET /test6/_search
{
"query": {
"bool": {
"should": [
{
"terms": {
"hobby.keyword": ["watch TV", "basketball"]
}
},
{
"match": {
"name": "hello"
}
}
],
"minimum_should_match": 2
}
}
}
minimum_should_match:文档必须满足至少 2 个 should 中的子查询。
再来看个 demo:当存在 must 或者 filter 时,minimum_should_match 值默认为 0,即 should 语句不生效。
GET /test6/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "hello"
}
}
],
"should": [
{
"terms": {
"hobby.keyword": ["not match"]
}
}
]
}
}
}
4.4 得分计算规则
should 得分计算规则 = sum(所有子查询的得分)
5 filter
5.1 描述
文档必须满足 filter 中的子查询,且不贡献算分。
重要:ES 会缓存 filter 中的子查询结果,可以加速查询!!!在实际开发中,如果查询条件不需要算分,都可以放在 filter 中执行。
5.2 demo
GET /test6/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"company": "a"
}
}
]
}
}
}
6 混合使用demo
GET /test6/_search?explain=true
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "hello pingpong",
"fields": ["name^2", "hobby"]
}
}
],
"filter": [
{
"terms": {
"company": ["a", "b", "c"]
}
}
],
"must_not": [
{
"range": {
"ctime": {
"gte": "2024/06/12 00:00:00",
"lte": "2024/06/23 00:00:00"
}
}
}
]
}
}
}
7 总结
| must | must_not | should | filter | |
|---|---|---|---|---|
| 描述 | 必须匹配 | 必须不能匹配 | 选择性匹配 | 必须匹配 |
| 算分 | sum(子查询得分) | 不算分 | sum(子查询得分) | 不算分, ES 会缓存子查询结果 |