使用连接参数的Elasticsearch桶聚合

时间:2016-12-28 06:54:01

标签: json elasticsearch

我使用Elasticsearch API和文档架构如下

{
  name: "",
  born_year: "",
  born_month: "",
  born_day: "",
  book_type: "",
  price: <some number>,
  country: ""
}

现在我需要的是获得1995年之前出生的每个名字的文件数(born_year + born_month + born_day&lt;&#34; 20051220&#34;)。我怎样才能实现?

我试过了:

{
  "query": {
    "query_string": {
      "query": "country:\"SL\""
    }
  },
  "size": 0,
  "aggs": {
    "total": {
      "terms": {
        "field": "name"
      }
    }
  }
}

但我不知道如何为生日添加过滤器。

1 个答案:

答案 0 :(得分:1)

如@val所述,您需要添加一个真实的日期字段,您可以通过在创建时连接这三个字段来轻松添加。 但是如何根据日期范围进行过滤,有两种方法,它们都会返回不同的结果集 现在可以选择过滤级别。

您提到在国家/地区字段上查询。但是您没有提到要在日期范围内过滤的级别。我会给你两个案件的查询。

映射 - 假设您创建了一个日期字段。

{
    name:"",
    born_year:"",
    born_month:"",
    born_day:"",
    book_type:"",
    price:<some number>,
    country:"",
    date : ""
  }

案例 - 1)仅过滤名称聚合的日期范围,此处文件计数不受日期范围过滤器的影响

{
    "query": {
        "query_string": {
            "query": "country:\"SL\""
        }
    },
    "aggs": {
        "total": {
            "filter": {
                "range": {
                    "date": {
                        "gte": "your_date_mx",
                        "lte": "your_date_min"
                    }
                }
            },
            "aggs": {
                "NAME": {
                    "terms": {
                        "field": "name",
                        "size": 10
                    }
                }
            }
        }
    }
}

案例2)在这种情况下,当我们在查询级别添加日期范围过滤器时,您的文档计数和聚合都将被过滤日期范围。

{
    "query": {
        "query_string": {
            "query": "country:\"SL\""
        },
        "bool": {
            "must": [
                {
                    "range": {
                        "date": {
                            "gte": "your_date_mx",
                            "lte": "your_date_mic"
                        }
                    }
                }
            ]
        }
    },
    "aggs": {
        "toal": {
            "terms": {
                "field": "name",
                "size": 10
            }
        }
    }
}

因此,向聚合添加过滤器将仅影响aggs计数。 编辑 - Approach1)使用groovy脚本尝试连接字符串并将其解析为整数,然后与输入日期进行比较。

{
    "query": {
        "bool": {
            "must": [
                {}
            ],
            "filter": {
                "script": {
                    "script": {
                        "inline": "(doc['year'].value  +  doc['month'].value + doc['date'].value).toInteger() > 19910701",
                        "params": {
                            "param1": 19911122
                        }
                    }
                }
            }
        }
    }
}

确保将索引日期(或月份)索引为单个数字(如6)作为06

2)方法2 - 将字符串解析为确切的日期(首选)

{
    "query": {
        "bool": {
            "must": [
                {}
            ],
            "filter": {
                "script": {
                    "script": {
                        "inline": "Date.parse('dd-MM-yyyy',doc['date'].value  +'-'+  doc['month'].value +'-'+ doc['year'].value).format('dd-MM-yyyy') > param1",
                        "params": {
                            "param1": "04-05-1991"
                        }
                    }
                }
            }
        }
    }
}

第二种方法是更好的方法,因为您不必担心为每个字段(日期,月份,日期)维护字符串,以便稍后解析为适当的int进行比较。