考虑以下 Elasticsearch (v5.4) 对象(“奖励”文档类型):
{
"name": "Gold 1000",
"date": "2017-06-01T16:43:00.000+00:00",
"recipient": {
"name": "James Conroy",
"date_of_birth": "1991-05-30"
}
}
award.date
两者的映射类型award.recipient.date_of_birth
都是“日期”。
我想执行范围聚合以获取该奖项获得者的年龄范围列表(“18 岁以下”、“18-24 岁”、“24-30 岁”、“30 岁以上”),在他们的时间奖。我尝试了以下聚合查询:
{
"size": 0,
"query": {"match_all": {}},
"aggs": {
"recipients": {
"nested": {
"path": "recipient"
},
"aggs": {
"age_ranges": {
"range": {
"script": {
"inline": "doc['date'].date - doc['recipient.date_of_birth'].date"
},
"keyed": true,
"ranges": [{
"key": "Under 18",
"from": 0,
"to": 18
}, {
"key": "18-24",
"from": 18,
"to": 24
}, {
"key": "24-30",
"from": 24,
"to": 30
}, {
"key": "30+",
"from": 30,
"to": 100
}]
}
}
}
}
}
}
问题 1
但是由于script
部分中的日期比较,我收到以下错误:
Cannot apply [-] operation to types [org.joda.time.DateTime] and [org.joda.time.MutableDateTime].
DateTime
对象即award.date
场,对象MutableDateTime
即award.recipient.date_of_birth
场。我试过做类似的事情(尽管 Joda 文档声称这个方法是从父类继承的,doc['recipient.date_of_birth'].date.toDateTime()
但它不起作用)。MutableDateTime
我也尝试过进一步做这样的事情:
"script": "ChronoUnit.YEARS.between(doc['date'].date, doc['recipient.date_of_birth'].date)"
可悲的是,这也行不通:(
问题 2
我注意到如果我这样做:
"aggs": {
"recipients": {
"nested": {
"path": "recipient"
},
"aggs": {
"award_years": {
"terms": {
"script": {
"inline": "doc['date'].date.year"
}
}
}
}
}
}
我得到1970
的doc_count
结果恰好等于 ES 中的文档总数。这使我相信访问嵌套对象之外的属性根本不起作用,并给了我一些默认值,例如纪元日期时间。如果我做相反的事情(聚合出生日期而不嵌套),我会得到所有出生日期完全相同的东西(1970,纪元日期时间)。那么如何比较这两个日期呢?
我在这里绞尽脑汁,我觉得有一些聪明的解决方案超出了我目前在 Elasticsearch 方面的专业知识。帮助!
如果你想为此建立一个快速的环境来帮助我,这里有一些 curl 的好处:
curl -XDELETE http://localhost:9200/joelinux
curl -XPUT http://localhost:9200/joelinux -d "{\"mappings\": {\"award\": {\"properties\": {\"name\": {\"type\": \"string\"}, \"date\": {\"type\": \"date\", \"format\": \"yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ\"}, \"recipient\": {\"type\": \"nested\", \"properties\": {\"name\": {\"type\": \"string\"}, \"date_of_birth\": {\"type\": \"date\", \"format\": \"yyyy-MM-dd\"}}}}}}}"
curl -XPUT http://localhost:9200/joelinux/award/1 -d '{"name": "Gold 1000", "date": "2016-06-01T16:43:00.000000+00:00", "recipient": {"name": "James Conroy", "date_of_birth": "1991-05-30"}}'
curl -XPUT http://localhost:9200/joelinux/award/2 -d '{"name": "Gold 1000", "date": "2017-02-28T13:36:00.000000+00:00", "recipient": {"name": "Martin McNealy", "date_of_birth": "1983-01-20"}}'
这应该会给你一个“joelinux”索引,其中包含两个“获奖”文档来测试这一点(“James Conroy”和“Martin McNealy”)。提前致谢!