适用版本: 7.9-8.9
1. 错误异常的基本描述 #
Can only use wildcard queries on keyword, text and wildcard fields - not on [...] 是 Elasticsearch 在执行 wildcard 查询时抛出的类型校验异常。该错误表明:你正在对一个不支持通配符查询的字段类型发起 wildcard 查询,Elasticsearch 在查询解析阶段即拒绝执行。
常见现象 #
- 搜索接口直接返回 HTTP
400 Bad Request,请求体被拒绝执行。 - 应用侧表现为搜索无结果、异常抛出,或客户端 SDK 捕获到
illegal_argument_exception。 - Kibana 或应用日志中出现类似如下报错信息:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Can only use wildcard queries on keyword, text and wildcard fields - not on [age] which is of type [integer]"
}
],
"type": "illegal_argument_exception",
"reason": "Can only use wildcard queries on keyword, text and wildcard fields - not on [age] which is of type [integer]"
},
"status": 400
}
典型报错与异常栈 #
illegal_argument_exception: Can only use wildcard queries on keyword, text and wildcard fields - not on [price] which is of type [long]
at org.elasticsearch.index.query.WildcardQueryBuilder.doToQuery(WildcardQueryBuilder.java:...)
at org.elasticsearch.index.query.AbstractQueryBuilder.toQuery(AbstractQueryBuilder.java:...)
2. 为什么会发生这个错误 #
wildcard 查询底层依赖 Lucene 的 WildcardQuery,它只对字符串类型的字段有意义。Elasticsearch 在查询重写阶段会校验字段类型,若字段类型不在允许范围内,则直接抛出 illegal_argument_exception。
常见原因 #
- 字段类型不匹配:对
integer、long、double、boolean、date、geo_point等非字符串类型字段使用了wildcard查询。 - 字段映射理解错误:以为某个字段是
keyword类型,但实际上它是数值类型或text类型未配置keyword子字段。 - 动态映射导致类型不符预期:写入的第一条数据决定了字段类型,若误写入数值,后续将无法对该字段执行
wildcard查询。 - 跨索引查询时字段类型不一致:在多个索引中同名字段的映射类型不同,查询时命中了类型不支持的索引。
哪些字段类型支持 wildcard 查询 #
| 字段类型 | 是否支持 wildcard 查询 | 说明 |
|---|---|---|
keyword | 支持 | 推荐用于精确通配符匹配 |
text | 支持 | 对分词后的词项做通配符匹配 |
wildcard | 支持 | ES 7.9+ 专为此场景优化的类型 |
integer / long / double | 不支持 | 数值类型无意义 |
boolean | 不支持 | 只有 true / false |
date | 不支持 | 应使用 range 查询 |
geo_point / geo_shape | 不支持 | 应使用地理查询 |
3. 如何排查这个异常 #
第一步:确认报错字段及其类型 #
使用以下 API 查看目标字段的 mapping:
GET /your_index/_mapping
重点关注报错信息中提示的字段名及其 type,例如:
{
"your_index": {
"mappings": {
"properties": {
"product_code": { "type": "keyword" },
"price": { "type": "long" },
"description": { "type": "text" }
}
}
}
}
若报错提示 not on [price] which is of type [long],则说明你正对 price 字段使用 wildcard 查询,这是不被允许的。
第二步:检查查询 DSL #
确认你的查询 DSL 是否类似如下结构:
{
"query": {
"wildcard": {
"price": {
"value": "*100*"
}
}
}
}
上述查询对 long 类型的 price 字段使用了 wildcard,会触发该异常。
第三步:检查是否存在跨索引字段类型冲突 #
GET /index1,index2/_mapping/field/field_name
若不同索引中同名字段类型不一致,可使用 ignore_unavailable 或指定单个索引进行排查。
4. 如何解决这个错误 #
方案一:改用支持 wildcard 的字段 #
若业务上确实需要对该字段做通配符模糊匹配,将该字段映射为 keyword 或 wildcard 类型:
PUT /your_index/_mapping
{
"properties": {
"product_code": {
"type": "wildcard"
}
}
}
注意: 修改已有索引的字段类型需要 重建索引(Reindex),无法直接修改。
方案二:重建索引并修正 mapping #
# 1. 创建新索引,使用正确的字段类型
PUT /your_index_new
{
"mappings": {
"properties": {
"product_code": { "type": "wildcard" },
"price": { "type": "long" }
}
}
}
# 2. 使用 Reindex API 迁移数据
POST /_reindex
{
"source": { "index": "your_index" },
"dest": { "index": "your_index_new" }
}
# 3. 切换到新索引(更新别名)
POST /_aliases
{
"actions": [
{ "remove": { "index": "your_index", "alias": "your_alias" }},
{ "add": { "index": "your_index_new", "alias": "your_alias" }}
]
}
方案三:改用合适的查询类型 #
若字段本身是数值或日期类型,不应使用 wildcard 查询,应改用:
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 200
}
}
}
}
或对于 keyword 字段的精确前缀匹配,可优先考虑 prefix 查询(性能更好):
{
"query": {
"prefix": {
"product_code": {
"value": "ABC"
}
}
}
}
5. 预防建议与最佳实践 #
- 设计 mapping 时明确字段用途:需要模糊匹配的字符串字段,优先使用
wildcard类型(ES 7.9+)或keyword类型。 - 避免使用动态映射处理关键字段:对业务核心字段显式定义 mapping,防止类型推断错误。
- 数值、日期、布尔字段不使用 wildcard 查询:这是最常见的误用场景,应在代码层面增加校验。
- 跨索引查询前统一字段映射:使用索引模板(Index Template)保证同名字段在各索引中类型一致。
- 使用
wildcard类型替代keyword做模糊查询:在 ES 7.9+ 中,wildcard类型对通配符查询做了专门优化,性能和存储效率更优。
6. 借助 INFINI 产品提升排障效率 #
- INFINI Console 可查看索引 mapping、字段类型分布和查询错误趋势,帮助快速确认字段类型是否符合查询预期。
- INFINI Gateway 可部署在 Elasticsearch 前端,对非法查询 DSL 进行拦截和改写,防止类型不匹配的查询进入集群。
- 建议将慢查询日志、异常查询和字段映射变更统一接入监控面板,在查询报错前主动发现 mapping 设计问题。
7. 小结 #
Can only use wildcard queries on keyword, text and wildcard fields 是一个典型的字段类型与查询方式不匹配的错误。核心解决思路是:确认报错字段的真实类型,要么将字段改为支持通配符查询的类型(需重建索引),要么改用适合该字段类型的查询方式。
在设计索引 mapping 时提前规划字段用途,是避免此类问题的最有效手段。
相关错误 #
- unknown-vector-index-options-type-type-for-field-fieldname:未知的向量索引选项类型
- unsupported-field-fieldname:不支持的字段名
- wrong-value-for-termvector-termvector-for-field-fieldname:termvector字段值错误
- unknown-property-fieldname:未知属性字段
- unknown-string-property-fieldname:未知字符串属性
附:日志上下文 #
public Query wildcardQuery(String value,
@Nullable MultiTermQuery.RewriteMethod method,
boolean caseInsensitive,
SearchExecutionContext context) {
throw new QueryShardException(context,
"Can only use wildcard queries on keyword, text and wildcard fields - not on [" + name
+ "] which is of type [" + typeName() + "]");
}





