Skip to content

Latest commit

 

History

History
162 lines (132 loc) · 4.37 KB

File metadata and controls

162 lines (132 loc) · 4.37 KB

Ranges

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

In SQL terms, a range can be expressed as:

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

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

If you need an unbounded range (e.g. just >20), just omit one of the boundaries:

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

Ranges on dates

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" (1)
    }
}
  1. Less than January 1 2014 plus one month.

Date math is "calendar aware", so it knows how many days are in each month, days in a year, etc. More details about working with dates can be found in the {ref}/mapping-date-format.html[date format reference documentation].

Ranges on strings

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"
    }
}
Be careful of cardinality

Numeric and date fields are indexed in such a way that ranges are very efficient to calculate. This is not the case for string fields, however. To perform a range on a string field, Elasticsearch is effectively performing a term filter for every term that falls in the range. This is much slower than a date or numeric range.

String ranges are fine on a field with low cardinality — a small number of unique terms. But the more unique terms you have, the slower the string range will be.