Elasticsearch Aggregation(集計、分類)

Aggregation(集計、分類)

Elasticsearch では次の Aggregation クエリを実行できる。

まず Aggregation クエリを実行するために、demo_agg インデックスを作成する。

demo_agg インデックス作成

POST /_bulk
{ "index" : { "_index" : "demo_agg" , "_id" : "1" }}
{ "text" : "This is Elasticsearch test." , "type" : 1 }
{ "index" : { "_index" : "demo_agg" , "_id" : "2" }}
{ "text" : "Elasticsearch is God." , "type" : 2 }
{ "index" : { "_index" : "demo_agg" , "_id" : "3" }}
{ "text" : "This is a pen." , "type" : 3 }
{ "index" : { "_index" : "demo_agg" , "_id" : "4" }}
{ "text" : "I have a pen." , "type" : 2 }

集計(Metrics)

demo_agg インデックスに対して集計を行う。まず、avg クエリを使って値の平均を求める。

avg クエリ

GET demo_agg/_search
{
  "size": 0,
  "aggs": {
    "hoge_name": {
      "avg": {
        "field":"type"
      }
    }
  }
}

avg クエリ結果

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "hoge_name" : {
      "value" : 2.0
    }
  }
}

value2.0 である。ここで平均を求めた type の値は [1,2,3,2] なので、この平均は 2 となり正しい結果であることがわかる。

また、"size": 0_search API の検索結果を 0 件表示する、つまり表示しないことを意味する。この値を増やすと、平均を求めるために使用した検索結果を確認できる。

その他にも、以下の集計を行うことができる。

  • sum: 合計値を取得する。
  • max: 最大値を取得する。
  • min: 最小値を取得する。
  • stats: 上記すべての値を取得する。
  • cardinary: 値の種類を取得する。たとえば [1,2,3,2] の場合は、1、2、3 の 3 種類となる。

分類(Buckets)

以下のように指定した条件ごとに Buckets を作成し、該当するドキュメントを Buckets に入れることができる。

範囲(range)で分類

Buckets 作成

GET demo_agg/_search
{
  "size": 0,
  "aggs": {
    "bucket_name": {
      "range": {
        "field":"type",
        "ranges": [
          {
            "from": 0, 
            "to":2
          },
          {
            "from": 2
          }
        ]
      }
    }
  }
}

Buckets 作成結果

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "bucket_name" : {
      "buckets" : [
        {
          "key" : "0.0-2.0",
          "from" : 0.0,
          "to" : 2.0,
          "doc_count" : 1
        },
        {
          "key" : "2.0-*",
          "from" : 2.0,
          "doc_count" : 3
        }
      ]
    }
  }
}

実行結果から次のことを確認できる。

  • "type" フィールドの値が 0 以上 2 未満の Bucket には、1 つのドキュメントが含まれる。(type=[1])
  • "type" フィールドの値が 2 以上の Bucket には、3 つのドキュメントが含まれる。(type=[2,3,2])

同じ間隔(histogram)で分類

このほかにも、histogram クエリを使って値を同じ間隔で分類できる。

histogram クエリ

GET demo_agg/_search
{
  "size" : 0 ,
   "aggs" : {
     "bucket_name" : {
       "histogram" : {
         "field" : "type" ,
         "interval" : 1
      }
    }
  }
}

histogram クエリ実行結果

{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "bucket_name" : {
      "buckets" : [
        {
          "key" : 1.0,
          "doc_count" : 1
        },
        {
          "key" : 2.0,
          "doc_count" : 2
        },
        {
          "key" : 3.0,
          "doc_count" : 1
        }
      ]
    }
  }
}

上記のように、入力した間隔値である 1 ごとにドキュメントがそれぞれ Buckets に分類されたことがわかる。