在使用 ElasticSearch 的时候,如果索引中的字段是 text 类型,针对该字段聚合、排序和查询的时候常会出现 Fielddata is disabled on text fields by default. Set fielddata=true 的错误。本文总结这个错误出现的原因,可能的修复方法等。

这个问题的解决方法并没有尝试过

常见原因

在 ElasticSearch 中,Fielddata 默认在 text 类型的字段时是不启用的。设想,如果默认打开,那么你的数据中,每个字符串大概率不一样的话,那么这个字段需要的集合大小(Cardinality)会非常大。

而这个字段是需要存在内存中的 (heap),因此不可能默认打开。所以如果你从一个 script 来对一个 text 字段进行排序、聚合或者查询的话,就会出现这个错误。

Fielddata is disabled on text fields by default. Set fielddata=true on
[你的字段名字] in order to load fielddata in memory by uninverting the
inverted index. Note that this can however use significant memory.

错误表现

出现这个错误的返回 JSON 会类似如下,root_cause 字段中的类型为 illegal_argument_exception。

{
    "error": {
        "root_cause": [
            {
                "type": "illegal_argument_exception",
                "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [YOUR_FIELD] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
            }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
            {
                "shard": 0,
                "index": "XXXX",
                "node": "YOUR_NODE",
                "reason": {
                    "type": "illegal_argument_exception",
                    "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [YOUR_FIELD] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
                }
            }
        ]
    },
    "status": 400
}

多数情况下这个错误其实信息量相对大,且指导清晰了,无非查询的字段里没有 enable fielddata。但有时,如果你重新定义了 mapping ,则很有可能在查询时少了后缀的 .keyword (具体请见下文)

如何解决

  1. 尝试用 keyword 类型
    尝试将对应的字段 map 成 keyword 类型。比如说:
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_field": { 
        "type": "text",
        "fields": {
          "keyword": { 
            "type": "keyword"
          }
        }
      }
    }
  }
}

但请注意,如果 map 过后,查询时的字段需要加上后缀 .keyword。比如如果你的字段如上是叫 my_field 那么查询时需要使用 my_field.keyword (参考: How to fix ElasticSearch ‘Fielddata is disabled on text fields by default’ for keyword field)

es.search(index="strings", body={
    "size": 0,
    "aggs" : {
        "patterns" : {
            "terms" : { "field" : "pattern.keyword" }
        }
    }
  1. 对已存在字段更改 mapping
    如果这个字段已经存在的话,那么你需要把这个字段的 fielddata 改为 true。比如说,用以下 PUT 方法:
PUT my-index-000001/_mapping
{
  "properties": {
    "my_field": { 
      "type":     "text",
      "fielddata": true
    }
  }
}
  1. 重建索引
    如果按方法 1 和 2 中的方式调整过后仍然有错误的话,建议重新建立索引。(参考How to fix ElasticSearch ‘Fielddata is disabled on text fields by default’ for keyword field)

总结

多数情况下,出现 Fielddata 相关的错误都是因为尝试聚合和排序一个 text 字段,因此只要把字段的 fielddata 设为 true 或者类型调整为 keyword 即可。如果是已存在字段可能需要重新索引。

index.highlight.max_analyzed_offset

错误表现

我在用python添加数据到es,在使用kibana查询的时候,查询全部是没有问题的,但是查询某个字段,例如 status时,就会报上面的错误,字面意思是该索引超过了最大偏移量

如何解决

  1. 百度上的解决方法几乎都是调整该索引的最大偏移量,有的文章也解释了调整之后的利弊,奈何才疏学浅,暂时理解不了。

    后来经过多次百度及询问同事,发现偏移量的意思,不准确的解释就是说这个字段的值太大了,以至于筛选的时候超过了最大限制,我的办法是把这个值的长度做一个限制,就解决了。

  2. 调整该索引的最大偏移量,看网上说不要调的太大,会影响内存,具体不是很明白

在kibana的Dev Tools中执行

PUT <your_index_name>/_settings
{
“index.highlight.max_analyzed_offset”: 1000000000
}

todo 在使用LogStash把mysql中的数据导入到es中,从ElasticSearch-head发现数据不一致了,但是查出来的结果是一致的

注意id

在这里插入图片描述
在这里插入图片描述

部分知识引用:https://kalasearch.cn/community/tutorials/elasticsearch-fielddata-is-disabled-on-text-fields-error/

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐