LoginSignup
6
6

More than 5 years have passed since last update.

[elasticsearch2.0] Pipeline Aggregationを試す -Bucket Script Aggregation

Last updated at Posted at 2015-11-11

テーマ

「期間Aと期間Bで単語の出現頻度の差を算出する」

  • if-idf的なことをやるためのお試しといった感じです
  • 出現頻度:その単語を含む記事数

方針

  1. terms aggregation → 単語毎の出現頻度を数える
  2. filter aggregation → 期間Aと期間Bに分割
  3. bucket script aggregation → 期間Aと期間Bを比較

設定

elasticsearch.yml
script.engine.groovy.inline.aggs: on

query

bucket-script-agg.json
GET _search?search_type=count
{
  "query": {
    "match_all": {}
  },
  "aggs": { // 1.terms aggregation
    "term": {
      "terms": {
        "field": "text",
        "size": 5
      },
      "aggs": { // 2.filter aggregation
        "dateRange1": { // 期間A
          "filter": {
            "range": {
              "datetime": {
                "gte": "2014-04-01T00:00:00+0900",
                "lte": "2014-04-10T23:59:59+0900"
              }
            }
          }
        },
        "dateRange2": { // 期間B
          "filter": {
            "range": {
              "datetime": {
                "gte": "2014-04-11T00:00:00+0900",
                "lte": "2014-04-20T23:59:59+0900"
              }
            }
          }
        },
        "tf-idf": { // 語弊あり
          "bucket_script": { // 3.bucket script aggregation
            "buckets_path": {
              "range1": "dateRange1._count", //doc_countを取り出す
              "range2": "dateRange2._count"
            },
            "script": "range2 - range1" //簡単なscript
          }
        }
      }
    }
  }
}

結果

response.json
{
  "took": 133,
  "timed_out": false,
  "_shards": {
    "total": 7,
    "successful": 7,
    "failed": 0
  },
  "hits": {
    "total": 48762,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "term": {
      "doc_count_error_upper_bound": 6688,
      "sum_other_doc_count": 904138,
      "buckets": [
        {
          "key": "い", // term(analyzerの設定が適当なので変な感じ)
          "doc_count": 23490, // hits全体での件数
          "dateRange2": {
            "doc_count": 7642 // 期間Aでの件数
          },
          "dateRange1": {
            "doc_count": 8270 // 期間Bでの件数
          },
          "if-idf": {
            "value": -628 // 期間B - 期間A の結果
          }
        }
...
      ]
    }
  }
}

まとめと感想

  • かなり柔軟に処理を書けそう
  • scriptで扱うbucketの数が特定できないと使えないような気が
  • bucketからドキュメント件数を取り出すには{backet_path}._countを使う
  • ひとまず思ったとおりのことができた
  • bucketを任意の条件でfilterするaggregationの構想もあるらしいので期待
    • (20151112追記) bucket selector aggregationと言うのがそれらしい
  • Senseが超便利

課題

  • 期間Aと期間Bそれぞれの全ドキュメント数で正規化するような処理を入れたい
  • terms aggregationとfilter aggregationの順序を逆に出来るだろうか

参考

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6