--- title: "验证查询" date: 2026-01-26 lastmod: 2026-01-26 description: "验证查询语句是否有效,不实际执行查询" tags: ["搜索", "查询验证", "调试"] summary: "验证查询语句是否有效,检查查询语法和参数,不实际执行查询。 API # GET /_validate/query POST /_validate/query GET /{index}/_validate/query POST /{index}/_validate/query API 的作用 # 该 API 用于验证查询语句的有效性,帮助调试和优化查询。 验证 API 的功能 # 功能 描述 语法检查 验证查询语法是否正确 错误信息 提供详细的错误信息 重写查询 显示实际执行的 Lucene 查询 验证范围 在索引或分片级别验证 与 Explain API 的区别 # API 用途 /_validate/query 验证查询语法,不检查具体文档 /_explain/{id} 计算特定文档的评分 API 的参数 # 路由参数 # 参数 类型 是否必填 描述 {index} 字符串 否 索引名称。支持:单个索引、逗号分隔的多个索引、通配符表达式 Query String 参数 # 验证控制参数 # 参数 类型 是否必填 默认值 描述 explain 布尔值 否 false 是否返回详细的错误信息 rewrite 布尔值 否 false 是否提供实际的 Lucene 查询语句 all_shards 布尔值 否 false 是否在所有分片上执行验证 查询参数 # 参数 类型 是否必填 默认值 描述 q 字符串 否 - Lucene 查询字符串 analyzer 字符串 否 - 查询字符串的分析器 analyze_wildcard 布尔值 否 false 是否分析通配符和前缀查询 default_operator 枚举值 否 OR 默认操作符:AND、OR df 字符串 否 - 查询字符串的默认字段 lenient 布尔值 否 false 是否忽略基于格式的失败 索引选项参数 # 参数 类型 是否必填 默认值 描述 ignore_unavailable 布尔值 否 false 是否忽略不可用的索引 allow_no_indices 布尔值 否 false 是否允许空索引结果 expand_wildcards 枚举值 否 open 通配符展开方式 请求体参数(POST) # { "query": { ." --- 验证查询语句是否有效,检查查询语法和参数,不实际执行查询。 ## API ``` GET /_validate/query POST /_validate/query GET /{index}/_validate/query POST /{index}/_validate/query ``` ## API 的作用 该 API 用于验证查询语句的有效性,帮助调试和优化查询。 ### 验证 API 的功能 | 功能 | 描述 | |------|------| | **语法检查** | 验证查询语法是否正确 | | **错误信息** | 提供详细的错误信息 | | **重写查询** | 显示实际执行的 Lucene 查询 | | **验证范围** | 在索引或分片级别验证 | ### 与 Explain API 的区别 | API | 用途 | |-----|------| | `/_validate/query` | 验证查询语法,不检查具体文档 | | `/_explain/{id}` | 计算特定文档的评分 | ## API 的参数 ### 路由参数 | 参数 | 类型 | 是否必填 | 描述 | |------|------|----------|------| | `{index}` | 字符串 | 否 | 索引名称。支持:单个索引、逗号分隔的多个索引、通配符表达式 | ### Query String 参数 #### 验证控制参数 | 参数 | 类型 | 是否必填 | 默认值 | 描述 | |------|------|----------|--------|------| | `explain` | 布尔值 | 否 | false | 是否返回详细的错误信息 | | `rewrite` | 布尔值 | 否 | false | 是否提供实际的 Lucene 查询语句 | | `all_shards` | 布尔值 | 否 | false | 是否在所有分片上执行验证 | #### 查询参数 | 参数 | 类型 | 是否必填 | 默认值 | 描述 | |------|------|----------|--------|------| | `q` | 字符串 | 否 | - | Lucene 查询字符串 | | `analyzer` | 字符串 | 否 | - | 查询字符串的分析器 | | `analyze_wildcard` | 布尔值 | 否 | false | 是否分析通配符和前缀查询 | | `default_operator` | 枚举值 | 否 | OR | 默认操作符:`AND`、`OR` | | `df` | 字符串 | 否 | - | 查询字符串的默认字段 | | `lenient` | 布尔值 | 否 | false | 是否忽略基于格式的失败 | #### 索引选项参数 | 参数 | 类型 | 是否必填 | 默认值 | 描述 | |------|------|----------|--------|------| | `ignore_unavailable` | 布尔值 | 否 | false | 是否忽略不可用的索引 | | `allow_no_indices` | 布尔值 | 否 | false | 是否允许空索引结果 | | `expand_wildcards` | 枚举值 | 否 | open | 通配符展开方式 | ### 请求体参数(POST) ```json { "query": { ... } } ``` ## 示例 ### 验证查询语法 ```bash POST /my_index/_validate/query { "query": { "bool": { "must": [ { "match": { "title": "search" } } ], "filter": [ { "term": { "status": "published" } } ] } } } ``` **有效响应:** ```json { "valid": true, "_shards": { "total": 1, "successful": 1, "failed": 0 } } ``` ### 验证无效查询 ```bash POST /my_index/_validate/query { "query": { "match": { "title": 123 } } } ``` **无效响应:** ```json { "valid": false, "error": "org.easysearch.index.query.QueryShardException: [match] failed to parse query" } ``` ### 获取详细错误信息 ```bash POST /my_index/_validate/query?explain=true { "query": { "match": { "message": "search" } } } ``` ### 重写查询 ```bash POST /my_index/_validate/query?rewrite=true { "query": { "query_string": { "query": "title:search OR content:search" } } } ``` **响应示例:** ```json { "valid": true, "shards": { "total": 1, "successful": 1, "failed": 0 }, "explanations": [ { "index": "my_index", "shard": 0, "node": "node1", "explanation": "..." } ] } ``` ### 在所有分片上验证 ```bash POST /my_index/_validate/query?all_shards=true { "query": { "term": { "user": "kimchy" } } } ``` ### 使用查询字符串 ```bash GET /my_index/_validate/query?q=title:easysearch ``` ### 带查询字符串参数 ```bash GET /my_index/_validate/query?q=title:search&lenient=true ``` ### 验证多索引查询 ```bash POST /index1,index2/_validate/query { "query": { "match_all": {} } } ``` ### 使用通配符 ```bash POST /logs-*/_validate/query { "query": { "range": { "@timestamp": { "gte": "now-1d" } } } } ``` ## 响应字段说明 ### 有效查询响应 | 字段 | 描述 | |------|------| | `valid` | 是否有效(true) | | `_shards` | 分片信息 | | `explanations` | 重写查询的解释(rewrite=true 时) | ### 无效查询响应 | 字段 | 描述 | |------|------| | `valid` | 是否有效(false) | | `error` | 错误信息 | | `explanations` | 分片级别的验证详情 | ## 使用场景 ### 场景 1:查询开发 ```bash POST /my_index/_validate/query?explain=true { "query": { "bool": { "must": [ { "match": { "title": "search" } }, { "range": { "created_at": { "gte": "2026-01-01" } } } ] } } } ``` ### 场景 2:语法调试 ```bash POST /my_index/_validate/query { "query": { "query_string": { "query": "title:(easysearch) AND status:active" } } } ``` ### 场景 3:性能优化 ```bash POST /my_index/_validate/query?rewrite=true { "query": { "bool": { "should": [ { "match": { "title": "test" } }, { "match": { "content": "test" } } ] } } } ``` ### 场景 4:复杂查询验证 ```bash POST /my_index/_validate/query { "query": { "nested": { "path": "comments", "query": { "match": { "comments.author": "john" } } } } } ``` ## 常见错误 ### 语法错误 ```json { "valid": false, "error": "org.easysearch.common.parsing ParsingException: [match] malformed query, ..." } ``` ### 字段不存在 ```json { "valid": false, "error": "No mapping found for [nonexistent_field] in order to sort on" } ``` ### 类型不匹配 ```json { "valid": false, "error": "Cannot use range query on [price] of type [text]" } ``` ## 最佳实践 1. **开发阶段**:在开发阶段使用验证 API 检查查询 2. **复杂查询**:验证复杂的 Bool 和 Nested 查询 3. **重构查询**:使用 rewrite 查看优化后的查询 4. **多索引**:在跨索引查询前验证 5. **生产部署**:部署前验证查询的正确性 ## 注意事项 1. **不返回数据**:只验证查询,不返回文档 2. **性能开销**:explain=true 会增加性能开销 3. **分片验证**:all_shards=true 会增加开销 4. **类型已弃用**:有类型的 API 已被弃用