Introducción al lenguaje de OData para las expresiones $filter, $orderby y $select en Azure AI Search

En este artículo se proporciona información general sobre el lenguaje de expresiones de OData usado en las expresiones $filter, $order-by y $select en Azure AI Search. El lenguaje se presenta en sentido ascendente, empezando por los elementos más básicos. Las expresiones OData que se pueden construir en una solicitud de consulta pueden ser desde simples hasta muy complejas, pero todas comparten elementos comunes. Entre los elementos compartidos se incluyen los siguientes:

  • Rutas de acceso de campo, que hacen referencia a campos específicos del índice.
  • Constantes, que son valores literales de un tipo de datos determinado.

Una vez que comprenda estos conceptos comunes, puede continuar con la sintaxis de nivel superior para cada expresión:

  • Las expresiones $filter se evalúan durante el análisis de la consulta y se restringe la búsqueda a campos específicos o se agregan criterios de coincidencia que se usan durante los exámenes de índice.
  • Las expresiones $orderby se aplican como un paso posterior al procesamiento en un conjunto de resultados para ordenar los documentos que se devuelven.
  • Las expresiones $select determinan qué campos de un documento se incluyen en el conjunto de resultados.

La sintaxis de estas expresiones es distinta de la sintaxis de consulta simple o completa que se usa en el parámetro search, aunque hay cierto solapamiento en la sintaxis de los campos de referencia.

Nota:

La terminología de Azure AI Search tiene ciertas diferencias con respecto al estándar de OData. Lo que llamamos un campo en Azure AI Search se denomina una propiedad en OData y lo mismo sucede con ruta de acceso de campo y ruta de acceso de propiedad. Un índice que contiene documentos en Azure AI Search se conoce más generalmente en OData como un conjunto de entidades que contiene entidades. En esta referencia se usará la terminología de Azure AI Search.

Rutas de acceso de campo

La siguiente EBNF (notación de Backus-Naur extendida) define la gramática de las rutas de acceso de campo:

field_path ::= identifier('/'identifier)*

identifier ::= [a-zA-Z_][a-zA-Z_0-9]*

También está disponible un diagrama de sintaxis interactivo:

Nota:

Consulte Referencia de la sintaxis de expresiones de OData para Azure AI Search para obtener la EBNF completa.

Una ruta de acceso de campo se compone de uno o varios identificadores separados por barras diagonales. Cada identificador es una secuencia de caracteres que debe comenzar con una letra ASCII o un carácter de subrayado y contener solo letras ASCII, dígitos o caracteres de subrayado. Las letras pueden ser mayúsculas o minúsculas.

Un identificador puede hacer referencia al nombre de un campo o a una variable de rango en el contexto de una expresión de colección (any o all) en un filtro. Una variable de rango es como una variable de bucle que representa el elemento actual de la colección. Si las colecciones son complejas, esa variable representa un objeto, que es el motivo de que pueda usar rutas de acceso de campo para hacer referencia a subcampos de la variable. Esta sintaxis es análoga a la notación de puntos de muchos lenguajes de programación.

En la tabla siguiente se muestran ejemplos de rutas de acceso de campo:

Ruta de acceso de campo Descripción
HotelName Hace referencia a un campo de nivel superior del índice.
Address/City Hace referencia al subcampo City de un campo complejo en el índice; Address es de tipo Edm.ComplexType en este ejemplo.
Rooms/Type Hace referencia al subcampo Type de un campo de colección complejo en el índice; Rooms es de tipo Collection(Edm.ComplexType) en este ejemplo.
Stores/Address/Country Hace referencia al subcampo Country del subcampo Address de un campo de colección complejo en el índice; Stores es de tipo Collection(Edm.ComplexType) y Address es de tipo Edm.ComplexType en este ejemplo.
room/Type Hace referencia al subcampo Type de la variable de rango room, por ejemplo, en la expresión de filtro Rooms/any(room: room/Type eq 'deluxe').
store/Address/Country Hace referencia al subcampo Country del subcampo Address de la variable de rango store, por ejemplo, en la expresión de filtro Stores/any(store: store/Address/Country eq 'Canada').

El significado de una ruta de acceso de campo varía según el contexto. En los filtros, una ruta de acceso de campo hace referencia al valor de una única instancia de un campo en el documento actual. En otros contextos, como $orderby, $select o en la búsqueda clasificada por campos de la sintaxis completa de Lucene, una ruta de acceso de campo hace referencia al campo propiamente dicho. Esta diferencia tiene algunas consecuencias en cómo se usan las rutas de acceso de campo en los filtros.

Considere la ruta de acceso de campo Address/City. En un filtro, esta ruta hacer referencia a una única ciudad del documento actual, como "San Francisco". En cambio, Rooms/Type hace referencia al subcampo Type para muchas habitaciones (por ejemplo, "standard" para la primera habitación, "deluxe" para la segunda, etc.). Puesto que Rooms/Type no hace referencia a una única instancia del subcampo Type, no se puede usar directamente en un filtro. Así que, para filtrar por el tipo de habitación, usaría una expresión lambda con una variable de rango, como esta:

Rooms/any(room: room/Type eq 'deluxe')

En este ejemplo, la variable de rango room aparece en la ruta de acceso de campo room/Type. De este modo, room/Type hace referencia al tipo de habitación actual en el documento actual. Como es una única instancia del subcampo Type, se puede usar directamente en el filtro.

Uso de rutas de acceso de campo

Las rutas de acceso de campo se usan muchos parámetros de las API REST de Azure AI Search. En la tabla siguiente se enumeran todos los lugares donde pueden usarse, además de las restricciones sobre su uso:

API Nombre de parámetro Restricciones
Create or Update Index suggesters/sourceFields Ninguno
Create or Update Index scoringProfiles/text/weights Solo puede hacer referencia a campos que permiten realizar búsquedas.
Create or Update Index scoringProfiles/functions/fieldName Solo puede hacer referencia a campos filtrables.
Buscar search cuando queryType es full Solo puede hacer referencia a campos que permiten realizar búsquedas.
Buscar facet Solo puede hacer referencia a campos clasificables
Buscar highlight Solo puede hacer referencia a campos que permiten realizar búsquedas.
Buscar searchFields Solo puede hacer referencia a campos que permiten realizar búsquedas.
Suggest y Autocomplete searchFields Solo puede hacer referencia a campos que forman parte de un proveedor de sugerencias.
Search, Suggest y Autocomplete $filter Solo puede hacer referencia a campos filtrables.
Search y Suggest $orderby Solo puede hacer referencia a campos ordenables.
Search, Suggest y Lookup $select Solo puede hacer referencia a campos recuperables

Constantes

Las constantes en OData son valores literales de un determinado tipo de Entity Data Model (EDM). Consulte Tipos de datos admitidos para ver una lista de los tipos que se admiten en Azure AI Search. No se admiten constantes de tipos de colección.

En la tabla siguiente se muestran ejemplos de constantes para cada uno de los tipos de datos que Azure AI Search admite:

Tipo de datos Constantes de ejemplo
Edm.Boolean true, false
Edm.DateTimeOffset 2019-05-06T12:30:05.451Z
Edm.Double 3.14159, -1.2e7, NaN, INF, -INF
Edm.GeographyPoint geography'POINT(-122.131577 47.678581)'
Edm.GeographyPolygon geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'
Edm.Int32 123, -456
Edm.Int64 283032927235
Edm.String 'hello'

Caracteres especiales de escape en constantes de cadena

Las constantes de cadena en OData están delimitadas por comillas simples. Si tiene que crear una consulta con una constante de cadena que, a su vez, pueda contener comillas simples, puede escapar las comillas incrustadas si las duplica.

Por ejemplo, una frase con un apóstrofo sin formato, como "Alice's car", se representaría en OData como la constante de cadena 'Alice''s car'.

Importante

Al construir filtros mediante programación, es importante recordar escapar las constantes de cadena que proceden de los datos proporcionados por el usuario. Esto es para mitigar la posibilidad de ataques por inyección de código, en especial cuando se usan filtros para implementar el recorte de seguridad.

Sintaxis de las constantes

El siguiente EBNF (notación de Backus-Naur extendida) define la gramática de la mayoría de las constantes que se muestran en la tabla anterior. La gramática de los tipos geoespaciales se puede encontrar en Funciones geoespaciales de OData en Azure AI Search.

constant ::=
    string_literal
    | date_time_offset_literal
    | integer_literal
    | float_literal
    | boolean_literal
    | 'null'

string_literal ::= "'"([^'] | "''")*"'"

date_time_offset_literal ::= date_part'T'time_part time_zone

date_part ::= year'-'month'-'day

time_part ::= hour':'minute(':'second('.'fractional_seconds)?)?

zero_to_fifty_nine ::= [0-5]digit

digit ::= [0-9]

year ::= digit digit digit digit

month ::= '0'[1-9] | '1'[0-2]

day ::= '0'[1-9] | [1-2]digit | '3'[0-1]

hour ::= [0-1]digit | '2'[0-3]

minute ::= zero_to_fifty_nine

second ::= zero_to_fifty_nine

fractional_seconds ::= integer_literal

time_zone ::= 'Z' | sign hour':'minute

sign ::= '+' | '-'

/* In practice integer literals are limited in length to the precision of
the corresponding EDM data type. */
integer_literal ::= digit+

float_literal ::=
    sign? whole_part fractional_part? exponent?
    | 'NaN'
    | '-INF'
    | 'INF'

whole_part ::= integer_literal

fractional_part ::= '.'integer_literal

exponent ::= 'e' sign? integer_literal

boolean_literal ::= 'true' | 'false'

También está disponible un diagrama de sintaxis interactivo:

Nota:

Consulte Referencia de la sintaxis de expresiones de OData para Azure AI Search para obtener la EBNF completa.

Generación de expresiones a partir de rutas de acceso de campo y constantes

Las rutas de acceso de campo y las constantes son la parte más básica de una expresión de OData, pero ya son expresiones completas por derecho propio. De hecho, el parámetro $select de Azure AI  Search no es más que una lista separada por comas de rutas de acceso de campo y $orderby no es mucho más complicado que $select. Si resulta que tiene un campo de tipo Edm.Boolean en el índice, puede escribir incluso un filtro que no sea si no la ruta de acceso de ese campo. Las constantes true y false son igualmente filtros válidos.

Sin embargo, casi siempre necesitará expresiones más complejas que hagan referencia a más de un campo y más de una constante. Estas expresiones se compilan de diferentes maneras según el parámetro.

La siguiente EBNF (notación de Backus-Naur extendida) define la gramática de los parámetros $filter, $orderby y $select. Estos parámetros se generan a partir de expresiones más sencillas que hacen referencia a las rutas de acceso de campo y a las constantes:

filter_expression ::= boolean_expression

order_by_expression ::= order_by_clause(',' order_by_clause)*

select_expression ::= '*' | field_path(',' field_path)*

También está disponible un diagrama de sintaxis interactivo:

Nota:

Consulte Referencia de la sintaxis de expresiones de OData para Azure AI Search para obtener la EBNF completa.

Pasos siguientes

Los parámetros $orderby y $select son ambos listas separadas por comas de expresiones más sencillas. El parámetro $filter es una expresión booleana que se compone de subexpresiones más sencillas. Estas subexpresiones se combinan mediante operadores lógicos, como and, or y not, operadores de comparación, como eq, lt, gt, etc. y operadores de colección, como any y all.

Los parámetros $filter, $orderby, y $select se exploran con más detalle en los siguientes artículos: