获取索引的字段数

问题描述 投票:0回答:7

出于优化目的,我正在尝试减少我的总字段数。然而,在我这样做之前,我想了解一下我实际拥有多少个字段。

_stats
端点中似乎没有任何信息,我不太清楚迁移工具如何进行字段计数计算。

是否有某种方式,无论是通过端点还是其他方式,来获取指定索引的总字段数?

elasticsearch logstash
7个回答
48
投票

要进一步构建其他答案提供的内容,您可以获得映射,然后简单地计算关键字

type
出现在输出中的次数,这给出了字段数,因为每个字段都需要一个类型:

curl -s -XGET localhost:9200/index/_mapping?pretty | grep type | wc -l

27
投票

你可以试试这个:

curl -s -XGET "http://localhost:9200/index/_field_caps?fields=*" | jq '.fields|length'

10
投票

无需编写脚本即可在 Kibana 中获得相对估计的快速方法(我不相信这是 100% 精确的,但这是判断您的动态字段是否由于某种原因爆炸到巨大数字的简单方法).

在 Kibana 开发工具中运行此查询

GET /index_name/_mapping

在 Kibana 输出中,对 "type"(包括引号)的所有实例执行

search
。这将计算实例并为您提供答案。 (在这个例子中,804)

如果你摸不着头脑为什么会出现

[remote_transport_exception]
错误

,这可能会有所帮助

Limit of total fields [1000] in index [index_name] has been exceeded


6
投票

Val 的第一个答案也为我解决了这个问题。但我只是想列出一些可能导致误导性数字的极端情况。

  1. 文档中包含带有“type”字样的字段。

例如

 "content_type" : {
   "type" : "text",
     "fields" : {
       "keyword" : {
          "type" : "keyword",
       }
     }
   },

这将匹配

grep type
三次,而它应该只匹配两次,即它不应该匹配“content_type”。这种情况很容易解决。

代替

curl -s -XGET localhost:9200/index/_mapping?pretty | grep type 

使用

curl -s -XGET localhost:9200/index/_mapping?pretty | grep '"type"'

获得“类型”的精确匹配

  1. 文档有一个字段的确切名称为“类型”

例如

"type" : {
  "type" : "text",
   "fields" : {
     "keyword" : {
       "type" : "keyword"
     }
   }
},

在这种情况下,比赛也是三次而不是两次。但是使用

curl -s -XGET localhost:9200/index/_mapping?pretty | grep '"type"'

不会削减它。我们将不得不跳过以“type”关键字作为子字符串以及完全匹配的字段。在这种情况下,我们可以像这样添加一个额外的过滤器:

curl -s -XGET localhost:9200/index/_mapping?pretty |\
grep '"type"' | grep -v "{"

除了上述两种情况之外,如果您以编程方式使用 api 将数字推送到 AWS cloudwatch 或 Graphite 之类的东西中,您可以使用以下代码调用 API - 获取数据,并递归搜索关键字“type”——同时跳过任何模糊匹配并更深入地解析具有确切名称“type”的字段。

import sys
import json
import requests

# The following find function is a minor edit of the function posted here
# https://stackoverflow.com/questions/9807634/find-all-occurrences-of-a-key-in-nested-python-dictionaries-and-lists

def find(key, value):
  for k, v in value.iteritems():
    if k == key and not isinstance(v, dict) and not isinstance(v, list):
      yield v
    elif isinstance(v, dict):
      for result in find(key, v):
        yield result
    elif isinstance(v, list):
      for d in v:
        for result in find(key, d):
          yield result

def get_index_type_count(es_host):
  try:
    response = requests.get('https://%s/_mapping/' % es_host)
  except Exception as ex:
    print('Failed to get response - %s' % ex)
    sys.exit(1)

  indices_mapping_data = response.json()
  output = {}

  for index, mapping_data in indices_mapping_data.iteritems():
    output[index] = len(list(find('type', mapping_data)))

  return output

if __name__ == '__main__':
  print json.dumps(get_index_type_count(sys.argv[1]), indent=2)

上面的代码也作为要点发布在这里 - https://gist.github.com/saurabh-hirani/e8cbc96844307a41ff4bc8aa8ebd7459


1
投票

您可以使用索引 API 的

_mapping
端点获取该信息,请参阅https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.html

获取映射 API 允许检索索引或索引/类型的映射定义。

获取/twitter/_mapping/tweet

卷曲:

curl [elasticsearch adress]/[index]/_mapping?pretty


0
投票

一个字段可以有多个“类型”: 例如

"datapath-id": {
    "fields": {
        "keyword": {
            "ignore_above": 256, 
            "type": "keyword"
        }
    }, 
    "type": "text"
}

我们可以忽略“字段”中的“类型”以获得准确的字段数。一个例子是:

import json


def myprint(d, field_count):
    for k, v in d.iteritems():
        if isinstance(v, dict):
            if k != "fields":
                field_count = myprint(v, field_count)
        else:
            print "{0} : {1}".format(k, v)
            field_count += 1
    return field_count

with open("output/mappings.json") as f:
    d = json.load(f)
    final_field_count = myprint(d, field_count=0)
    print "field count", final_field_count

0
投票

我要求 chatGPT 为 jq 创建一个过滤器。
显示不包括 metadata_field 的计数。

curl -s -XGET  -u 'elastic:changeme' -k "http://localhost:9200/target_index/_field_caps?fields=*" | jq '.fields | with_entries(select(any(.value[]; .metadata_field == false))) | length'
© www.soinside.com 2019 - 2024. All rights reserved.