0

I would like to do something like the following using painless:

select day,sum(price)/sum(quantity) as ratio
from data 
group by day

Is it possible?

I want to do this in order to visualize the ratio field in kibana, since kibana itself doesn't have the ability to divide aggregated values, but I would gladly listen to alternative solutions beyond scripted fields.

Elisavet
  • 41
  • 1
  • 6

2 Answers2

1

Yes, it's possible, you can achieve this with the bucket_script pipeline aggregation:

{
  "aggs": {
    "days": {
      "date_histogram": {
        "field": "dateField",
        "interval": "day"
      },
      "aggs": {
        "price": {
          "sum": {
            "field": "price"
          }
        },
        "quantity": {
          "sum": {
            "field": "quantity"
          }
        },
        "ratio": {
          "bucket_script": {
            "buckets_path": {
              "sumPrice": "price",
              "sumQuantity": "quantity"
            },
            "script": "params.sumPrice / params.sumQuantity"
          }
        }
      }
    }
  }
}

UPDATE:

You can use the above query through the Transform API which will create an aggregated index out of the source index.

For instance, I've indexed a few documents in a test index and then we can dry-run the above aggregation query in order to see how the target aggregated index would look like:

POST _transform/_preview
{
  "source": {
    "index": "test2",
    "query": {
      "match_all": {}
    }
  },
  "dest": {
    "index": "transtest"
  },
  "pivot": {
    "group_by": {
      "days": {
        "date_histogram": {
          "field": "@timestamp",
          "calendar_interval": "day"
        }
      }
    },
    "aggregations": {
      "price": {
        "sum": {
          "field": "price"
        }
      },
      "quantity": {
        "sum": {
          "field": "quantity"
        }
      },
      "ratio": {
        "bucket_script": {
          "buckets_path": {
            "sumPrice": "price",
            "sumQuantity": "quantity"
          },
          "script": "params.sumPrice / params.sumQuantity"
        }
      }
    }
  }
}

The response looks like this:

{
  "preview" : [
    {
      "quantity" : 12.0,
      "price" : 1000.0,
      "days" : 1580515200000,
      "ratio" : 83.33333333333333
    }
  ],
  "mappings" : {
    "properties" : {
      "quantity" : {
        "type" : "double"
      },
      "price" : {
        "type" : "double"
      },
      "days" : {
        "type" : "date"
      }
    }
  }
}

What you see in the preview array are documents that are going to be indexed in the transtest target index, that you can then visualize in Kibana as any other index.

So what a transform actually does is run the aggregation query I gave you above and it will then store each bucket into another index that can be used.

Val
  • 207,596
  • 13
  • 358
  • 360
  • Thank you for your answer! I don't understand how the ratio that is created in the json, will be visualised in kibana... Should I create a new index with the ratios? – Elisavet May 20 '20 at 09:20
  • I've updated my answer with a more illustrative example – Val May 20 '20 at 09:56
  • Thank you so much!!! I have been looking for this for days! :) – Elisavet May 20 '20 at 10:38
1

I found a solution to get the ratio of sums with TSVB visualization in kibana. You may see the image here to see an example.

At first, you have to create two sum aggregations, one that sums price and another that sums quantity. Then, you choose the 'Bucket Script' aggregation to divide the aforementioned sums, with the use of painless script.

The only drawback that I found is that you can not aggregate on multiple columns.

Elisavet
  • 41
  • 1
  • 6