具有范围查询的弹性搜索聚合

Elastic search aggregation with range query

我正在努力构建满足条件 >= avg 的 ES 查询。

这是一个例子:

GET /_search
{
    "size" : 0,
    "query" : {
        "filtered": {
            "filter": {
                "range": {
                    "price": {
                        "gte": {
                          "aggs" : {
                            "single_avg_price": {
                                "avg" :{ 
                                  "field" : "price" 
                                }
                              }
                            }
                          }
                }
            }
        }
    }
    }
}

我收到以下错误

"type": "query_parsing_exception",
"reason": "[range] query does not support [aggs]",

我想知道我们如何在 Elastic 查询中使用带范围查询的聚合值

您不能在查询中嵌入聚合。您需要先发送一个聚合查询以找出平均值,然后使用获得的平均值发送第二个范围查询。

查询 1:

POST /_search
{
  "size": 0,
  "aggs": {
    "single_avg_price": {
      "avg": {
        "field": "price"
      }
    }
  }
}

然后你得到平均价格,假设它是 12.3 并在你的第二个查询中使用它,如下所示:

查询 2:

POST /_search
{
  "size": 10,
  "query": {
    "filtered": {
      "filter": {
        "range": {
          "price": {
            "gte": 12.3
          }
        }
      }
    }
  }
}

在我尝试使用不同的 ES 聚合(例如 bucket selector 之后,我发现可以使用 python.

来完成

这是我为解决此问题而创建的 python 代码。 请注意: URL , USER_NAME , PASSWORD 需要在 运行 之前填写

#! /usr/bin/python
import sys,json,requests
from requests.auth import HTTPBasicAuth

# static variables
URL=''
USER_NAME=''
PASSWORD=''

# returns avg value 
def getAvg():
    query = json.dumps({
        "aggs": {
            "single_avg_price": {
              "avg": {
                "field": "price"
              }
            }
         }
    })
    response = requests.get(URL,auth=HTTPBasicAuth(USER_NAME,PASSWORD), data=query)
    results = json.loads(response.text)
    return results['aggregations']['single_avg_price']['value']

#returns rows that are greater than avg value 
def rows_greater_than_avg(avg_value):
    query = json.dumps({
     "query" : {
        "range": {
            "price": {
                "gte":avg_value
              }
         }
      }
    })
    response = requests.get(URL,auth=HTTPBasicAuth(USER_NAME,PASSWORD), data=query)
    results = json.loads(response.text)
    return results

# main method
def main():
   avg_value = getAvg()
   print( rows_greater_than_avg(avg_value))

main()