如何查询时间是否介于两个字段值之间



如何搜索介于开始时间和结束时间之间的文档?例如,我只想使用"18:33"或"21:32"这样的时间来查询以下文档。"18:33"将返回以下文档,而"21:32"则不会。我不在乎日期部分,也不在乎秒。

{
"my start time field": "2020-01-23T18:32:21.768Z",
"my end time field": "2020-01-23T20:32:21.768Z"
}

我已经复习了:使用带有date字段的range查询。但我不知道如何只看时间。另外,我想看看一个时间是否在两个字段之间,而不是一个字段是否在两次之间。


本质上是SQL Server的BETWEEN的Elasticsearch等价物。就像这个答案,只是我不想使用当前时间,而是一个变量。

DECLARE @blah datetime2 = GETDATE()
SELECT  *
FROM Table1 T
WHERE CAST(@blah AS TIME) 
BETWEEN cast(T.StartDate as TIME) AND cast(T.EndDate as TIME)

根据OP的建议和他提供的符合stackoverflow定律的链接,我在这里提供第二个解决方案:

解决方案2:将小时-分钟插入单独的字段,格式为hh:mm

注意所使用的格式,上面写着hour_minute。您可以在上述链接下找到可用格式的列表。

基本上,您使用一个单独的字段重新获取文档,该字段将具有hour and minute values并执行range queries以获得您想要的内容。

映射:

PUT my_time_index
{
"mappings": {
"properties": {
"start_time":{
"type": "date",
"format": "hour_minute"
},
"end_time":{
"type": "date",
"format": "hour_minute"
}
}
}
}

示例文档:

POST my_time_index/_doc/1
{
"start_time": "18:32",
"end_time": "20:32"
}

查询请求:

POST my_time_index/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"start_time": {
"gte": "18:00"
}
}
},
{
"range": {
"end_time": {
"lte": "21:00"
}
}
}
]
}
}
}

如果这有帮助,请告诉我!

不要基于此讨论将时间存储在datetime数据类型中。

如果你想过滤一天中的特定时间,你需要将其提取到它自己的字段中。

通过Kibana开发工具->控制台

创建一些模拟数据:

POST between-research/_doc/1
{
"my start hour": 0,
"my end hour": 12
}
POST between-research/_doc/2
{
"my start hour": 13,
"my end hour": 23
}

执行"中间"搜索

POST between-research/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"my start hour": {
"lte": 10
}
}
},
{
"range": {
"my end hour": {
"gte": 10
}
}
}
]
}
}
}

解决方案1:现有日期格式

在不改变和摄入你的小时和分钟的情况下,我提出了以下解决方案,我认为你不会对ES为你提供解决方案的方式感到满意,但它确实有效。

我已经根据您提供的数据创建了一个示例映射、文档、查询和响应。

映射:

PUT my_date_index
{
"mappings": {
"properties": {
"start_time":{
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
},
"end_time":{
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
}
}
}
}

示例文档:

POST my_date_index/_doc/1
{
"start_time": "2020-01-23T18:32:21.768Z",
"end_time": "2020-01-23T20:32:21.768Z"
}
POST my_date_index/_doc/2
{
"start_time": "2020-01-23T19:32:21.768Z",
"end_time": "2020-01-23T20:32:21.768Z"
}
POST my_date_index/_doc/3
{
"start_time": "2020-01-23T21:32:21.768Z",
"end_time": "2020-01-23T22:32:21.768Z"
}

查询请求:

POST my_date_index/_search
{
"query": {
"bool": {
"must": [
{
"script": {
"script": {
"source": """
ZonedDateTime zstart_time = doc['start_time'].value;
int zstart_hour = zstart_time.getHour();
int zstart_minute = zstart_time.getMinute();
int zstart_total_minutes = zstart_hour * 60 + zstart_minute;
ZonedDateTime zend_time = doc['end_time'].value;
int zend_hour = zend_time.getHour();
int zend_minute = zend_time.getMinute();
int zend_total_minutes = zend_hour * 60 + zend_minute;
int my_input_total_minutes = params.my_input_hour * 60 + params.my_input_minute;
if(zstart_total_minutes <= my_input_total_minutes && zend_total_minutes >= my_input_total_minutes){
return true;
}
return false;
""",
"params": {
"my_input_hour": 20,
"my_input_minute": 10
}
}
}
}
]
}
}
}

基本上

  • start_date计算分钟数

  • end_date计算分钟数

  • 从CCD_ 9&params.my_input_minute

  • 使用所有三个值的分钟执行if条件中的逻辑为CCD_ 11,并相应地返回文档。

响应:

{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.0,
"hits" : [
{
"_index" : "my_time_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 2.0,
"_source" : {
"start_time" : "18:32",
"end_time" : "20:32"
}
}
]
}
}

当涉及到解决方案1时,请彻底测试它们的性能问题,因为脚本查询通常会影响性能,但如果您没有选择,它们会派上用场。

如果这有帮助,请告诉我!

最新更新