Naslaginformatie over de syntaxis van de OData-expressie voor Azure AI Search

Azure AI Search maakt gebruik van OData-expressies als parameters in de API. Meestal worden OData-expressies gebruikt voor de $orderby en $filter parameters. Deze expressies kunnen complex zijn, met meerdere componenten, functies en operators. Zelfs eenvoudige OData-expressies, zoals eigenschapspaden, worden echter gebruikt in veel onderdelen van de REST API van Azure AI Search. Padexpressies worden bijvoorbeeld gebruikt om overal in de API te verwijzen naar subvelden van complexe velden, zoals bij het weergeven van subvelden in een suggestiefunctie, een scorefunctie, de $select parameter of zelfs zoeken in velden in Lucene-query's.

In dit artikel worden al deze vormen van OData-expressies beschreven met behulp van een formele grammatica. Er is ook een interactief diagram om de grammatica visueel te verkennen.

Formele grammatica

We kunnen de subset van de OData-taal beschrijven die wordt ondersteund door Azure AI Search met behulp van een EBNF-grammatica (Extended Backus-Naur Form). Regels worden 'top-down' weergegeven, beginnend met de meest complexe expressies en worden opgesplitst in primitievere expressies. Bovenaan ziet u de grammaticaregels die overeenkomen met specifieke parameters van de REST API van Azure AI Search:

  • $filter, gedefinieerd door de filter_expression regel.
  • $orderby, gedefinieerd door de order_by_expression regel.
  • $select, gedefinieerd door de select_expression regel.
  • Veldpaden, gedefinieerd door de field_path regel. Veldpaden worden overal in de API gebruikt. Ze kunnen verwijzen naar velden op het hoogste niveau van een index of subvelden met een of meer complexe bovenliggende velden .

Nadat ebNF een wenkbrauwbaar syntaxisdiagram is waarmee u interactief de grammatica en de relaties tussen de regels kunt verkennen.

/* Top-level rules */

filter_expression ::= boolean_expression

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

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

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


/* Shared base rules */

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


/* Rules for $orderby */

order_by_clause ::= (field_path | sortable_function) ('asc' | 'desc')?

sortable_function ::= geo_distance_call | 'search.score()'


/* Rules for $filter */

boolean_expression ::=
    collection_filter_expression
    | logical_expression
    | comparison_expression
    | boolean_literal
    | boolean_function_call
    | '(' boolean_expression ')'
    | variable

/* This can be a range variable in the case of a lambda, or a field path. */
variable ::= identifier | field_path

collection_filter_expression ::=
    field_path'/all(' lambda_expression ')'
    | field_path'/any(' lambda_expression ')'
    | field_path'/any()'

lambda_expression ::= identifier ':' boolean_expression

logical_expression ::=
    boolean_expression ('and' | 'or') boolean_expression
    | 'not' boolean_expression

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'


/* Rules for constants and literals */

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 ::= sign? 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'


/* Rules for functions */

function_call ::=
    geo_distance_call |
    boolean_function_call

geo_distance_call ::=
    'geo.distance(' variable ',' geo_point ')'
    | 'geo.distance(' geo_point ',' variable ')'

geo_point ::= "geography'POINT(" lon_lat ")'"

lon_lat ::= float_literal ' ' float_literal

boolean_function_call ::=
    geo_intersects_call |
    search_in_call |
    search_is_match_call

geo_intersects_call ::=
    'geo.intersects(' variable ',' geo_polygon ')'

/* You need at least four points to form a polygon, where the first and
last points are the same. */
geo_polygon ::=
    "geography'POLYGON((" lon_lat ',' lon_lat ',' lon_lat ',' lon_lat_list "))'"

lon_lat_list ::= lon_lat(',' lon_lat)*

search_in_call ::=
    'search.in(' variable ',' string_literal(',' string_literal)? ')'

/* Note that it is illegal to call search.ismatch or search.ismatchscoring
from inside a lambda expression. */
search_is_match_call ::=
    'search.ismatch'('scoring')?'(' search_is_match_parameters ')'

search_is_match_parameters ::=
    string_literal(',' string_literal(',' query_type ',' search_mode)?)?

query_type ::= "'full'" | "'simple'"

search_mode ::= "'any'" | "'all'"

Syntaxisdiagram

Als u de OData-taal grammatica visueel wilt verkennen die wordt ondersteund door Azure AI Search, probeert u het interactieve syntaxisdiagram:

Zie ook