我们现在做的是医疗的业务,有个需求是这样的,查询出某位医生前七天的坐诊记录,并且,医生的坐诊记录是不连续的,这样就需要写一个dsl语句来实现es库的搜索
首先我使用了es库中的聚合功能,按照日期去聚合,相当于mysql中的group by,查询语句和结果是这样的
{ "query": { "match": { "ysdm": "000485" } }, "aggs": { "jzrq": { "date_histogram": { "field": "jzrq", "format": "yyyy-MM-dd", "interval": "day", "min_doc_count": 1, "order": { "_key": "desc" } } } } }
我们这里指定的医生代码,然后按照就诊日期去分组,这里的出的聚合数据我们是没办法指定size的,所以只能通过日期去限制了,从结果中拿到7天的数据,他这里的聚合实际上是根据query中的条件拿到数据,再执行的聚合
返回结果如下,敏感信息我已经用xx代替:
{ "took": 2, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": xx, "max_score": xx, "hits": [ { "_index": "xx", "_type": "xx", "_id": "xx", "_score": 6.271472, "_source": { "jzid": "xx", "jzrq": "2019-05-14T09:07:29+08:00", "ksdm": "xx", "ksmc": "xx", "ysdm": "xx", "ysxm": "xx", "blh": "xx", "kh": "xx", "brxm": "xx", "diaginfo": "屈光不正;", "zydm": "xx", "zymc": "xx", "vapphisid": "45287777", "vappregid": "xx", "csrq": "xx0", "age": "", "xb": "0", "xb1": "男", "ybh": "", "sfzh": "xx", "contactname": "xx", "contactphone": "x", "contactidcard": "x", "vprovince": "x", "vcity": "朝阳市", "dz": "朝阳县", "vbjhlcode": "" } } ] }, "aggregations": { "jzrq": { "buckets": [ { "key_as_string": "2019-12-26", "key": 1577318400000, "doc_count": 2 }, { "key_as_string": "2019-12-17", "key": 1576540800000, "doc_count": 43 }, { "key_as_string": "2019-12-12", "key": 1576108800000, "doc_count": 1 } ] } } }
可以看到,我们会得到es库中的搜索结果和聚合信息,但是我们只想要聚合信息,不想要搜索结果,这里我们加一个size:0来去掉搜索结果,语句如下
{ "query": { "match": { "ysdm": "000485" } }, "aggs": { "jzrq": { "date_histogram": { "field": "jzrq", "format": "yyyy-MM-dd", "interval": "day", "min_doc_count": 1, "order": { "_key": "desc" } } } }, "size": 0 }
说一下几个参数的作用
aggs:指定这是一个聚合功能
jzrq:这个是聚合函数的名字
date_histogram:按照时间去聚合
field:指定字段,按照哪个字段聚合
format:指定返回的buckets的key_as_string的格式
interval:按照天/月/年去分组
min_doc_count:所允许的buckets中最小的doc_count条数
order:_key 排序方式
这里是文档,点我
这里要强调一点
GET /cars/transactions/_search{ "size" : 0, "aggs": { "sales": { "date_histogram": { "field": "sold", "interval": "month", "format": "yyyy-MM-dd", "min_doc_count" : 0, "extended_bounds" : { "min" : "2014-01-01", "max" : "2014-12-31" } } } }}
文档中说道有一个extened_bounds参数,我试了一下,并没有对日期做限制,比如我限定2019-12-01至2019-12-31,仍然会在聚合结果中显示出其他时间段的数据,其实这里的extened_bounds仅仅是个扩展时间的范围,一切以实际数据为准,官方解释如下
extended_bounds
参数需要一点解释。min_doc_count
参数强制返回空 buckets,但是 Elasticsearch 默认只返回你的数据中最小值和最大值之间的 buckets。因此如果你的数据只落在了 4 月和 7 月之间,那么你只能得到这些月份的 buckets(可能为空也可能不为空)。因此为了得到全年数据,我们需要告诉 Elasticsearch 我们想要全部 buckets, 即便那些 buckets 可能落在最小日期 之前 或 最大日期 之后 。
我的时间字段的类型是date,即
于是我在query中对日期做了限制,就可以
{ "query": { "bool": { "must": { "term": { "ysdm": "000485" } }, "filter": { "range": { "jzrq": { "from": "2019-12-01", "to": "2019-12-05" } } } } }, "size": 0, "aggs": { "jzrq": { "date_histogram": { "field": "jzrq", "format": "yyyy-MM-dd", "interval": "day", "min_doc_count": 1, "order": { "_key": "desc" } } } } }
好了踩坑到此结束,希望对大家有所帮助