--- title: "查询字符串前导通配符允许配置" date: 2026-01-01 lastmod: 2026-01-01 description: "indices.query.query_string.allowLeadingWildcard 配置项用于控制是否允许查询字符串使用前导通配符。" tags: ["查询", "通配符", "QueryString", "性能优化"] summary: "配置项作用 # indices.query.query_string.allowLeadingWildcard 配置项用于控制查询字符串解析器是否允许使用通配符(* 或 ?)作为查询词的开头。 前导通配符查询(如 *search 或 ?query)会导致全索引扫描,严重影响性能。此配置可以禁用此类查询以保护系统。 配置项属性 # 配置路径: indices.query.query_string.allowLeadingWildcard 数据类型: Boolean(布尔值) 默认值: true 是否可选: 是 作用域: NodeScope(节点级别) 配置项详解 # 工作机制 # 前导通配符查询流程 allowLeadingWildcard = true (默认): 查询: *term │ ↓ 解析器接受前导通配符 ✅ │ ↓ 执行查询 │ ↓ 全索引扫描 ❌ │ ↓ 返回结果(可能很慢) 查询: term* │ ↓ 解析器接受后缀通配符 ✅ │ ↓ 使用索引优化 │ ↓ 执行查询 ✅ allowLeadingWildcard = false: 查询: *term │ ↓ 解析器拒绝前导通配符 ❌ │ ↓ 返回错误: "Cannot parse '." --- ## 配置项作用 `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 ``` ## 配置建议 ## 生产环境(推荐禁用) ```yaml indices: query: query_string: allowLeadingWildcard: false # 推荐禁用 ``` **建议**: 设置为 `false`。防止性能问题和 DoS 攻击。 ## 开发环境 ```yaml indices: query: query_string: allowLeadingWildcard: true # 允许使用 ``` **建议**: 保持 `true`。开发环境需要灵活性。 ## 特定业务需求 ```yaml indices: query: query_string: allowLeadingWildcard: true ``` **建议**: 仅在确实需要前导通配符时使用,并监控查询性能。 ## 代码示例 ## easysearch.yml 基础配置 ```yaml indices: query: query_string: allowLeadingWildcard: true ``` ## 禁用前导通配符(推荐) ```yaml indices: query: query_string: allowLeadingWildcard: false ``` ## 完整查询配置 ```yaml indices: query: query_string: allowLeadingWildcard: false analyze_wildcard: true ``` ## 动态更新配置 ```json PUT /_cluster/settings { "transient": { "indices.query.query_string.allowLeadingWildcard": false } } ``` ## 相关配置 | 配置项 | 作用 | 默认值 | |--------|------|--------| | `indices.query.query_string.allowLeadingWildcard` | 是否允许前导通配符 | true | | `indices.query.query_string.analyze_wildcard` | 是否分析通配符 | true | ## 查询示例 ## 允许前导通配符 ```json GET /_search { "query": { "query_string": { "query": "*product" // 前导通配符 } } } ``` ## 禁用后会被拒绝 ```json GET /_search { "query": { "query_string": { "query": "*product" } } } // 错误: leading wildcard is not allowed ``` ## 推荐的替代方案 ```json // 使用前缀查询 GET /_search { "query": { "prefix": { "field": "name", "value": "prod" } } } ``` ```json // 使用后缀通配符 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. **测试验证**: 禁用后需要验证所有查询是否正常工作。