Elasticsearch:fielddata 介绍

1021 篇文章 595 订阅

默认情况下,大多数字段都已编入索引,这使它们可搜索。 但是,脚本中的排序,聚合和访问字段值需要与搜索不同的访问模式。

搜索需要回答“哪个文档包含该术语?”这个问题,而排序和汇总则需要回答一个不同的问题:“此字段对该文档的值是什么?”。

大多数字段可以将索引时生产的磁盘 doc_values 用于此数据访问模式,但是文本(text)字段不支持 doc_values。

替代的方案,文本(text)字段使用查询时内存中的数据结构,称为 fielddata。 当我们首次将该字段用于聚合,排序或在脚本中使用时,将按需构建此数据结构。 它是通过从磁盘读取每个段的整个反向索引,反转术语 ↔︎ 文档关系并将结果存储在 JVM 堆中的内存中来构建的。

Fielddata 针对 text 字段在默认时是禁用的

Fielddata 会占用大量堆空间,尤其是在加载大量的文本字段时。 一旦将字段数据加载到堆中,它在该段的生命周期内将一直保留在那里。 同样,加载字段数据是一个昂贵的过程,可能导致用户遇到延迟的情况。 这就是默认情况下禁用字段数据的原因。

假如我们创建一个如下的myindex的索引:

PUT myindex
{
  "mappings": {
    "properties": {
      "address": {
        "type": "text"
      }
    }
  }
}

PUT myindex/_doc/1
{
  "address": "New York"  
}

如果你尝试对文本字段中的脚本进行排序,汇总或访问值:

GET myindex/_search
{
  "size": 20,
  "aggs": {
    "aggr_mame": {
      "terms": {
        "field": "address",
        "size": 5
      }
    }
  }
}

则会看到以下异常:

显然,我们不能对 text 字段进行聚合处理。那么我们该如何处理这个问题呢?

我们的一种方法就是在配置 mapping 的时候加入"fielddata"=true 这个选项。我们来重新对我们的 myindex 的 mapping 进行配置:

DELETE myindex

PUT myindex
{
  "mappings": {
    "properties": {
      "address": {
        "type": "text",
        "fielddata": true
      }
    }
  }
}

PUT myindex/_doc/1
{
  "address": "New York"  
}

GET myindex/_search
{
  "size": 0,
  "aggs": {
    "aggr_mame": {
      "terms": {
        "field": "address",
        "size": 5
      }
    }
  }
}

另外一种方法就是直接在现有的索引 mapping 上进行修改,而不用删除该索引:

PUT myindex/_mapping
{
  "properties": {
    "address": {
      "type": "text",
      "fielddata": true
    }
  }
}

那么,通过这样的动态修改,我们就直接可以对该字段 address 进行数据统计了。

在这里,我们尽管还是把 address 这个字段设置为 text,但是由于我们加入了 "fielddata"=true,那么我们,我们就可以对这个项进行统计了。

与简单的搜索操作不同,排序和聚合需要能够发现在特定文档的特定字段中可以找到哪些术语。 对于这些任务和其他任务,必须具有与Elasticsearch(反向)索引相反的数据结构。 这就是 fielddata 的目的。

细心的开发者,如果这个时候去 Kibana 创建一个以 myindex 为索引的 index pattern,我们可以发现:

我们的 address 字段变为 aggregatable,也就是说我们可以对它进行做聚合分析尽管它没有 doc_values。

在启动 fielddata之 前

在启用 fielddata 之前,请考虑为什么将文本字段用于聚合,排序或在脚本中使用。 这样做通常没有任何意义。

在索引之前会分析文本字段,以便可以通过搜索 new 或 york 来找到类似 New York 的值。 当你可能想要一个名为 New York 的存储桶时,此字段上的术语汇总将返回一个叫做 new 存储桶和一个叫做 york 存储桶。

相反,你应该有一个用于全文搜索的文本字段,以及一个为聚合启用 doc_values 的未分析的 keyword 字段,如下所示:

DELETE myindex

PUT myindex
{
  "mappings": {
    "properties": {
      "address": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

这样,我们可以使用 address 来做全文的搜索,而 address.keyword 被用来做 aggregations, sorting 及在脚本中使用。

参考:

【1】fielddata mapping parameter | Elasticsearch Guide [8.8] | Elastic

【2】https://qbox.io/blog/field-data-elasticsearch-cluster-instability

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值