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

适用版本: 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

常见原因 #

  • 字段类型不匹配:对 integerlongdoublebooleandategeo_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 的字段 #

若业务上确实需要对该字段做通配符模糊匹配,将该字段映射为 keywordwildcard 类型

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 时提前规划字段用途,是避免此类问题的最有效手段。

相关错误 #

附:日志上下文 #

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() + "]");
}