OData comparison operators in Azure AI Search - eq
, ne
, gt
, lt
, ge
, and le
The most basic operation in an OData filter expression in Azure AI Search is to compare a field to a given value. Two types of comparison are possible -- equality comparison, and range comparison. You can use the following operators to compare a field to a constant value:
Equality operators:
eq
: Test whether a field is equal to a constant valuene
: Test whether a field is not equal to a constant value
Range operators:
gt
: Test whether a field is greater than a constant valuelt
: Test whether a field is less than a constant valuege
: Test whether a field is greater than or equal to a constant valuele
: Test whether a field is less than or equal to a constant value
You can use the range operators in combination with the logical operators to test whether a field is within a certain range of values. See the examples later in this article.
Note
If you prefer, you can put the constant value on the left side of the operator and the field name on the right side. For range operators, the meaning of the comparison is reversed. For example, if the constant value is on the left, gt
would test whether the constant value is greater than the field. You can also use the comparison operators to compare the result of a function, such as geo.distance
, with a value. For Boolean functions such as search.ismatch
, comparing the result to true
or false
is optional.
Syntax
The following EBNF (Extended Backus-Naur Form) defines the grammar of an OData expression that uses the comparison operators.
comparison_expression ::=
variable_or_function comparison_operator constant |
constant comparison_operator variable_or_function
variable_or_function ::= variable | function_call
comparison_operator ::= 'gt' | 'lt' | 'ge' | 'le' | 'eq' | 'ne'
An interactive syntax diagram is also available:
Note
See OData expression syntax reference for Azure AI Search for the complete EBNF.
There are two forms of comparison expressions. The only difference between them is whether the constant appears on the left- or right-hand-side of the operator. The expression on the other side of the operator must be a variable or a function call. A variable can be either a field name, or a range variable in the case of a lambda expression.
Data types for comparisons
The data types on both sides of a comparison operator must be compatible. For example, if the left side is a field of type Edm.DateTimeOffset
, then the right side must be a date-time constant. Numeric data types are more flexible. You can compare variables and functions of any numeric type with constants of any other numeric type, with a few limitations, as described in the following table.
Variable or function type | Constant value type | Limitations |
---|---|---|
Edm.Double |
Edm.Double |
Comparison is subject to special rules for NaN |
Edm.Double |
Edm.Int64 |
Constant is converted to Edm.Double , resulting in a loss of precision for values of large magnitude |
Edm.Double |
Edm.Int32 |
n/a |
Edm.Int64 |
Edm.Double |
Comparisons to NaN , -INF , or INF are not allowed |
Edm.Int64 |
Edm.Int64 |
n/a |
Edm.Int64 |
Edm.Int32 |
Constant is converted to Edm.Int64 before comparison |
Edm.Int32 |
Edm.Double |
Comparisons to NaN , -INF , or INF are not allowed |
Edm.Int32 |
Edm.Int64 |
n/a |
Edm.Int32 |
Edm.Int32 |
n/a |
For comparisons that are not allowed, such as comparing a field of type Edm.Int64
to NaN
, the Azure AI Search REST API will return an "HTTP 400: Bad Request" error.
Important
Even though numeric type comparisons are flexible, we highly recommend writing comparisons in filters so that the constant value is of the same data type as the variable or function to which it is being compared. This is especially important when mixing floating-point and integer values, where implicit conversions that lose precision are possible.
Special cases for null
and NaN
When using comparison operators, it's important to remember that all non-collection fields in Azure AI Search can potentially be null
. The following table shows all the possible outcomes for a comparison expression where either side can be null
:
Operator | Result when only the field or variable is null |
Result when only the constant is null |
Result when both the field or variable and the constant are null |
---|---|---|---|
gt |
false |
HTTP 400: Bad Request error | HTTP 400: Bad Request error |
lt |
false |
HTTP 400: Bad Request error | HTTP 400: Bad Request error |
ge |
false |
HTTP 400: Bad Request error | HTTP 400: Bad Request error |
le |
false |
HTTP 400: Bad Request error | HTTP 400: Bad Request error |
eq |
false |
false |
true |
ne |
true |
true |
false |
In summary, null
is equal only to itself, and is not less or greater than any other value.
If your index has fields of type Edm.Double
and you upload NaN
values to those fields, you will need to account for that when writing filters. Azure AI Search implements the IEEE 754 standard for handling NaN
values, and comparisons with such values produce non-obvious results, as shown in the following table.
Operator | Result when at least one operand is NaN |
---|---|
gt |
false |
lt |
false |
ge |
false |
le |
false |
eq |
false |
ne |
true |
In summary, NaN
is not equal to any value, including itself.
Comparing geo-spatial data
You can't directly compare a field of type Edm.GeographyPoint
with a constant value, but you can use the geo.distance
function. This function returns a value of type Edm.Double
, so you can compare it with a numeric constant to filter based on the distance from constant geo-spatial coordinates. See the examples below.
Comparing string data
Strings can be compared in filters for exact matches using the eq
and ne
operators. These comparisons are case-sensitive.
Examples
Match documents where the Rating
field is between 3 and 5, inclusive:
Rating ge 3 and Rating le 5
Match documents where the Location
field is less than 2 kilometers from the given latitude and longitude:
geo.distance(Location, geography'POINT(-122.031577 47.578581)') lt 2.0
Match documents where the LastRenovationDate
field is greater than or equal to January 1st, 2015, midnight UTC:
LastRenovationDate ge 2015-01-01T00:00:00.000Z
Match documents where the Details/Sku
field is not null
:
Details/Sku ne null
Match documents for hotels where at least one room has type "Deluxe Room", where the string of the Rooms/Type
field matches the filter exactly:
Rooms/any(room: room/Type eq 'Deluxe Room')