admin管理员组

文章数量:1186688

I have documents that contain a field named "device" and I wrote this query so far:

GET some_index/_search
{
  "size": 0,
  "aggs": {
    "total": {
      "value_count": {
        "field": "_id"
      }
    },
    "per_device": {
      "terms": {
        "field": "device_type",
        "size": 10
      }
    }
  }
}

I need "per_device / total" ratio for each device_type.

I tried bucket-script inside "per_device" aggregation but I have no access to "total" aggregation from there. also searching through the official documents didn't help.

I have documents that contain a field named "device" and I wrote this query so far:

GET some_index/_search
{
  "size": 0,
  "aggs": {
    "total": {
      "value_count": {
        "field": "_id"
      }
    },
    "per_device": {
      "terms": {
        "field": "device_type",
        "size": 10
      }
    }
  }
}

I need "per_device / total" ratio for each device_type.

I tried bucket-script inside "per_device" aggregation but I have no access to "total" aggregation from there. also searching through the official documents didn't help.

Share Improve this question edited Jan 27 at 7:39 DarkBee 15.7k8 gold badges70 silver badges113 bronze badges asked Jan 27 at 7:38 Mehdi.ValizadeMehdi.Valizade 314 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I am afraid it isn't possible to do it dynamically. However, if you know all the unique values for devices beforehand, you can run multiple bucket script aggregations like this:

GET log/_search
{
    "size": 0,
    "aggs": {
        "filters_agg": {
            "filters": {
                "filters": {
                    "devices_count": {
                        "match_all": {}
                    }
                }
            },
            "aggs": {
                "device_unique_values": {
                    "terms": {
                        "field": "device.keyword"
                    }
                },
                "d1_count_percentage": {
                    "bucket_script": {
                        "buckets_path": {
                            "device_count": "device_unique_values['D1']>_count",
                            "total_count": "_count"
                        },
                        "script": "(params.device_count * 100)/params.total_count"
                    }
                }
            }
        }
    }
}

Please note that I am calculating percentage specifically for D1 device. You can add it for others as well. This is how the query output will look like:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "filters_agg": {
      "buckets": {
        "devices_count": {
          "doc_count": 5,
          "device_unique_values": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "D1",
                "doc_count": 1
              },
              {
                "key": "D2",
                "doc_count": 1
              },
              {
                "key": "D3",
                "doc_count": 1
              },
              {
                "key": "D4",
                "doc_count": 1
              },
              {
                "key": "D5",
                "doc_count": 1
              }
            ]
          },
          "d1_count_percentage": {
            "value": 20
          }
        }
      }
    }
  }
}

Now, to do it for all the devices at once, you can just run a terms query, like this:

POST log/_search
{
  "size": 0,
  "aggs": {
    "devicesDetails": {
      "terms": {
        "field": "device.keyword"
      }
    }
  }
}

The response will be this:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "aggregations": {
    "devicesDetails": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "D1",
          "doc_count": 1
        },
        {
          "key": "D2",
          "doc_count": 1
        },
        {
          "key": "D3",
          "doc_count": 1
        },
        {
          "key": "D4",
          "doc_count": 1
        },
        {
          "key": "D5",
          "doc_count": 1
        }
      ]
    }
  }
}

You can use the hits.total.value field to get total count, and the individual devices count is present in the bucket, and the percentages can be calculated via a script. Make sure that the value of hits.total.relation is eq, otherwise it will be an approximate count.

本文标签: elasticsearchHow to calculate a simple percentageStack Overflow