Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElasticSearch: How to query a date field using an hours-range filter

Currently, I already know how to filter a days range from a (timestamp) date field. That's an easy one:

"range": {
    "date": {
        "gte": "2015-11-01",
        "lte": "2015-11-30"
    }
}

But how to filter dates when you are interested in ranges based on hours like gte:"8:00:00" and lte:"10:00:00"? Is this possible?

My requirement in other words: How to get all the events happening this month (15-11-01/15-11-30) but only between 8:00:00 am and 10:00:00?

like image 283
xtingray Avatar asked Nov 05 '15 01:11

xtingray


People also ask

How does range query work in Elasticsearch?

A query that has a term query that matches 10,000 documents (0.1% of the index) is intersected with ranges that match various numbers of documents. On the X axis is the number of documents that the range matches, and on the Y axis is the time it took to run the query.

What is bool query in Elasticsearch?

Boolean, or a bool query in Elasticsearch, is a type of search that allows you to combine conditions using Boolean conditions. Elasticsearch will search the document in the specified index and return all the records matching the combination of Boolean clauses.


2 Answers

You can do it with your range filter to filter the correct days and then with a script filter to filter the desired hours, like this:

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "range": {
                "date": {
                  "gte": "2015-11-01",
                  "lte": "2015-11-30"
                }
              }
            },
            {
              "script": {
                "script": {
                  "source": "doc.date.date.getHourOfDay() >= params.min && doc.date.date.getHourOfDay() <= params.max",
                  "params": {
                    "min": 8,
                    "max": 10
                  }
                }
              }
            }
          ]
        }
      }
    }
  }
}

Note that you need to make sure to enable dynamic scripting in order for this query to work.

like image 64
Val Avatar answered Oct 25 '22 12:10

Val


If I understood your question correctly then I think you have to add new field which indexes only time like

PUT your_index
{
  "mappings": {
    "your_type": {
      "properties": {
        "time": {
          "type":   "date",
          "format": "HH:mm:ss"
        }
      }
    }
  }
}

Then you can query like this

{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "date": {
              "gte": "2015-11-01",
              "lte": "2015-11-30"
            }
          }
        },
        {
          "range": {
            "time": {
              "gte": "08:00:00",
              "lte": "10:00:00"
            }
          }
        }
      ]
    }
  }
}

Does this help?

like image 39
ChintanShah25 Avatar answered Oct 25 '22 12:10

ChintanShah25