Ranges

edit

When dealing with numbers in this chapter, we have so far searched for only exact numbers. In practice, filtering on ranges is often more useful. For example, you might want to find all products with a price greater than $20 and less than $40.

In SQL terms, a range can be expressed as follows:

SELECT document
FROM   products
WHERE  price BETWEEN 20 AND 40

Elasticsearch has a range filter, which, unsurprisingly, allows you to filter ranges:

"range" : {
    "price" : {
        "gt" : 20,
        "lt" : 40
    }
}

The range filter supports both inclusive and exclusive ranges, through combinations of the following options:

  • gt: > greater than
  • lt: < less than
  • gte: >= greater than or equal to
  • lte: <= less than or equal to

Here is an example range filter:

GET /my_store/products/_search
{
    "query" : {
        "filtered" : {
            "filter" : {
                "range" : {
                    "price" : {
                        "gte" : 20,
                        "lt"  : 40
                    }
                }
            }
        }
    }
}

If you need an unbounded range (for example, just >20), omit one of the boundaries:

"range" : {
    "price" : {
        "gt" : 20
    }
}

Ranges on Dates

edit

The range filter can be used on date fields too:

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-07 00:00:00"
    }
}

When used on date fields, the range filter supports date math operations. For example, if we want to find all documents that have a timestamp sometime in the last hour:

"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

This filter will now constantly find all documents with a timestamp greater than the current time minus 1 hour, making the filter a sliding window across your documents.

Date math can also be applied to actual dates, rather than a placeholder like now. Just add a double pipe (||) after the date and follow it with a date math expression:

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" 
    }
}

Less than January 1, 2014 plus one month

Date math is calendar aware, so it knows the number of days in each month, days in a year, and so forth. More details about working with dates can be found in the date format reference documentation.

Ranges on Strings

edit

The range filter can also operate on string fields. String ranges are calculated lexicographically or alphabetically. For example, these values are sorted in lexicographic order:

  • 5, 50, 6, B, C, a, ab, abb, abc, b

Terms in the inverted index are sorted in lexicographical order, which is why string ranges use this order.

If we want a range from a up to but not including b, we can use the same range filter syntax:

"range" : {
    "title" : {
        "gte" : "a",
        "lt" :  "b"
    }
}