Syntaxe OData $filter dans la Recherche Azure AI

Dans la Recherche Azure AI, le paramètre $filter spécifie des critères d’inclusion ou d’exclusion pour renvoyer des correspondances dans les résultats de recherche. Cet article décrit la syntaxe OData de $filter et fournit des exemples.

La construction du chemin des champs et les constantes de champs sont décrites dans la Vue d’ensemble du langage OData dans la Recherche Azure AI. Pour plus d’informations sur les scénarios de filtre, consultez Filtres dans la Recherche Azure AI.

Syntaxe

Un filtre dans le langage OData est une expression booléenne, qui à son tour peut prendre un de différents types d’expression, comme indiqué par l’EBNF (Extended Backus-Naur Form) suivant :

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

Un diagramme de syntaxe interactif est également disponible :

Remarque

Consultez Informations de référence sur la syntaxe d’expression OData pour la Recherche Azure AI afin d’avoir la forme EBNF complète.

Les types d’expressions booléennes incluent les suivants :

  • Expressions de filtre de collection utilisant any ou all. Celles-ci appliquent des critères de filtre aux champs de collection. Pour plus d’informations, consultez Opérateurs de collection OData dans la Recherche Azure AI.
  • Expressions logiques qui combinent d’autres expressions booléennes à l’aide des opérateurs and, or et not. Pour plus d’informations, consultez Opérateurs logiques OData dans la Recherche Azure AI.
  • Expressions de comparaison, qui comparent des champs ou variables de plage à des valeurs constantes à l’aide des opérateurs eq, ne, gt, lt, ge et le. Pour plus d’informations, consultez Opérateurs de comparaison OData dans la Recherche Azure AI. Les expressions de comparaison sont également utilisées pour comparer des distances entre des coordonnées géospatiales à l’aide de la fonction geo.distance. Pour plus d’informations, consultez Fonctions géospatiales OData dans la Recherche Azure AI.
  • Littéraux booléens true et false. Ces constantes peuvent parfois être utiles lors de la génération de filtre par programmation, mais ne sont pas systématiquement utilisées dans la pratique.
  • Appels de fonctions booléennes, notamment :
  • Chemins d’accès de champ ou variables de plage de type Edm.Boolean. Par exemple, si votre index comporte un champ booléen appelé IsEnabled et que vous souhaitez retourner tous les documents où ce champ est true, votre expression de filtre peut être simplement le nom IsEnabled.
  • Expressions booléennes entre parenthèses. L’utilisation de parenthèses peut vous aider à déterminer explicitement l’ordre des opérations dans un filtre. Pour plus d’informations sur la priorité par défaut des opérateurs OData, consultez la section suivante.

Précédence des opérateurs dans les filtres

Si vous écrivez une expression de filtre sans parenthèses autour de ses sous-expressions, la Recherche Azure AI l’évalue en fonction d’un ensemble de règles de priorité d’opérateur. Ces règles sont basées sur les opérateurs utilisés pour combiner des sous-expressions. Le tableau suivant répertorie les groupes d’opérateurs dans l’ordre de la priorité la plus élevée à la plus faible :

Groupe Opérateur(s)
Opérateurs logiques not
Opérateurs de comparaison eq, ne, gt, lt, ge, le
Opérateurs logiques and
Opérateurs logiques or

Un opérateur qui est plus élevé dans le tableau ci-dessus sera « lié plus étroitement » à ses opérandes que les autres opérateurs. Par exemple, and a une priorité plus élevée que or, et les opérateurs de comparaison ont une priorité plus élevée que ces deux-ci. Par conséquent, les deux expressions suivantes sont équivalentes :

    Rating gt 0 and Rating lt 3 or Rating gt 7 and Rating lt 10
    ((Rating gt 0) and (Rating lt 3)) or ((Rating gt 7) and (Rating lt 10))

L’opérateur not a la priorité la plus élevée de tous, supérieure encore aux opérateurs de comparaison. C’est pourquoi, si vous essayez d’écrire un filtre tel que le suivant :

    not Rating gt 5

Vous obtenez ce message d’erreur :

    Invalid expression: A unary operator with an incompatible type was detected. Found operand type 'Edm.Int32' for operator kind 'Not'.

Cette erreur se produit car l’opérateur est associé au champ Rating uniquement, qui est de type Edm.Int32, et non à l’expression de comparaison entière. La solution consiste à placer l’opérande de not entre parenthèses :

    not (Rating gt 5)

Limitations de taille des filtres

Les expressions de filtre que vous pouvez envoyer à la Recherche Azure AI sont limitées en taille et en complexité. Les limites sont en gros basées sur le nombre de clauses de votre expression de filtre. Une directive appropriée est que, si vous avez des centaines de clauses, vous risquez de dépasser la limite. Nous vous recommandons de concevoir votre application de telle sorte qu’elle ne génère pas de filtres de taille illimitée.

Conseil

L’utilisation de la fonction search.in au lieu de disjonctions longues de comparaisons d’égalité peut permettre d’éviter la limite de clause de filtre, dans la mesure où un appel de fonction est comptabilisé comme une seule clause.

Exemples

Rechercher tous les hôtels avec au moins une chambre, un tarif de base inférieur à 200 $ et une note d’évaluation égale ou supérieure à 4 :

    $filter=Rooms/any(room: room/BaseRate lt 200.0) and Rating ge 4

Rechercher tous les hôtels autres que « Sea View Motel » qui ont été rénovés depuis 2010 :

    $filter=HotelName ne 'Sea View Motel' and LastRenovationDate ge 2010-01-01T00:00:00Z

Rechercher tous les hôtels qui ont été rénovés en 2010 ou ultérieurement. Le littéral DateHeure inclut des informations de fuseau horaire pour l’heure standard du Pacifique :

    $filter=LastRenovationDate ge 2010-01-01T00:00:00-08:00

Rechercher tous les hôtels avec un parking inclus et où toutes les chambres sont non-fumeur :

    $filter=ParkingIncluded and Rooms/all(room: not room/SmokingAllowed)

- OU -

    $filter=ParkingIncluded eq true and Rooms/all(room: room/SmokingAllowed eq false)

Rechercher tous les hôtels de catégorie « Luxury » ou incluant un parking et ayant une évaluation de 5 :

    $filter=(Category eq 'Luxury' or ParkingIncluded eq true) and Rating eq 5

Rechercher tous les hôtels avec la balise « wifi » dans au moins une chambre (où chaque chambre a des balises stockées dans un champ Collection(Edm.String)) :

    $filter=Rooms/any(room: room/Tags/any(tag: tag eq 'wifi'))

Rechercher tous les hôtels avec n’importe quelles chambres :

    $filter=Rooms/any()

Rechercher tous les hôtels qui n’ont pas de chambres :

    $filter=not Rooms/any()

Rechercher tous les hôtels dans les 10 kilomètres d’un point de référence donnée (où Location est un champ de type Edm.GeographyPoint) :

    $filter=geo.distance(Location, geography'POINT(-122.131577 47.678581)') le 10

Rechercher tous les hôtels dans une fenêtre d’affichage décrite sous forme de polygone (où Location est un champ de type Edm.GeographyPoint). Le polygone doit être fermé, ce qui signifie que le premier point et le dernier doivent être le même. En outre, les points doivent être répertoriés dans le sens inverse des aiguilles d’une montre.

    $filter=geo.intersects(Location, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))')

Rechercher tous les hôtels où le champ « Description » est nul. Le champ sera nul s’il n’a jamais été défini ou s’il a été défini explicitement sur la valeur Null :

    $filter=Description eq null

Recherchez tous les hôtels avec un nom égal à « Sea View motel » ou « Budget hotel ». Ces expressions contiennent des espaces, et l’espace est un séparateur par défaut. Vous pouvez spécifier un autre séparateur entre guillemets simples comme troisième paramètre de chaîne :

    $filter=search.in(HotelName, 'Sea View motel,Budget hotel', ',')

Recherchez tous les hôtels avec un nom égal à « Sea View motel » ou « Budget hotel » séparés par « | » :

    $filter=search.in(HotelName, 'Sea View motel|Budget hotel', '|')

Recherchez tous les hôtels où toutes les chambres comportent la balise « wifi » ou « baignoire » :

    $filter=Rooms/any(room: room/Tags/any(tag: search.in(tag, 'wifi, tub')))

Recherchez une correspondance entre des expressions tirées d’une collection, telles que « heated towel racks » ou « hairdryer included » dans les balises.

    $filter=Rooms/any(room: room/Tags/any(tag: search.in(tag, 'heated towel racks,hairdryer included', ','))

Rechercher les documents avec le mot « waterfront ». Cette requête de filtre est identique à une demande de recherche avec search=waterfront.

    $filter=search.ismatchscoring('waterfront')

Rechercher les documents avec le mot « hostel » et une évaluation supérieure ou égale à 4, ou les documents avec le mot « motel » et une évaluation égale à 5. Cette requête n’a pas pu être exprimée sans la fonction search.ismatchscoring dans la mesure où elle combine la recherche en texte intégral et des opérations de filtre à l’aide de or.

    $filter=search.ismatchscoring('hostel') and rating ge 4 or search.ismatchscoring('motel') and rating eq 5

Rechercher les documents sans le mot « luxury ».

    $filter=not search.ismatch('luxury')

Rechercher les documents avec la phrase « ocean view » ou une évaluation égale à 5. La requête search.ismatchscoring sera exécutée seulement sur les champs HotelName et Description. Les documents qui correspondent uniquement à la deuxième clause de la disjonction sont également renvoyés (hôtels avec une Rating égale à 5). Ces documents sont renvoyés avec un score égal à zéro pour montrer clairement qu’ils ne correspondent à aucune des parties avec score de l’expression.

    $filter=search.ismatchscoring('"ocean view"', 'Description,HotelName') or Rating eq 5

Recherchez les hôtels où les termes « hôtel » et « aéroport » sont séparés par plus de cinq mots dans la description, et où toutes les chambres sont non-fumeur. Cette requête utilise le langage de requête Lucene complet.

    $filter=search.ismatch('"hotel airport"~5', 'Description', 'full', 'any') and not Rooms/any(room: room/SmokingAllowed)

Recherchez des documents qui ont un mot commençant par les lettres « Lux » dans le champ Description. Cette requête utilise la recherche de préfixe en association avec search.ismatch.

    $filter=search.ismatch('lux*', 'Description')

Étapes suivantes