web-dev-qa-db-ja.com

インデックスのフィールド数を取得する

最適化の目的で、合計フィールド数を削減しようとしています。ただし、その前に、実際にフィールドがいくつあるかを把握したいと思います。 _statsエンドポイントに情報がないようで、移行ツールがフィールド数の計算をどのように行うのかよくわかりません。

エンドポイントを使用するか、他の方法で、指定されたインデックスの合計フィールド数を取得する方法はありますか?

10
Fairy

他の回答が提供したものをさらに構築するために、マッピングを取得してから、キーワードtypeが出力に表示される回数を数えるだけで、各フィールドにはタイプが必要なため、フィールドの数がわかります。 :

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

ヴァルによる最初の答えは私にとっても問題を解決します。しかし、誤解を招くような数字につながる可能性のあるいくつかのコーナーケースをリストアップしたかっただけです。

  1. ドキュメントには、「タイプ」という単語が含まれるフィールドがあります。

例えば

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

これはgrep typeに3回一致しますが、2回だけ一致する必要があります。つまり、「content_type」とは一致しないはずです。このシナリオは簡単に修正できます。

の代わりに

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

使用する

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

'"type"'の完全一致を取得するには

  1. ドキュメントには、正確な名前「タイプ」のフィールドがあります

例えば

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

この場合も、試合は2回ではなく3回です。しかし、

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

それをカットするつもりはありません。完全一致だけでなく、部分文字列として「type」キーワードを含むフィールドをスキップする必要があります。この場合、次のようにフィルターを追加できます。

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

上記の2つのシナリオに加えて、APIをプログラムで使用して追跡用の番号をプッシュする場合、つまりAWSクラウドウォッチや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

3
Saurabh Hirani

あなたはこれを試すことができます:

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

スクリプトを記述せずにKibanaで相対的な見積もりを取得する簡単な方法(これが100%正確であるとは思わないが、簡単な方法です動的フィールドが何らかの理由で膨大な数に爆発しているかどうかを確認するため)。

Kibana開発ツールでこのクエリを実行します

GET /index_name/_mapping

Kibana出力内で、"type"のすべてのインスタンス(引用符を含む)に対してsearchを実行します。これにより、インスタンスがカウントされ、回答が得られます。 (この例では、804)

enter image description here

これは、[remote_transport_exception]エラーが発生する理由について頭を悩ませている場合に役立ちます。

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

1
Matthew Rideout

その情報は、インデックスAPIの_mappingエンドポイントで取得できます。 https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-mapping.htmlを参照してください。

Get Mapping APIを使用すると、インデックスまたはインデックス/タイプのマッピング定義を取得できます。

GET/Twitter/_mapping/Tweet

カールあり:curl [elasticsearch adress]/[index]/_mapping?pretty

1
baudsp

フィールドには、複数の「タイプ」を含めることができます。

"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
Anish