📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

配置项作用 #

indices.query.query_string.allowLeadingWildcard 配置项用于控制查询字符串解析器是否允许使用通配符(*?)作为查询词的开头

前导通配符查询(如 *search?query)会导致全索引扫描,严重影响性能。此配置可以禁用此类查询以保护系统。

配置项属性 #

  • 配置路径: indices.query.query_string.allowLeadingWildcard
  • 数据类型: Boolean(布尔值)
  • 默认值: true
  • 是否可选: 是
  • 作用域: NodeScope(节点级别)

配置项详解 #

工作机制 #

前导通配符查询流程

allowLeadingWildcard = true (默认):

查询: *term
    │
    ↓
解析器接受前导通配符 ✅
    │
    ↓
执行查询
    │
    ↓
全索引扫描 ❌
    │
    ↓
返回结果(可能很慢)


查询: term*
    │
    ↓
解析器接受后缀通配符 ✅
    │
    ↓
使用索引优化
    │
    ↓
执行查询 ✅


allowLeadingWildcard = false:

查询: *term
    │
    ↓
解析器拒绝前导通配符 ❌
    │
    ↓
返回错误:
"Cannot parse '...
leading wildcard is not allowed"

通配符位置说明 #

通配符位置示例

前导通配符(allowLeadingWildcard 控制的):
*term     ← * 在开头 ❌
?term     ← ? 在开头 ❌

后缀通配符(不受影响):
term*     ← * 在结尾 ✅
term?     ← ? 在结尾 ✅

中间通配符(不受影响):
te*rm     ← * 在中间 ✅
te?rm     ← ? 在中间 ✅

全索引扫描问题 #

前导通配符导致的性能问题

查询: *prod

执行计划:
1. 扫描所有分片
2. 读取所有文档
3. 检查每个文档是否包含 "prod"
4. 返回匹配结果

影响:
├── 无法使用索引优化
├── 读取大量磁盘
├── 消耗大量 CPU
├── 查询延迟很高
└── 可能导致 DoS

替代方案:
- 前缀查询: prefix query
- 通配符查询但避免前导: prod*
- 反向索引: 反转词 + ngram

配置建议 #

生产环境(推荐禁用) #

indices:
  query:
    query_string:
      allowLeadingWildcard: false  # 推荐禁用

建议: 设置为 false。防止性能问题和 DoS 攻击。

开发环境 #

indices:
  query:
    query_string:
      allowLeadingWildcard: true  # 允许使用

建议: 保持 true。开发环境需要灵活性。

特定业务需求 #

indices:
  query:
    query_string:
      allowLeadingWildcard: true

建议: 仅在确实需要前导通配符时使用,并监控查询性能。

代码示例 #

easysearch.yml 基础配置 #

indices:
  query:
    query_string:
      allowLeadingWildcard: true

禁用前导通配符(推荐) #

indices:
  query:
    query_string:
      allowLeadingWildcard: false

完整查询配置 #

indices:
  query:
    query_string:
      allowLeadingWildcard: false
      analyze_wildcard: true

动态更新配置 #

PUT /_cluster/settings
{
  "transient": {
    "indices.query.query_string.allowLeadingWildcard": false
  }
}

相关配置 #

配置项作用默认值
indices.query.query_string.allowLeadingWildcard是否允许前导通配符true
indices.query.query_string.analyze_wildcard是否分析通配符true

查询示例 #

允许前导通配符 #

GET /_search
{
  "query": {
    "query_string": {
      "query": "*product"  // 前导通配符
    }
  }
}

禁用后会被拒绝 #

GET /_search
{
  "query": {
    "query_string": {
      "query": "*product"
    }
  }
}
// 错误: leading wildcard is not allowed

推荐的替代方案 #

// 使用前缀查询
GET /_search
{
  "query": {
    "prefix": {
      "field": "name",
      "value": "prod"
    }
  }
}
// 使用后缀通配符
GET /_search
{
  "query": {
    "query_string": {
      "query": "product*"
    }
  }
}

性能影响分析 #

allowLeadingWildcard 设置优点缺点
true(默认)灵活查询性能风险、DoS 风险
false防止慢查询限制查询灵活性

查询性能对比 #

查询性能对比

查询: *term

allowLeadingWildcard = true:
耗时: 10-30 秒(全索引扫描)
CPU: 高
磁盘: 高

allowLeadingWildcard = false:
耗时: 拒绝查询
CPU: 无
磁盘: 无


替代方案: term*
耗时: 10-50 毫秒(使用索引)
CPU: 低
磁盘: 低

安全考虑 #

DoS 攻击防护

恶意用户可能:
├── 发送大量前导通配符查询
├── 每个查询触发全索引扫描
├── 消耗大量 CPU 和磁盘 I/O
└── 导致服务不可用

防护措施:
├── 设置 allowLeadingWildcard = false
├── 限制慢查询的执行时间
├── 使用查询熔断器
└── 监控异常查询模式

使用场景 #

推荐禁用的场景 #

  • 生产环境: 防止性能问题和 DoS 攻击
  • 公开 API: 外部用户可访问的 API
  • 大数据量: 索引数据量很大
  • 性能敏感: 对查询性能要求高

推荐启用的场景 #

  • 内部工具: 内部管理工具
  • 小数据集: 数据量很小的场景
  • 受控环境: 用户可信任的环境
  • 特殊需求: 确实需要前导通配符

替代方案 #

前导通配符的替代方案

1. 前缀查询 (Prefix Query)

GET /_search
{
  "query": {
    "prefix": {
      "field": "name",
      "value": "prod"
    }
  }
}

适用: 搜索以特定字符串开头的文档


2. 后缀通配符

GET /_search
{
  "query": {
    "query_string": {
      "query": "product*"
    }
  }
}

适用: 搜索以特定字符串结尾的文档


3. 通配符查询 (Wildcard Query)

GET /_search
{
  "query": {
    "wildcard": {
      "field": "name",
      "value": "prod*"
    }
  }
}

适用: 更灵活的模式匹配


4. 反向索引 + ngram

索引时: 反转词语并使用 ngram

查询时: 反转查询词

适用: 复杂模式匹配

注意事项 #

  1. 默认值: 默认值为 true,但生产环境建议禁用。

  2. 性能影响: 前导通配符会导致全索引扫描,性能极差。

  3. DoS 风险: 恶意用户可能利用此进行 DoS 攻击。

  4. 查询级别: 此配置在索引级别生效。

  5. 动态更新: 支持动态更新,修改后立即生效。

  6. 替代方案: 应该使用前缀查询或后缀通配符。

  7. 监控建议: 监控慢查询日志,发现前导通配符查询。

  8. 查询优化: 禁用后应优化查询语句,避免使用前导通配符。

  9. 用户教育: 教育用户避免使用前导通配符查询。

  10. 测试验证: 禁用后需要验证所有查询是否正常工作。