Filtres dans les requêtes de texte

Un filtre fournit des critères basés sur des valeurs pour inclure ou exclure du contenu avant l’exécution de la requête. Par exemple, l’inclusion ou l’exclusion de documents sur la base de dates, d’emplacements ou d’une langue. Les filtres sont spécifiés sur des champs individuels. Une définition de champ doit être attribuée comme « filtrable » si vous souhaitez l’utiliser dans les expressions de filtre.

Un filtre est spécifié à l’aide de la syntaxe d’expression de filtre OData. Contrairement à la recherche en texte intégral, un filtre ne fonctionne que si une correspondance exacte est établie.

Quand utiliser un filtre

Certains filtres sont fondamentaux pour diverses expériences de recherche. C’est notamment le cas des filtres de recherche géospatiale de type « recherche à proximité », de navigation par facettes et de sécurité, qui montrent uniquement les documents qu’un utilisateur est autorisé à afficher. Si vous implémentez l’une de ces expériences, un filtre est requis. C’est le filtre associé à la requête de recherche qui fournit les coordonnées de géolocalisation, la catégorie de facettes sélectionnée par l’utilisateur, ou l’ID de sécurité du demandeur.

Les scénarios courants sont les suivants :

  • Répartition des résultats de la recherche en fonction du contenu de l’index. À partir d’un schéma indiquant l’emplacement, les catégories et les équipements de l’hôtel, vous pouvez créer un filtre qui correspond explicitement aux critères (à Seattle, sur l’eau, avec une vue).

  • Implémentation d’une expérience de recherche avec une dépendance de filtre :

    • La navigation par facettes utilise un filtre pour re-transmettre la catégorie de facettes sélectionnée par l’utilisateur.
    • La recherche géospatiale utilise un filtre pour passer des coordonnées de l’emplacement actuel dans des applications et des fonctions « Rechercher près de moi » qui correspondent dans une zone ou à distance.
    • Les filtres de sécurité transmettent des identificateurs de sécurité comme critères de filtre, une correspondance dans l’index servant de proxy pour les droits d’accès au document.
  • Effectuez une « recherche de numéros ». Les champs numériques sont récupérables et peuvent apparaître dans des résultats de la recherche. Cependant, ils ne peuvent pas faire l’objet d’une recherche (en texte intégral) individuelle. Si vous avez besoin de critères de sélection basés sur des données numériques, utilisez un filtre.

Comment les filtres sont-ils exécutés ?

Au moment de la requête, un analyseur de filtre accepte les critères en entrée, convertit l’expression en expressions booléennes atomiques sous la forme d’une arborescence de filtres qui est ensuite évaluée sur les champs filtrables dans un index.

Le filtrage se produit en même temps que la recherche. Il permet de qualifier les documents à inclure dans le traitement en aval pour la récupération de documents et le scoring de leur pertinence. En association avec une chaîne de recherche, le filtre réduit efficacement l’ensemble de rappels de l’opération de recherche suivante. Utilisé seul (par exemple, lorsque la chaîne de requête est vide, où search=*), le critère de filtre est la seule entrée.

Définition des filtres

Les filtres sont des expressions OData formulées dans la syntaxe de filtre prise en charge par la Recherche Azure AI.

Vous pouvez spécifier un filtre pour chaque opération de recherche, mais le filtre lui-même peut inclure plusieurs champs, plusieurs critères et, si vous utilisez une fonction ismatch, plusieurs expressions de recherche en texte intégral. Dans une expression de filtre comportant plusieurs parties, vous pouvez spécifier des prédicats dans n’importe quel ordre (soumis aux règles de précédence de l’opérateur). Vous n’obtenez aucun gain sensible des performances si vous tentez de réorganiser les prédicats dans une séquence particulière.

L’une des limites inconditionnelles sur une expression de filtre est la limite de taille maximale de la demande. La demande entière, filtre inclus, peut être un maximum de 16 Mo pour la commande POST ou de 8 Ko pour la commande GET. Le nombre de clauses dans votre expression de filtre est également limité. Une règle empirique est que, si vous avez des centaines de clauses, vous risquez d’atteindre 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.

Les exemples suivants illustrent des définitions de filtre prototypiques dans plusieurs API.

POST https://[service name].search.windows.net/indexes/hotels/docs/search?api-version=2020-06-30
{
    "search": "*",
    "filter": "Rooms/any(room: room/BaseRate lt 150.0)",
    "select": "HotelId, HotelName, Rooms/Description, Rooms/BaseRate"
}
options = new SearchOptions()
{
    Filter = "Rating gt 4",
    OrderBy = { "Rating desc" }
};

Modèles de filtre

Les exemples suivants illustrent plusieurs modèles d’utilisation pour des scénarios de filtre. Pour d’autres idées, voir Syntaxe d’expression OData > Exemples.

  • $filter autonome, sans chaîne de requête, utile lorsque l’expression de filtre est en mesure de qualifier complètement les documents d’intérêt. À défaut de chaîne de requête, il n’y a ni analyse lexicale ou linguistique, ni notation, ni classement. Notez que la chaîne de recherche comporte uniquement un astérisque, ce qui signifie « faire correspondre tous les documents ».

    {
      "search": "*",
      "filter": "Rooms/any(room: room/BaseRate ge 60 and room/BaseRate lt 300) and Address/City eq 'Honolulu"
    }
    
  • Combinaison de chaîne de requête et de $filter, où le filtre crée le sous-ensemble, et la chaîne de requête fournit les entrées de condition de recherche en texte intégral sur le sous-ensemble filtré. L’ajout de termes (théâtres à distance de marche) introduit des scores de recherche dans les résultats, où les documents qui correspondent le mieux aux termes sont mieux classés. Utiliser un filtre avec une chaîne de requête constitue le modèle d’utilisation le plus courant.

    {
      "search": "walking distance theaters",
      "filter": "Rooms/any(room: room/BaseRate ge 60 and room/BaseRate lt 300) and Address/City eq 'Seattle'"
    }
    
    
  • Requêtes composées, séparées par « OR » (ou), chacune avec ses propres critères de filtre (par exemple, « beagle » dans « chien » ou « siamois » dans « chat »). Les expressions combinées utilisant or sont évaluées individuellement et la correspondance des documents joints avec chaque expression est retournée avec la réponse. Ce modèle d’utilisation est obtenu via la fonction search.ismatchscoring. Vous pouvez également utiliser la version sans scoring, search.ismatch.

    # Match on hostels rated higher than 4 OR 5-star motels.
    $filter=search.ismatchscoring('hostel') and Rating ge 4 or search.ismatchscoring('motel') and Rating eq 5
    
    # Match on 'luxury' or 'high-end' in the description field OR on category exactly equal to 'Luxury'.
    $filter=search.ismatchscoring('luxury | high-end', 'Description') or Category eq 'Luxury'&$count=true
    

    Il est également possible de combiner la recherche en texte intégral via search.ismatchscoring avec des filtres utilisant and au lieu de or. Toutefois, cette opération équivaut à utiliser les paramètres search et $filter dans une demande de recherche sur le plan fonctionnel. Par exemple, les deux requêtes suivantes génèrent le même résultat :

    $filter=search.ismatchscoring('pool') and Rating ge 4
    
    search=pool&$filter=Rating ge 4
    

Conditions requises des champs pour le filtrage

Dans l’API REST, la propriété filterable (filtrable) est activée par défaut pour les champs simples. Les champs filtrables augmentent la taille de l’index. Veillez à définir "filterable": false pour les champs que vous ne prévoyez pas réellement d’utiliser dans un filtre. Pour plus d’informations sur les paramètres des définitions de champ, voir Create Index (Créer un index).

Dans le Kit de développement logiciel (SDK) .NET, la propriété filterable (filtrable) est désactivée par défaut. Vous pouvez rendre un champ filtrable en définissant la propriété IsFilterable de l’objet SearchField correspondant sur true. Dans l’exemple suivant, l’attribut est défini sur la propriété Rating d’une classe de modèle mappant vers la définition d’index.

[SearchField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public double? Rating { get; set; }

Rendre filtrable un champ existant

Vous ne pouvez pas modifier des champs existants pour les rendre filtrables. À la place, vous devez ajouter un nouveau champ ou régénérer l’index. Pour plus d’informations sur la régénération d’un index ou comment remplir à nouveau des champs, consultez Comment régénérer un index Recherche Azure AI.

Notions de base concernant les filtres de texte

Les filtres de texte comparent les champs de chaîne aux chaînes littérales que vous fournissez dans le filtre : $filter=Category eq 'Resort and Spa'

Contrairement à la recherche en texte intégral, les filtres de texte n’appliquent aucune analyse lexicale ou césure de mots. Les comparaisons portent alors uniquement sur des correspondances exactes. Par exemple, supposons un champ f contenant les mots « Sunny day » (journée ensoleillée). $filter=f eq 'sunny day' sera une correspondance, mais pas $filter=f eq 'sunny'.

Les chaînes de texte respectent la casse, et les filtres de texte respectent la casse par défaut. Par exemple, $filter=f eq 'Sunny day' ne trouve pas « journée ensoleillée ». Toutefois, vous pouvez utiliser un normaliseur pour faire en sorte que le filtrage ne respecte pas la casse.

Approches pour le filtrage de texte

Approche Description Quand utiliser
search.in Une fonction qui compare un champ à une liste délimitée de chaînes. Cette fonction est recommandée pour les filtres de sécurité et pour tous les filtres dans lesquels plusieurs valeurs de texte brut doivent être comparées à un champ de chaîne. La fonction search.in est conçue pour fonctionner rapidement. Elle est donc beaucoup plus rapide qu’une comparaison explicite du champ à chaque chaîne à l’aide de eq et or.
search.ismatch Fonction permettant de combiner des opérations de recherche en texte intégral avec des opérations de filtre strictement booléen dans une même expression de filtre. Utilisez search.ismatch (ou son équivalent search.ismatchscoring pour le scoring) lorsque vous souhaitez utiliser plusieurs combinaisons de filtres et de recherches dans une seule demande. Vous pouvez également l’utiliser pour un filtre contains afin de filtrer sur une chaîne partielle figurant à l’intérieur d’une chaîne de plus grande taille.
$filter=field operator string Expression définie par l’utilisateur composée de champs, d’opérateurs et de valeurs. Utilisez-la lorsque vous souhaitez rechercher des correspondances exactes entre un champ de chaîne et une valeur de chaîne.

Notions de base concernant les filtres numériques

Les champs numériques ne sont pas de type searchable (il n’est pas possible d’y effectuer une recherche) dans le contexte d’une recherche en texte intégral. Seules des chaînes peuvent faire l’objet d’une recherche en texte intégral. Par exemple, le terme de recherche 99,99 ne permet pas d’obtenir la liste des articles dont le prix est 99,99. Au lieu de cela, vous obtenez la liste des documents dont des champs de chaîne contiennent le nombre 99. Par conséquent, si vous avez des données numériques, l’hypothèse est que vous allez les utiliser pour des filtres, dont des plages, des facettes, des groupes, etc.

Les documents contenant des champs numériques (prix, taille, référence, ID, etc.) fournissent ces valeurs dans les résultats de recherche si ces champs sont marqués en tant que retrievable. Ce qu’il importe de souligner ici, c’est que la recherche en texte intégral proprement dite ne s’applique pas aux champs de type numérique.

Étapes suivantes

Tout d’abord, essayez l’Explorateur de recherche dans le portail pour soumettre des requêtes avec des paramètres de $filter. L’index d’exemple immobilier fournit des résultats intéressants pour les requêtes filtrées suivantes lorsque vous les collez dans la barre de recherche :

# Geo-filter returning documents within 5 kilometers of Redmond, Washington state
# Use $count=true to get a number of hits returned by the query
# Use $select to trim results, showing values for named fields only
# Use search=* for an empty query string. The filter is the sole input

search=*&$count=true&$select=description,city,postCode&$filter=geo.distance(location,geography'POINT(-122.121513 47.673988)') le 5

# Numeric filters use comparison like greater than (gt), less than (lt), not equal (ne)
# Include "and" to filter on multiple fields (baths and bed)
# Full text search is on John Leclerc, matching on John or Leclerc

search=John Leclerc&$count=true&$select=source,city,postCode,baths,beds&$filter=baths gt 3 and beds gt 4

# Text filters can also use comparison operators
# Wrap text in single or double quotes and use the correct case
# Full text search is on John Leclerc, matching on John or Leclerc

search=John Leclerc&$count=true&$select=source,city,postCode,baths,beds&$filter=city gt 'Seattle'

Pour utiliser d’autres exemples, consultez Syntaxe d’expression de filtre OData > Exemples.

Voir aussi