如何在 Elasticsearch 中与过滤器和 must_not 一起编写至少 N 项查询?
How to write an at-least-N-terms query together with filter and must_not in Elasticsearch?
我要匹配满足以下所有条件的文档:
- 作者 == "tom"
- 状态 != "deleted"
f1-f4
字段中至少有两个 匹配给定值
(所有字段都是keyword
)
{"size":24,
"query":{
"bool":{
"filter":[{"term":{"author":{"value":"tom","boost":1.0}}}],
"must_not":[{"term":{"status":{"value":"deleted","boost":1.0}}}],
"should":[
{"term":{"f1":{"value":"v1","boost":1.0}}},
{"term":{"f2":{"value":"v2","boost":1.0}}},
{"term":{"f3":{"value":"v3","boost":1.0}}},
{"term":{"f4":{"value":"v4","boost":1.0}}}
],
"minimum_should_match":"2",
"boost":1.0
}}
}
更新与总结
上面我 post 的查询实际上是正确的,但是我的 es 提供者安装了一个有缺陷的自定义插件执行 "query optimization" 导致所有 "minimum_should_match" 被忽略。如果你遇到同样的问题,找不到任何线索,也许你应该检查一下你是否安装了可疑的插件
您的查询是正确的,您只需删除 "adjust_pure_negative"
标志或将其更改为 false。
简而言之,elastic 将 "ignore" 您的所有查询,并且在标志设置为 true 的情况下仅使用 must_not
进行过滤。 source
您也可以删除 boost:1
,因为默认值为 1,这使它变得多余。
编辑:我的测试
await client.index({index: 'test', id: 5, type: 'test', body: {author: "george", status: "deleted", f1: "v1", f2: "v2"}});
await client.index({index: 'test', id: 6, type: 'test', body: {author: "george", status: "x", f1: "v1",}});
await client.index({index: 'test', id: 7, type: 'test', body: {author: "george", status: "u", f1: "v1", f2: "v2"}});
await client.index({index: 'test', id: 8, type: 'test', body: {author: "george", status: "q", f1: "v1", f4: "v4"}});
await client.index({index: 'test', id: 9, type: 'test', body: {author: "george", status: "1", f3: "v3"}});
let x = await client.search({
index: 'test',
body:
{"size":24,
"query":{
"bool":{
"filter":[{"term":{"author":{"value":"george","boost":1.0}}}],
"must_not":[{"term":{"status":{"value":"deleted","boost":1.0}}}],
"must":[{
"bool":{
"should":[
{"term":{"f1":{"value":"v1","boost":1.0}}},
{"term":{"f2":{"value":"v2","boost":1.0}}},
{"term":{"f3":{"value":"v3","boost":1.0}}},
{"term":{"f4":{"value":"v4","boost":1.0}}}],
"minimum_should_match":"2",
"adjust_pure_negative":false,
"boost":1.0}}
],
"adjust_pure_negative":false,
"boost":1.0}}},
});
结果:
2 次符合预期:
[
{
"_index": "test",
"_type": "test",
"_id": "7",
"_score": 0.5753642,
"_source": {
"author": "george",
"status": "u",
"f1": "v1",
"f2": "v2"
}
},
{
"_index": "test",
"_type": "test",
"_id": "8",
"_score": 0.47000366,
"_source": {
"author": "george",
"status": "q",
"f1": "v1",
"f4": "v4"
}
}
]
我要匹配满足以下所有条件的文档:
- 作者 == "tom"
- 状态 != "deleted"
f1-f4
字段中至少有两个 匹配给定值
(所有字段都是keyword
)
{"size":24,
"query":{
"bool":{
"filter":[{"term":{"author":{"value":"tom","boost":1.0}}}],
"must_not":[{"term":{"status":{"value":"deleted","boost":1.0}}}],
"should":[
{"term":{"f1":{"value":"v1","boost":1.0}}},
{"term":{"f2":{"value":"v2","boost":1.0}}},
{"term":{"f3":{"value":"v3","boost":1.0}}},
{"term":{"f4":{"value":"v4","boost":1.0}}}
],
"minimum_should_match":"2",
"boost":1.0
}}
}
更新与总结
上面我 post 的查询实际上是正确的,但是我的 es 提供者安装了一个有缺陷的自定义插件执行 "query optimization" 导致所有 "minimum_should_match" 被忽略。如果你遇到同样的问题,找不到任何线索,也许你应该检查一下你是否安装了可疑的插件
您的查询是正确的,您只需删除 "adjust_pure_negative"
标志或将其更改为 false。
简而言之,elastic 将 "ignore" 您的所有查询,并且在标志设置为 true 的情况下仅使用 must_not
进行过滤。 source
您也可以删除 boost:1
,因为默认值为 1,这使它变得多余。
编辑:我的测试
await client.index({index: 'test', id: 5, type: 'test', body: {author: "george", status: "deleted", f1: "v1", f2: "v2"}});
await client.index({index: 'test', id: 6, type: 'test', body: {author: "george", status: "x", f1: "v1",}});
await client.index({index: 'test', id: 7, type: 'test', body: {author: "george", status: "u", f1: "v1", f2: "v2"}});
await client.index({index: 'test', id: 8, type: 'test', body: {author: "george", status: "q", f1: "v1", f4: "v4"}});
await client.index({index: 'test', id: 9, type: 'test', body: {author: "george", status: "1", f3: "v3"}});
let x = await client.search({
index: 'test',
body:
{"size":24,
"query":{
"bool":{
"filter":[{"term":{"author":{"value":"george","boost":1.0}}}],
"must_not":[{"term":{"status":{"value":"deleted","boost":1.0}}}],
"must":[{
"bool":{
"should":[
{"term":{"f1":{"value":"v1","boost":1.0}}},
{"term":{"f2":{"value":"v2","boost":1.0}}},
{"term":{"f3":{"value":"v3","boost":1.0}}},
{"term":{"f4":{"value":"v4","boost":1.0}}}],
"minimum_should_match":"2",
"adjust_pure_negative":false,
"boost":1.0}}
],
"adjust_pure_negative":false,
"boost":1.0}}},
});
结果: 2 次符合预期:
[
{
"_index": "test",
"_type": "test",
"_id": "7",
"_score": 0.5753642,
"_source": {
"author": "george",
"status": "u",
"f1": "v1",
"f2": "v2"
}
},
{
"_index": "test",
"_type": "test",
"_id": "8",
"_score": 0.47000366,
"_source": {
"author": "george",
"status": "q",
"f1": "v1",
"f4": "v4"
}
}
]