ElasticSearch:在包含文档的日期范围中查找不同日期的最佳方法是什么?

标签 elasticsearch elasticsearch-aggregation elasticsearch-java-api

假设我有包含两个对过滤文档很重要的字段的月度索引:client_id 和 date_time,以及我对此查询不感兴趣的其他几个数据字段。

如果我想查找索引中存在的所有不同的 date_time 一段时间(即,如果是订单,则将是该期间注册的订单的所有日期,如果是租车,则将是所有天有租车等)

假设我想查找 ES 中存在的 2018-10-01 和 2018-10-03 的不同 dateTime(此示例的简称)

我可以先添加一个 bool 查询来将此数据限制在日期范围内:

{
  "size" : 0,
  "timeout" : 1500,
  "query" : {
    "bool" : {
      "must" : {
        "range" : {
          "date_time" : {
            "from" : "2018-10-01T00:00:00.000Z",
            "to" : "2018-10-03T23:59:59.999Z",
            "include_lower" : true,
            "include_upper" : true
          }
        }
      }
    }
  }
} 

我虽然在代码上进行日期范围聚合和按文档计数过滤:
{
  "size" : 0,
  "timeout" : 1500,
  "query" : {
    "bool" : {
      "must" : {
        "range" : {
          "date_time" : {
            "from" : "2018-09-19T00:00:00.000Z",
            "to" : "2018-10-19T23:59:59.999Z",
            "include_lower" : true,
            "include_upper" : true
          }
        }
      }
    }
  },
  "aggregations" : {
    "date_range_agg" : {
      "date_range" : {
        "field" : "date_time",
        "ranges" : [ {
          "from" : "2018-09-30T00:00:00.000Z",
          "to" : "2018-10-01T00:00:00.000Z"
        }, {
          "from" : "2018-10-01T00:00:00.000Z",
          "to" : "2018-10-02T00:00:00.000Z"
        }, {
          "from" : "2018-10-02T00:00:00.000Z",
          "to" : "2018-10-03T00:00:00.000Z"
        }, {
          "from" : "2018-10-03T00:00:00.000Z",
          "to" : "2018-10-04T00:00:00.000Z"
        }]
      }
    }
  }
} 

我可以在我的代码中使用 doc_count > 0 过滤来自 date_range_agg 的存储桶,但我仍然不喜欢它。

有没有办法在 date_range 存储桶上应用过滤器以仅带来那些包含超过 0 文档计数的存储桶?

是否有另一种方法可以像 date_time 字段的 agg 一样执行“sql group by”,以在 ES 中为日期范围获取所有不同的组?

简而言之,我只需要获取在给定时间段内实际具有文档的所有不同 date_time 。

我们谈论的是具有 7GB 文档值(value)的索引(每个索引大约 160 万个文档),或者 3.8GB 和 200 万个文档的索引。所以我试图找到最有效的方法来检索它。

ADDED- 注意:实际上,这个查询是用来验证我们所有索引中是否存在每天的数据,其中一些非常小,有些像这样巨大,并且可以超时,它们都有一个 dateTime 字段,
并且它们都具有对应于第0天的毫秒的时间戳和相同的时区,因此它们不会以毫秒或任何时间变化。

最佳答案

我认为下面的查询是您正在寻找的。我已经实现了range partaggregation使用 date histogram并使用了bucket selector aggregation这样只有那些具有 document count>0 的范围将被退回。

{  
   "size":0,
   "timeout":"1500ms",
   "query":{  
      "bool":{  
         "must":{  
            "range":{  
               "date_time":{  
                  "from":"2018-09-19T00:00:00.000Z",
                  "to":"2018-10-19T23:59:59.999Z",
                  "include_lower":true,
                  "include_upper":true
               }
            }
         }
      }
   },
   "aggregations":{  
      "date_range_agg":{  
         "date_histogram":{  
            "field":"date_time",
            "format":"MM-dd-yyyy",
            "interval":"week"
         },
         "aggs":{  
            "count_bucket_selector":{  
               "bucket_selector":{  
                  "buckets_path":{  
                     "count":"_count"
                  },
                  "script":{  
                     "lang":"expression",
                     "inline":"count>0"
                  }
               }
            }
         }
      }
   }
}

因此,上面的查询将返回周列表以及该周的文档计数。如果哪一周没有任何文档,则不会显示该周。

您可以使用 monthday而不是 week在上面的查询中,如果您想分别查看每月或每天的详细信息。

表现

而不是指定 timeout , 我建议你玩一下 profiling功能可让您了解完成聚合查询需要多长时间。

以下是如何将分析参数添加到查询中。
{
    "profile": true,
    "size": 0,
    "query": {}
}

您可以使用 profile 查看单独的 JSON 对象在您添加此内容时的回复中。作为响应,您将能够查看每个分片的查询性能详细信息。特别检查aggregation部分,您可以进一步引用此link了解更多关于时间分割的信息。

希望能帮助到你!

关于ElasticSearch:在包含文档的日期范围中查找不同日期的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52899742/

相关文章:

elasticsearch - 按文本字段对Elasticsearch聚合桶进行排序

sorting - boost 弹性聚集结果

elasticsearch - Elasticsearch 聚合中的动态时区偏移量?

json - 自动生成文档ID时,以 Elasticsearch 方式更新文档

Elasticsearch 在使用 query_string 时提升一个字段

elasticsearch - 如何检索父/子关系破裂的文档?

java - 如何将 Java 应用程序连接到 Elasticsearch?

elasticsearch - 在 ElasticSearch 中对字符串数组进行排序

java - ElasticSearch 存储桶聚合

java - 应该如何查询它是否有效? ElasticSearch Java API