5. $filter en detalle
Operadores
| Grupo | Operadores |
|---|---|
| Comparación | eq ne gt ge lt le |
| Lógicos | and or not, con paréntesis |
| Pertenencia | in — code in ('A','B','C') |
| Aritméticos | add sub mul div mod |
Precedencia, de menor a mayor: or, and, not, comparación, aditiva, multiplicativa, unario.
Funciones
| Tipo | Funciones |
|---|---|
| Texto | contains startswith endswith tolower toupper trim length indexof substring concat |
| Fecha | year month day hour minute second date time now |
| Número | round floor ceiling |
| Conversión | cast — a Edm.String, Edm.Int32, Edm.Decimal, Edm.Boolean o Edm.DateTimeOffset |
Literales
# texto: comillas simples, y '' para una comilla literal
?$filter=name eq 'O''Brien'
# numeros, con sufijo de tipo opcional
?$filter=price gt 1500.50
# booleanos
?$filter=active eq true
# una columna booleana sola ya es una condicion
?$filter=active
# null: solo con eq y ne
?$filter=city_code eq null
# fechas ISO 8601, SIN comillas
?$filter=created ge 2024-01-31T00:00:00Z
?$filter=created ge 2024-01-31
# GUID, sin comillas y sin prefijo
?$filter=uid eq 0d7f1c5e-3a2b-4c8d-9e1f-5a6b7c8d9e0f
Combinaciones
?$filter=contains(name,'molinos') and active eq true
?$filter=year(created) eq 2024 and price gt 1000
?$filter=startswith(tolower(name),'mol')
?$filter=Localidad/name eq 'Rosario'
?$filter=(code eq 'A' or code eq 'B') and not active
La última línea del ejemplo muestra lo importante de Localidad/name: podés filtrar por un campo del maestro relacionado sin tener que expandirlo.
Lo que no se puede, y por qué
| Caso | Respuesta | Alternativa |
|---|---|---|
any / all — filtrar por el contenido de una colección | 501 | Consultar la entidad hija directamente y filtrar por la FK. |
Atravesar una navegación de uno a muchos: items/sku eq 'X' | 501 UnsupportedPath | Lo mismo: requiere any/all. |
null con gt, ge, lt, le | 400 | Usar eq null / ne null. |
| Campos de tipo Memo o Binary | 400 NotFilterable | Ninguna: en la base son text e image y no admiten comparación. |
has, isof, $it, $root, @parametro, geo.* | 501 | — |
aviso
Dos detalles que sorprenden. Solo contains, startswith y endswith pueden usarse como condición por sí mismas; cualquier otra función tiene que estar dentro de una comparación (length(name) gt 5, no length(name)). Y contains escapa los comodines: contains(descuento,'50%') busca el texto 50% literal, no "algo que empiece con 50".