フィールド抽出
フィールド抽出の目的はシンプルです。データ内に多くの情報を含むフィールドがありますが、必要な部分だけを抽出したいのです。
利用可能なオプションは2つあります:
- Grokは、再利用可能なエイリアス式をサポートする正規表現の方言です。Grokは正規表現(regex)の上に位置しているため、通常の正規表現もgrokで有効です。
- Dissectは、区切り文字を使用して一致パターンを定義し、テキストから構造化されたフィールドを抽出します。grokとは異なり、dissectは正規表現を使用しません。
Ruby
response = client.indices.create(
index: 'my-index',
body: {
mappings: {
properties: {
"@timestamp": {
format: 'strict_date_optional_time||epoch_second',
type: 'date'
},
message: {
type: 'wildcard'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index",
mappings: {
properties: {
"@timestamp": {
format: "strict_date_optional_time||epoch_second",
type: "date",
},
message: {
type: "wildcard",
},
},
},
});
console.log(response);
コンソール
PUT /my-index/
{
"mappings": {
"properties": {
"@timestamp": {
"format": "strict_date_optional_time||epoch_second",
"type": "date"
},
"message": {
"type": "wildcard"
}
}
}
}
フィールドをマッピングした後、ログデータからいくつかのレコードをElasticsearchにインデックスします。次のリクエストは、bulk APIを使用して、生のログデータをmy-index
にインデックスします。すべてのログデータをインデックスする代わりに、小さなサンプルを使用してランタイムフィールドを試すことができます。
Python
resp = client.bulk(
index="my-index",
refresh=True,
operations=[
{
"index": {}
},
{
"timestamp": "2020-04-30T14:30:17-05:00",
"message": "40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
},
{
"index": {}
},
{
"timestamp": "2020-04-30T14:30:53-05:00",
"message": "232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
},
{
"index": {}
},
{
"timestamp": "2020-04-30T14:31:12-05:00",
"message": "26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
},
{
"index": {}
},
{
"timestamp": "2020-04-30T14:31:19-05:00",
"message": "247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"
},
{
"index": {}
},
{
"timestamp": "2020-04-30T14:31:22-05:00",
"message": "247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"
},
{
"index": {}
},
{
"timestamp": "2020-04-30T14:31:27-05:00",
"message": "252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
},
{
"index": {}
},
{
"timestamp": "2020-04-30T14:31:28-05:00",
"message": "not a valid apache log"
}
],
)
print(resp)
Ruby
response = client.bulk(
index: 'my-index',
refresh: true,
body: [
{
index: {}
},
{
timestamp: '2020-04-30T14:30:17-05:00',
message: '40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
},
{
index: {}
},
{
timestamp: '2020-04-30T14:30:53-05:00',
message: '232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
},
{
index: {}
},
{
timestamp: '2020-04-30T14:31:12-05:00',
message: '26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
},
{
index: {}
},
{
timestamp: '2020-04-30T14:31:19-05:00',
message: '247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] "GET /french/splash_inet.html HTTP/1.0" 200 3781'
},
{
index: {}
},
{
timestamp: '2020-04-30T14:31:22-05:00',
message: '247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] "GET /images/hm_nbg.jpg HTTP/1.0" 304 0'
},
{
index: {}
},
{
timestamp: '2020-04-30T14:31:27-05:00',
message: '252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
},
{
index: {}
},
{
timestamp: '2020-04-30T14:31:28-05:00',
message: 'not a valid apache log'
}
]
)
puts response
Js
const response = await client.bulk({
index: "my-index",
refresh: "true",
operations: [
{
index: {},
},
{
timestamp: "2020-04-30T14:30:17-05:00",
message:
'40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
},
{
index: {},
},
{
timestamp: "2020-04-30T14:30:53-05:00",
message:
'232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
},
{
index: {},
},
{
timestamp: "2020-04-30T14:31:12-05:00",
message:
'26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
},
{
index: {},
},
{
timestamp: "2020-04-30T14:31:19-05:00",
message:
'247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] "GET /french/splash_inet.html HTTP/1.0" 200 3781',
},
{
index: {},
},
{
timestamp: "2020-04-30T14:31:22-05:00",
message:
'247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] "GET /images/hm_nbg.jpg HTTP/1.0" 304 0',
},
{
index: {},
},
{
timestamp: "2020-04-30T14:31:27-05:00",
message:
'252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
},
{
index: {},
},
{
timestamp: "2020-04-30T14:31:28-05:00",
message: "not a valid apache log",
},
],
});
console.log(response);
コンソール
POST /my-index/_bulk?refresh
{"index":{}}
{"timestamp":"2020-04-30T14:30:17-05:00","message":"40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp":"2020-04-30T14:30:53-05:00","message":"232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp":"2020-04-30T14:31:12-05:00","message":"26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp":"2020-04-30T14:31:19-05:00","message":"247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"}
{"index":{}}
{"timestamp":"2020-04-30T14:31:22-05:00","message":"247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"}
{"index":{}}
{"timestamp":"2020-04-30T14:31:27-05:00","message":"252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
{"index":{}}
{"timestamp":"2020-04-30T14:31:28-05:00","message":"not a valid apache log"}
ログメッセージからIPアドレスを抽出する(Grok)
Js
const response = await client.indices.putMapping({
index: "my-index",
runtime: {
"http.clientip": {
type: "ip",
script:
"\n String clientip=grok('%{COMMONAPACHELOG}').extract(doc[\"message\"].value)?.clientip;\n if (clientip != null) emit(clientip); \n ",
},
},
});
console.log(response);
コンソール
PUT my-index/_mappings
{
"runtime": {
"http.clientip": {
"type": "ip",
"script": """
String clientip=grok('%{COMMONAPACHELOG}').extract(doc["message"].value)?.clientip;
if (clientip != null) emit(clientip);
"""
}
}
}
この条件は、メッセージのパターンが一致しなくてもスクリプトが何も出力しないことを保証します。 |
特定のIPアドレスを検索するための簡単なクエリを定義し、関連するすべてのフィールドを返すことができます。検索APIのfields
パラメータを使用して、http.clientip
ランタイムフィールドを取得します。
Python
resp = client.search(
index="my-index",
query={
"match": {
"http.clientip": "40.135.0.0"
}
},
fields=[
"http.clientip"
],
)
print(resp)
Ruby
response = client.search(
index: 'my-index',
body: {
query: {
match: {
'http.clientip' => '40.135.0.0'
}
},
fields: [
'http.clientip'
]
}
)
puts response
Js
const response = await client.search({
index: "my-index",
query: {
match: {
"http.clientip": "40.135.0.0",
},
},
fields: ["http.clientip"],
});
console.log(response);
コンソール
GET my-index/_search
{
"query": {
"match": {
"http.clientip": "40.135.0.0"
}
},
"fields" : ["http.clientip"]
}
[](#13f015769493c2dc4e56ea54945b1975)
#### コンソール-結果
``````console-result
{
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index",
"_id" : "Rq-ex3gBA_A0V6dYGLQ7",
"_score" : 1.0,
"_source" : {
"timestamp" : "2020-04-30T14:30:17-05:00",
"message" : "40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
},
"fields" : {
"http.clientip" : [
"40.135.0.0"
]
}
}
]
}
}
`
文字列を解析してフィールドの一部を抽出する(Dissect)
前の例のようにログパターンに一致させるのではなく、単に捨てたい文字列の部分を含むdissectパターンを定義できます。
たとえば、このセクションの最初にあるログデータにはmessage
フィールドが含まれています。このフィールドには、いくつかのデータが含まれています:
Js
"message" : "247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"
ランタイムフィールドでdissectパターンを定義して、前の例の304
であるHTTPレスポンスコードを抽出できます。
Python
resp = client.indices.put_mapping(
index="my-index",
runtime={
"http.response": {
"type": "long",
"script": "\n String response=dissect('%{clientip} %{ident} %{auth} [%{@timestamp}] \"%{verb} %{request} HTTP/%{httpversion}\" %{response} %{size}').extract(doc[\"message\"].value)?.response;\n if (response != null) emit(Integer.parseInt(response));\n "
}
},
)
print(resp)
Js
const response = await client.indices.putMapping({
index: "my-index",
runtime: {
"http.response": {
type: "long",
script:
'\n String response=dissect(\'%{clientip} %{ident} %{auth} [%{@timestamp}] "%{verb} %{request} HTTP/%{httpversion}" %{response} %{size}\').extract(doc["message"].value)?.response;\n if (response != null) emit(Integer.parseInt(response));\n ',
},
},
});
console.log(response);
コンソール
PUT my-index/_mappings
{
"runtime": {
"http.response": {
"type": "long",
"script": """
String response=dissect('%{clientip} %{ident} %{auth} [%{@timestamp}] "%{verb} %{request} HTTP/%{httpversion}" %{response} %{size}').extract(doc["message"].value)?.response;
if (response != null) emit(Integer.parseInt(response));
"""
}
}
}
次に、http.response
ランタイムフィールドを使用して特定のHTTPレスポンスを取得するクエリを実行できます:
Python
resp = client.search(
index="my-index",
query={
"match": {
"http.response": "304"
}
},
fields=[
"http.response"
],
)
print(resp)
Ruby
response = client.search(
index: 'my-index',
body: {
query: {
match: {
'http.response' => '304'
}
},
fields: [
'http.response'
]
}
)
puts response
Js
const response = await client.search({
index: "my-index",
query: {
match: {
"http.response": "304",
},
},
fields: ["http.response"],
});
console.log(response);
コンソール
GET my-index/_search
{
"query": {
"match": {
"http.response": "304"
}
},
"fields" : ["http.response"]
}
レスポンスには、HTTPレスポンスが304
である単一のドキュメントが含まれています:
コンソール-結果
{
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index",
"_id" : "Sq-ex3gBA_A0V6dYGLQ7",
"_score" : 1.0,
"_source" : {
"timestamp" : "2020-04-30T14:31:22-05:00",
"message" : "247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"
},
"fields" : {
"http.response" : [
304
]
}
}
]
}
}
区切り文字でフィールド内の値を分割する(Dissect)
前の例のようにフィールドの一部を抽出したいが、特定の値で分割したいとします。dissectパターンを使用して、必要な情報のみを抽出し、そのデータを特定の形式で返すことができます。
たとえば、Elasticsearchからのガーベジコレクション(gc)ログデータがこの形式であるとします:
Txt
[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K
#### Python
``````python
resp = client.bulk(
index="my-index",
refresh=True,
operations=[
{
"index": {}
},
{
"gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K"
},
{
"index": {}
},
{
"gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K"
},
{
"index": {}
},
{
"gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K"
},
{
"index": {}
},
{
"gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K"
},
{
"index": {}
},
{
"gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K"
},
{
"index": {}
},
{
"gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K"
}
],
)
print(resp)
`
Ruby
response = client.bulk(
index: 'my-index',
refresh: true,
body: [
{
index: {}
},
{
gc: '[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K'
},
{
index: {}
},
{
gc: '[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K'
},
{
index: {}
},
{
gc: '[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K'
},
{
index: {}
},
{
gc: '[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K'
},
{
index: {}
},
{
gc: '[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K'
},
{
index: {}
},
{
gc: '[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K'
}
]
)
puts response
Js
const response = await client.bulk({
index: "my-index",
refresh: "true",
operations: [
{
index: {},
},
{
gc: "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K",
},
{
index: {},
},
{
gc: "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K",
},
{
index: {},
},
{
gc: "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K",
},
{
index: {},
},
{
gc: "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K",
},
{
index: {},
},
{
gc: "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K",
},
{
index: {},
},
{
gc: "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K",
},
],
});
console.log(response);
コンソール
POST /my-index/_bulk?refresh
{"index":{}}
{"gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K"}
{"index":{}}
{"gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K"}
{"index":{}}
{"gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K"}
{"index":{}}
{"gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K"}
{"index":{}}
{"gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K"}
{"index":{}}
{"gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K"}
データを再度見ると、タイムスタンプ、興味のない他のデータ、そしてused
、capacity
、committed
データがあります:
Txt
[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K
#### Txt
``````txt
[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}
`
dissectパターンには、変数を使用する代わりにused
、capacity
、committed
の用語を含めることができます。なぜなら、正確にそれらの用語を返したいからです。また、%{usize}
、%{csize}
、%{comsize}
など、返したい値に変数を割り当てます。ログデータの区切り文字はカンマなので、dissectパターンでもその区切り文字を使用する必要があります。
dissectパターンができたので、ランタイムフィールドの一部としてPainlessスクリプトに含めることができます。スクリプトは、gc
フィールドを分割するためにdissectパターンを使用し、emit
メソッドで定義された通りに、正確に必要な情報を返します。dissectはシンプルな構文を使用するため、必要なものを正確に指示するだけで済みます。
次のパターンは、dissectにused
の用語、空白、gc.usize
の値、およびカンマを返すように指示します。このパターンは、取得したい他のデータに対しても繰り返されます。このパターンは本番環境ではあまり役立たないかもしれませんが、データを操作したり実験したりするための柔軟性を提供します。本番環境では、emit(gc.usize)
を使用して、その値を集約したり計算に使用したりすることが望ましいかもしれません。
Painless
emit("used" + ' ' + gc.usize + ', ' + "capacity" + ' ' + gc.csize + ', ' + "committed" + ' ' + gc.comsize)
すべてをまとめると、検索リクエストでgc_size
という名前のランタイムフィールドを作成できます。fields
オプションを使用して、gc_size
ランタイムフィールドのすべての値を取得できます。このクエリには、データをグループ化するためのバケット集約も含まれています。
Python
resp = client.search(
index="my-index",
runtime_mappings={
"gc_size": {
"type": "keyword",
"script": "\n Map gc=dissect('[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}').extract(doc[\"gc.keyword\"].value);\n if (gc != null) emit(\"used\" + ' ' + gc.usize + ', ' + \"capacity\" + ' ' + gc.csize + ', ' + \"committed\" + ' ' + gc.comsize);\n "
}
},
size=1,
aggs={
"sizes": {
"terms": {
"field": "gc_size",
"size": 10
}
}
},
fields=[
"gc_size"
],
)
print(resp)
Js
const response = await client.search({
index: "my-index",
runtime_mappings: {
gc_size: {
type: "keyword",
script:
"\n Map gc=dissect('[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}').extract(doc[\"gc.keyword\"].value);\n if (gc != null) emit(\"used\" + ' ' + gc.usize + ', ' + \"capacity\" + ' ' + gc.csize + ', ' + \"committed\" + ' ' + gc.comsize);\n ",
},
},
size: 1,
aggs: {
sizes: {
terms: {
field: "gc_size",
size: 10,
},
},
},
fields: ["gc_size"],
});
console.log(response);
コンソール
GET my-index/_search
{
"runtime_mappings": {
"gc_size": {
"type": "keyword",
"script": """
Map gc=dissect('[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}').extract(doc["gc.keyword"].value);
if (gc != null) emit("used" + ' ' + gc.usize + ', ' + "capacity" + ' ' + gc.csize + ', ' + "committed" + ' ' + gc.comsize);
"""
}
},
"size": 1,
"aggs": {
"sizes": {
"terms": {
"field": "gc_size",
"size": 10
}
}
},
"fields" : ["gc_size"]
}
レスポンスには、dissectパターンで定義した通りにフォーマットされたgc_size
フィールドのデータが含まれています!
コンソール-結果
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 6,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index",
"_id" : "GXx3H3kBKGE42WRNlddJ",
"_score" : 1.0,
"_source" : {
"gc" : "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K"
},
"fields" : {
"gc_size" : [
"used 266K, capacity 384K, committed 384K"
]
}
}
]
},
"aggregations" : {
"sizes" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "used 107719K, capacity 111775K, committed 112724K",
"doc_count" : 1
},
{
"key" : "used 115409K, capacity 119541K, committed 120248K",
"doc_count" : 1
},
{
"key" : "used 14503K, capacity 15894K, committed 15948K",
"doc_count" : 1
},
{
"key" : "used 15255K, capacity 16726K, committed 16844K",
"doc_count" : 1
},
{
"key" : "used 266K, capacity 367K, committed 384K",
"doc_count" : 1
},
{
"key" : "used 266K, capacity 384K, committed 384K",
"doc_count" : 1
}
]
}
}
}