Aggregation の指定方法とレスポンスフォーマットについて


(Hidekazu Tanaka) #1

初めまして。

Aggregation の指定方法とレスポンスフォーマットについて質問をさせて下さい。

経緯

下記のようなインデックスがあります。

curl -XGET localhost:9200/reviews/_mapping?pretty
{
  "reviews" : {
    "mappings" : {
      "review" : {
        "properties" : {
          "item_code" : {
            "type" : "string"
          },
          "comment" : {
            "type" : "string",
            "analyzer" : "text_cjk"
          },
          "rate" : {
            "type" : "integer"
          }
        }
      }
    }
  }
}

rate フィールドは 1 から 5 の値が登録されるようにアプリケーション側で制御しています。この rate フィールドについて平均値と値別の件数を集計するために Global Aggregation を使うことにしました。

curl -XGET localhost:9200/reviews/_search?pretty=true -d '{
  "aggregations": {
    "rate": {
      "global" : {},
      "aggregations": {
        "average": { "avg": { "field": "rate" } },
        "terms": { "terms": { "field": "rate" } }
       }
    }
  }
}'

item_code フィールドや comment フィールドを検索条件に指定したところ、Aggregation の結果は検索条件を無視したものでした。

curl -XGET localhost:9200/reviews/_search -d '{
  "query": {
    "filtered": {
      "query": {
        "match": { "comment": "elasticsearch" }
      },
      "filter": {
        "term": { "item_code": "item001" }
      }
    }
  },
  "aggregations": {
    "rate": {
      "global" : {},
      "aggregations": {
        "average": { "avg": { "field": "rate" } },
        "terms": { "terms": { "field": "rate" } }
       }
    }
  }
}'

そのため、ドキュメントを読み直したところ Global Aggregation は検索条件を無視するものであると理解し、検索条件で絞り込んだ結果から rate フィールドについて平均値と値別の件数を集計することも要件に含まれているため、Global Aggregation は使えないことが分かりました。

やりたいこと

  • rate フィールドについて平均値と値別の件数を集計
    • item_code フィールドや comment フィールドを検索条件に指定した場合は、検索条件で絞り込んだ結果から集計
  • Global Aggregation のような条件指定、レスポンスフォーマットにしたい
    {
      "aggregations" : {
        "rate" : {
          "doc_count" : 4,
          "average" : {
            "value" : 2.75
          },
          "terms" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [ {
              "key" : 1,
              "doc_count" : 2
            }, {
              "key" : 4,
              "doc_count" : 1
            }, {
              "key" : 5,
              "doc_count" : 1
            } ]
          }
        }
      }
    }
    

Global Aggregation を使わずに下記のゆうに指定することをできないのでしょうか?

curl -XGET localhost:9200/reviews/_search -d '{
  "query": {
    "filtered": {
      "query": {
        "match": { "comment": "elasticsearch" }
      },
      "filter": {
        "term": { "item_code": "item001" }
      }
    }
  },
  "aggregations": {
    "rate": {
      "aggregations": {
        "average": { "avg": { "field": "rate" } },
        "terms": { "terms": { "field": "rate" } }
       }
    }
  }
}'

環境

  • Amazon Elasticsearch Service を使う想定でいるため、Elasticsearch 1.5.2

(Jun Ohtani) #2

例えば、こんな感じに、複数階層や、同一階層に対して、複数のaggsが適用可能です。

https://www.elastic.co/guide/en/elasticsearch/guide/current/_one_final_modification.html

で、Aggsの構造の書式はこのような形になります。もう一度構造を比較して、エラーを見た方がいいんじゃないですか?

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html#_structuring_aggregations


(Hidekazu Tanaka) #3

回答ありがとうございます。

教えて頂いたドキュメントを参考にして、下記のように実装することにしました。

curl -XGET localhost:9200/reviews/_search -d '{
  "query": {
    "filtered": {
      "query": {
        "match": { "comment": "elasticsearch" }
      },
      "filter": {
        "term": { "item_code": "item001" }
      }
    }
  },
  "aggregations": {
    "rate_average": { "avg": { "field": "rate" } },
    "rate_terms": { "terms": { "field": "rate" } }
  }
}'

(system) #4