我有以下结构的文件(简化):
curl -XPOST "http://localhost:9200/test/aggtest/1" -d "{
\"user_id\": 123,
\"date_created\": \"2015-05-12T10:29:49-04:00\"
}"
curl -XPOST "http://localhost:9200/test/aggtest/2" -d "{
\"user_id\": 123,
\"date_created\": \"2014-05-12T10:29:49-04:00\"
}"
curl -XPOST "http://localhost:9200/test/aggtest/3" -d "{
\"user_id\": 123,
\"date_created\": \"2013-05-12T10:29:49-04:00\"
}"
curl -XPOST "http://localhost:9200/test/aggtest/4" -d "{
\"user_id\": 456,
\"date_created\": \"2015-05-12T10:29:49-04:00\"
}"
curl -XPOST "http://localhost:9200/test/aggtest/5" -d "{
\"user_id\": 456,
\"date_created\": \"2012-05-12T10:29:49-04:00\"
}"
curl -XPOST "http://localhost:9200/test/aggtest/6" -d "{
\"user_id\": 456,
\"date_created\": \"2011-05-12T10:29:49-04:00\"
}"
如何计算在某个日期之前或之后创建的user_ids
的计数?例如。在上述文件中,只有一个独特的user_id
在2012年之后有记录。
在mongodb中,它相当简单。使用聚合框架,我可以转换文档,其中将是一个唯一的用户ID及其最小创建日期。然后只按日期和计数过滤结果。我无法在elasticsearch中编写类似的查询。任何帮助表示赞赏。
在SQL中,此查询应如下所示:
SELECT COUNT(DISTINCT(user_id)) FROM aggtest WHERE date_created >= 2015 AND user_id NOT IN (SELECT user_id FROM aggtest WHERE date_created < 2015)
答案 0 :(得分:1)
通过阅读评论,我认为我理解你所问的是什么,尽管原始问题并不完全清楚。
听起来你想要找到在某个日期之后有user_id
s的唯一creation_date
s,但之前没有。{/ p>
我想不出用你当前的数据结构做到这一点的方法,但如果你愿意使用parent/child relationship重新组织数据,那么设置你想要的查询就相当简单。 / p>
为了测试它,我设置了一个有两种类型的索引,如下所示:
PUT /test_index
{
"mappings": {
"user": {
"_id": {
"path": "user_id"
},
"properties": {
"user_id": {
"type": "integer"
}
}
},
"creation_date": {
"_parent": {
"type": "user"
},
"properties": {
"date_created": {
"type": "date",
"format": "dateOptionalTime"
}
}
}
}
}
然后我使用新架构索引您提供的数据:
POST /test_index/_bulk
{"index":{"_type":"user"}}
{"user_id":123}
{"index":{"_type":"creation_date","_parent":123}}
{"date_created":"2015-05-12T10:29:49-04:00"}
{"index":{"_type":"creation_date","_parent":123}}
{"date_created":"2014-05-12T10:29:49-04:00"}
{"index":{"_type":"creation_date","_parent":123}}
{"date_created":"2013-05-12T10:29:49-04:00"}
{"index":{"_type":"user"}}
{"user_id":456}
{"index":{"_type":"creation_date","_parent":456}}
{"date_created":"2015-05-12T10:29:49-04:00"}
{"index":{"_type":"creation_date","_parent":456}}
{"date_created":"2012-05-12T10:29:49-04:00"}
{"index":{"_type":"creation_date","_parent":456}}
{"date_created":"2011-05-12T10:29:49-04:00"}
现在我可以通过以下查询回复您所问的内容(假设我理解正确)。换句话说,我希望那些至少有一个(孩子)user
大于或等于creation_date
的人过滤(父)"2012-05-12"
文件,但是没有(孩子) )creation_date
小于"2012-05-12"
,然后我想在聚合中显示这些ID(聚合在这里是多余的,但我假设你的真实索引更复杂,所以它可能是有用的是不返回完整的user
文件):
POST /test_index/user/_search?search_type=count
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"has_child": {
"type": "creation_date",
"filter": {
"range": {
"date_created": {
"gte": "2012-05-12"
}
}
}
}
},
{
"not": {
"filter": {
"has_child": {
"type": "creation_date",
"filter": {
"range": {
"date_created": {
"lt": "2012-05-12"
}
}
}
}
}
}
}
]
}
}
}
},
"aggs": {
"distinct_user_ids": {
"terms": {
"field": "user_id"
}
}
}
}
返回:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0,
"hits": []
},
"aggregations": {
"distinct_user_ids": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 123,
"doc_count": 1
}
]
}
}
}
以下是我用来测试它的所有代码:
http://sense.qbox.io/gist/1fbe448a85b9c74cb25cd5245d4e77f1eec46ea7
答案 1 :(得分:0)
使用基数聚合在字段中获取不同的值计数:https://www.elastic.co/guide/en/elasticsearch/guide/current/cardinality.html
将聚合与范围过滤器结合使用,将结果限制为时间范围:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-filter.html
示例:
GET /test/aggtest/_search
{
"size": 0,
"query": {
"filtered" : {
"filter" : {
"range" : {
"date_created" : {
"gte": "2015-09-01"
}
}
}
}
},
"aggs" : {
"distinct_user_ids" : {
"cardinality" : {
"field" : "user_id"
}
}
}
}
您将获得doc_count
聚合的distinct_user_ids
聚合结果。