重写
多词元查询(如 wildcard
、prefix
、regexp
、fuzzy
和 range
)会在内部扩展为一组词元。rewrite
参数允许您控制这些词元扩展的执行和评分方式。
当一个多词元查询扩展为许多词元时(例如,prefix: "error*"
匹配数百个词元),它们在内部会被转换为 term
查询。这个过程可能会有以下缺点:
- 超出
indices.query.bool.max_clause_count
限制(默认为1024
)。 - 影响匹配文档的评分计算方式。
- 根据所使用的重写方法,影响内存和延迟。
rewrite
参数让您可以控制多词元查询在内部的行为。
模式 | 评分 | 性能 | 备注 |
---|---|---|---|
constant_score | 所有匹配项的评分相同 | 最佳 | 默认模式,适用于过滤器 |
scoring_boolean | 基于 TF/IDF | 中等 | 完全相关性评分 |
constant_score_boolean | 评分相同但具有布尔结构 | 中等 | 与 must_not 或 minimum_should_match 一起使用 |
top_terms_N | 对前 N 个词元进行 TF/IDF | 高效 | 截断扩展 |
top_terms_boost_N | 静态提升 | 快速 | 准确性较低 |
top_terms_blended_freqs_N | 混合评分 | 平衡 | 最佳评分/效率权衡 |
可用重写方法
下表总结了可用的重写方法。
重写方法 | 描述 |
constant_score | (默认)所有扩展的词元作为一个整体进行评估,为每个匹配项分配相同的评分。匹配的文档不单独评分,这对于过滤用例非常高效。 |
scoring_boolean | 将查询分解为一个布尔 should 子句,每个匹配项对应一个词元查询。每个结果根据相关性单独评分。 |
constant_score_boolean | 类似于 scoring_boolean ,但所有文档都接收固定评分,无论词元频率如何。保持布尔结构,不进行 TF/IDF 加权。 |
top_terms_N | 将评分和执行限制为前 N 个最频繁的词元。减少资源使用并防止子句过载。 |
top_terms_boost_N | 类似于 top_terms_N ,但使用静态提升而不是完整评分。通过简化的相关性提供性能改进。 |
top_terms_blended_freqs_N | 选择前 N 个匹配词元,并平均其文档频率进行评分。在不引起词元完全爆炸的情况下产生平衡的评分。 |
基于布尔的重写限制
所有基于布尔的重写,例如 scoring_boolean
、constant_score_boolean
和 top_terms_*
,都受以下动态集群级别索引设置的限制:
indices.query.bool.max_clause_count
此设置控制允许的最大布尔 should
子句数量(默认值:1024
)。如果您的查询扩展的词元数量超过此限制,它将被拒绝并返回 too_many_clauses
错误。
例如,通配符(如“error*”)可能会扩展为数百或数千个匹配词元,其中可能包括“error”、“errors”、“error_log”、“error404”等。这些词元中的每一个都会变成一个单独的 term
查询。如果词元数量超出 indices.query.bool.max_clause_count
限制,查询将失败。
POST /logs/_search
{
"query": {
"wildcard": {
"message": {
"value": "error*",
"rewrite": "scoring_boolean"
}
}
}
}
查询在内部扩展如下:
{
"bool": {
"should": [
{ "term": { "message": "error" } },
{ "term": { "message": "errors" } },
{ "term": { "message": "error_log" } },
{ "term": { "message": "error404" } },
...
]
}
}
常量得分
默认的 constant_score
重写方法将所有扩展词元包装到一个查询中,并完全跳过评分阶段。这种方法具有以下特点:
- 将所有词元匹配作为单个位数组查询执行。
- 完全忽略评分;每个文档的
_score
都为1.0
。 - 最快的选项;适用于过滤。
以下示例使用默认的 constant_score
重写方法运行 wildcard
查询,以高效过滤 message
字段中匹配 warning*
模式的文档。
POST /logs/_search
{
"query": {
"wildcard": {
"message": {
"value": "warning*"
}
}
}
}
评分布尔
scoring_boolean
重写方法将扩展的词元分解为单独的 term
查询,并组合在一个布尔 should
子句下。这种方法的工作原理如下:
- 将通配符扩展为布尔
should
子句内的独立term
查询。 - 每个文档的评分反映了它匹配的词元数量以及这些词元的频率。
以下示例使用 scoring_boolean
重写配置:
POST /logs/_search
{
"query": {
"wildcard": {
"message": {
"value": "warning*",
"rewrite": "scoring_boolean"
}
}
}
}
固定评分布尔
constant_score_boolean
重写方法使用与 scoring_boolean
相同的布尔结构,但禁用了评分,这使得它在需要子句逻辑而无需相关性排名时非常有用。此方法具有以下特点:
- 结构类似于
scoring_boolean
,但文档不进行排名。 - 所有匹配文档都获得相同的评分。
- 保留布尔子句的灵活性,例如使用
must_not
,而不进行排名。
以下示例查询使用了一个 must_not
布尔子句:
POST /logs/_search
{
"query": {
"bool": {
"must_not": {
"wildcard": {
"message": {
"value": "error*",
"rewrite": "constant_score_boolean"
}
}
}
}
}
}
此查询在内部扩展如下:
{
"bool": {
"must_not": {
"bool": {
"should": [
{ "term": { "message": "error" } },
{ "term": { "message": "errors" } },
{ "term": { "message": "error_log" } },
...
]
}
}
}
}
前 N 个词元
top_terms_N
方法是几种重写选项之一,旨在在扩展多词元查询时平衡评分准确性和性能。其工作原理如下:
- 仅选择和评分前 N 个最频繁匹配的词元。
- 当您预期词元会大量扩展并希望限制负载时非常有用。
- 为保持性能,其他有效词元将被忽略。
以下查询使用 top_terms_2
重写方法,仅对 message
字段中匹配 warning*
模式的两个最频繁词元进行评分:
POST /logs/_search
{
"query": {
"wildcard": {
"message": {
"value": "warning*",
"rewrite": "top_terms_2"
}
}
}
}
前 N 个词元提升
top_terms_boost_N
重写方法选择前 N 个匹配词元并应用静态 boost
值,而不是计算完整的相关性评分。其工作原理如下:
- 将扩展限制为前 N 个词元,类似于
top_terms_N
。 - 它不计算 TF/IDF,而是为每个词元分配一个预设的提升值。
- 提供更快的执行速度和可预测的相关性权重。
以下示例使用 top_terms_boost_2
重写参数:
POST /logs/_search
{
"query": {
"wildcard": {
"message": {
"value": "warning*",
"rewrite": "top_terms_boost_2"
}
}
}
}
前 N 个词元混合频率
top_terms_blended_freqs_N
重写方法选择前 N 个匹配词元并混合它们的文档频率,以产生更平衡的相关性评分。这种方法具有以下特点:
- 选择前 N 个匹配词元并对所有词元应用混合频率。
- 混合使不同频率的词元之间的评分更平滑。
- 当您希望在保持性能的同时获得真实评分时,这是一个很好的权衡。
以下示例使用 top_terms_blended_freqs_2
重写参数:
POST /logs/_search
{
"query": {
"wildcard": {
"message": {
"value": "warning*",
"rewrite": "top_terms_blended_freqs_2"
}
}
}
}