ElasticSearch

【読書】AngularJS アプリケーションプログラミング - むだブログ

は、ゆっくり(怠けながら)読書中 前回読んだ本を

高速スケーラブル検索エンジン ElasticSearch Server (アスキー書籍)

高速スケーラブル検索エンジン ElasticSearch Server (アスキー書籍)

バージョンの関係で記載がありませんが Aggregations の機能について

Aggregations | Elasticsearch Reference [2.4] | Elastic

ファセットに代わる、新しい集計の機能です。 仕事でお試ししたかったので、検証してみる

前提 日付フィールド:created_at

マルチフィールド:keyword

スキーマとして定義されている。

の前に、日付で絞り込む

curl -XGET 192.168.33.10:9200/sns/message/_search?pretty -d '
{
  "query":{
    "range":{
       "created_at":{
         "gte":"2016/09/13 00:00",
         "lte":"2016/09/13 23:59",
         "format" : "yyyy/MM/dd HH:mm"
       }
     }
  }
}'

結果

{
  "took" : 22,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "hits" : {
    "total" : 99,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "sns",
      "_type" : "message",
      "_id" : "3",
      "_score" : 1.0,
      "_source" : {
省略
"created_at" : "Tue Sep 13 08:25:19 +0000 2016",
省略

で、アグリゲーションする。

日別集計

"aggs"

は"aggregations"の略どちらでも

"by_hour"

は、エイリアス SQLでいうASみたいなもの

"date_histogram"

は、アグリゲーションクエリの種類の一つ 日付範囲ごとの集約してくれます。 1日分を1時間別に集計してるという意味となります。 フォーマットはqueryにも言えますが 書式を統一して検索しています。アグリゲーションは出力も

"time_zone"

大事です。前提で忘れましたがcreated_atはUTCで保存されているので JSTに変換してあげます。

curl -XGET 192.168.33.10:9200/sns/message/_search?pretty -d '
{
  "query":{
    "range":{
       "created_at":{
         "gte":"2016/09/15 00:00",
         "lte":"2016/09/15 23:59",
         "format" : "yyyy/MM/dd HH:mm",
         "time_zone" : "+09:00"
       }
     }
  },
  "aggs" : {
    "by_hour" : {
      "date_histogram" : {
        "field" : "created_at",
        "interval" : "1h",
        "format" : "yyyy/MM/dd HH:00",
         "time_zone" : "+09:00"
      }
    }
  }
}'

結果 できた!

省略
  "aggregations" : {
    "by_hour" : {
      "buckets" : [ {
        "key_as_string" : "2016/09/15 13:00",
        "key" : 1473912000000,
        "doc_count" : 201
      }, {
        "key_as_string" : "2016/09/15 14:00",
        "key" : 1473915600000,
        "doc_count" : 201
      }, {
        "key_as_string" : "2016/09/15 15:00",
        "key" : 1473919200000,
        "doc_count" : 201
      } ]
    }
  }
}

日別に集計したい場合はこんな感じ

  "aggs" : {
    "by_day" : {
       "date_histogram" : {
         "field" : "created_at",
         "interval" : "day",
         "format" : "yyyy-MM-dd"
       }
    }
  }

キーワードで集計

キーワードカラムには、配列で複数の単語が保存されいる。 それらを集計する

"terms"

は、値の種類別に集計 集計結果の件数で並び替え 100が上限(SQLのLIMIT)

curl -XGET 192.168.33.10:9200/sns/message/_search?pretty -d '
{
  "query":{
    "range":{
       "created_at":{
         "gte":"2016/09/13",
         "lte":"2016/09/20",
         "format" : "yyyy/MM/dd"
       }
     }
  },
  "aggs" : {
    "keyword_all" : { "value_count" : { "field" : "keyword" } },
    "keyword" : {
      "terms" : {
        "field" : "keyword",
        "order" : { "_count" : "desc" },
        "size" : 100
      }
    }
  }
}'

結果

省略
  "aggregations" : {
    "keyword_all" : {
      "value" : 3212
    },
    "keyword" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [ {
        "key" : "XXX",
        "doc_count" : 803
      }, {
        "key" : "XXXX",
        "doc_count" : 704
      }, {
        "key" : "XXX",
        "doc_count" : 702
      }, {
        "key" : "XXXX",
        "doc_count" : 402
      }, {
        "key" : "XXXX",
        "doc_count" : 401
      }, {
        "key" : "XX",
        "doc_count" : 101
      }, {
        "key" : "XXXXX",
        "doc_count" : 99
      } ]
    }
  }
}

キーワードと同じようなフィールド、URLも加えちゃう

curl -XGET 192.168.33.10:9200/sns/message/_search?pretty -d '
{
  "query":{
    "range":{
       "created_at":{
         "gte":"2016/09/13",
         "lte":"2016/09/20",
         "format" : "yyyy/MM/dd"
       }
     }
  },
  "aggs" : {
    "keyword_all" : { "value_count" : { "field" : "keyword" } },
    "keyword" : {
      "terms" : {
        "field" : "keyword",
        "order" : { "_count" : "desc" },
        "size" : 100
      }
    },
    "url_all" : { "value_count" : { "field" : "url" } },
    "url" : {
      "terms" : {
        "field" : "url",
        "order" : { "_count" : "desc" },
        "size" : 100
      }
    }
  }
}'

結果

  "aggregations" : {
    "url_all" : {
      "value" : 615
    },
    "keyword_all" : {
      "value" : 3212
    },
    "keyword" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [ {
        "key" : "XXXX",
        "doc_count" : 803
      }, {
        "key" : "ドXXXX販売",
        "doc_count" : 704
      }, {
        "key" : "XXX",
        "doc_count" : 702
      }, {
        "key" : "XXXX",
        "doc_count" : 402
      }, {
        "key" : "XXXX",
        "doc_count" : 401
      }, {
        "key" : "XXX",
        "doc_count" : 101
      }, {
        "key" : "XXXXX",
        "doc_count" : 99
      } ]
    },
    "url" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 21,
      "buckets" : [ {
        "key" : "http://www.altus5.co.jp/",
        "doc_count" : 99
      }, {
        "key" : "tp://www.xxxxxx.com/",
        "doc_count" : 99
      }, {
        "key" : "tp://www.xxxxx.co.jp/",
        "doc_count" : 99
      }, {
        "key" : "tps://www.xxxxx.co.jp/",
        "doc_count" : 99
      }, {
        "key" : "tps://twitter.com/xxxxxx/status/776201452247146496",
        "doc_count" : 35
      }, {
長いので省略

1回ででけた! terms、histogram だけですが、こんな感じです。

と結局、読んだこととは関係ないお話し