Recherche par attribut

La recherche par attribut vous permet d'associer des informations catégoriques à vos documents. Un attribut est un couple attribut/valeur. Par exemple, l'attribut nommé "taille" peut avoir les valeurs "petit", "moyen" et "grand".

En utilisant des attributs avec la recherche, vous pouvez extraire des informations récapitulatives pour vous aider à affiner une requête et à "explorer" vos résultats en une série d'étapes.

Ceci est utile pour les applications telles que les sites commerciaux, où vous avez l’intention de proposer un ensemble de filtres permettant aux clients de limiter les produits qu’ils souhaitent voir.

Les données agrégées d'un attribut vous montrent comment les valeurs d'un attribut sont distribuées. Par exemple, la "taille" de l'attribut peut apparaître dans de nombreux documents de votre jeu de résultats. Les données agrégées pour cet attribut pourraient indiquer que la valeur "petit" est apparue 100 fois, "moyenne" 300 fois et "grande" 250 fois. Chaque paire attribut/valeur représente un sous-ensemble de documents dans le résultat de la requête. Une clé, appelée raffinement, est associée à chaque paire. Vous pouvez inclure des raffinements dans une requête pour récupérer des documents correspondant à la chaîne de requête et dont les valeurs d'attribut correspondent à un ou plusieurs raffinements.

Lorsque vous effectuez une recherche, vous pouvez choisir les attributs à collecter et afficher avec les résultats, ou vous pouvez activer la découverte d'attributs pour sélectionner automatiquement les attributs qui apparaissent le plus souvent dans vos documents.

Ajouter des attributs à un document

Ajoutez des attributs à un document avant de l'ajouter à un index. Faites ceci en même temps que vous spécifiez les champs du document :

def add_faceted_document(index):
    document = search.Document(
        doc_id="doc1",
        fields=[search.AtomField(name="name", value="x86")],
        facets=[
            search.AtomFacet(name="type", value="computer"),
            search.NumberFacet(name="ram_size_gb", value=8),
        ],
    )

    index.put(document)

Un attribut est comparable à un champ de document : il possède un nom et une valeur.

Les noms des attributs suivent les mêmes règles que les champs de document : ils sont sensibles à la casse et ne peuvent contenir que des caractères ASCII. Ils doivent commencer par une lettre et peuvent contenir des lettres, des chiffres ou des traits de soulignement. Un nom ne peut pas dépasser 500 caractères.

La valeur d'un attribut peut être une chaîne atomique (500 caractères maximum) ou un nombre (valeur de virgule flottante en double précision comprise entre -2 147 483 647 et 2 147 483 647).

Vous pouvez affecter plusieurs valeurs à un attribut d'un document en ajoutant un attribut du même nom et du même type plusieurs fois, en utilisant chaque fois une valeur différente.

Il n'y a pas de limite au nombre de valeurs qu'un attribut peut avoir. Il n'y a pas non plus de limite au nombre d'attributs que vous pouvez ajouter à un document ni au nombre d'attributs nommés de manière unique dans un index.

Notez que chaque fois que vous utilisez un attribut, il peut prendre une valeur atomique ou numérique. Un attribut ayant pour nom "taille" peut être associé à un document avec la valeur de chaîne "petit" et à un autre document avec la valeur numérique 8. En fait, le même attribut peut apparaître plusieurs fois sur le même document avec les deux types de valeurs. Nous vous déconseillons d'utiliser à la fois des valeurs atomiques et numériques pour le même attribut, même si cela est autorisé.

Bien qu'un attribut ait un type spécifique lorsque vous l'ajoutez à un document, les résultats de la recherche rassemblent toutes ses valeurs. Par exemple, les résultats pour l'attribut "taille" pourraient indiquer qu'il y avait 100 instances de la valeur "petite", 150 instances de "moyen" et 135 instances de valeurs numériques dans la plage [4, 8). Les valeurs numériques exactes et leur distribution de fréquence ne sont pas montrées.

Lorsque vous récupérez un document à l'aide d'une requête, vous ne pouvez pas accéder directement à ses attributs et à ses valeurs. Vous devez demander que les informations d'attribut soient renvoyées avec votre requête, comme expliqué dans la section suivante.

Utiliser une recherche par attributs pour récupérer des informations sur les attributs

Vous pouvez demander au moteur de recherche de découvrir les attributs les plus fréquemment utilisés, ce qu’on appelle la découverte automatique d'attributs. Vous pouvez également extraire explicitement les informations sur les attributs en sélectionnant un attribut par son nom, ou par son nom et sa valeur. Vous pouvez combiner les trois types d'extraction d'attributs dans une même requête.

Demander des informations sur les attributs n’affectera pas les documents renvoyés par votre requête. Cela peut affecter les performances. Effectuer une recherche par attributs avec une profondeur par défaut de 1 000 a le même effet que de définir la limite du marqueur des options de tri sur 1 000.

Découverte automatique d'attributs

La découverte automatique d'attributs recherche les attributs qui apparaissent le plus souvent ensemble dans vos documents. Par exemple, supposons que les documents correspondant à votre requête incluent un attribut "couleur" qui apparaît 5 fois avec la valeur "rouge", 5 fois avec la valeur "blanc" et 5 fois avec la couleur "bleu". Cet attribut a un compte total de 15. En vue de la découverte, il serait mieux classé qu'un autre attribut "ombre" qui apparaît dans les mêmes documents correspondants 6 fois avec la valeur "sombre" et 7 fois avec la valeur "clair".

Pour activer la détection d'attributs, vous devez la définir dans votre requête :

def facet_discovery(index):
    # Create the query and enable facet discovery.
    query = search.Query("name:x86", enable_facet_discovery=True)
    results = index.search(query)

    for facet in results.facets:
        print("facet {}.".format(facet.name))
        for value in facet.values:
            print(
                "{}: count={}, refinement_token={}".format(
                    value.label, value.count, value.refinement_token
                )
            )

Lorsque vous récupérez des attributs par découverte, par défaut, seules les 10 valeurs les plus fréquentes d'un attribut sont renvoyées. Vous pouvez augmenter cette limite jusqu'à 100 en utilisant le paramètre discovery_limit de FacetOptions.

Notez que la découverte automatique d'attributs n'est pas censée renvoyer tous les attributs possibles et leurs valeurs. Les attributs renvoyés par la découverte peuvent varier d'une exécution à l'autre. Si vous souhaitez utiliser un ensemble d'attributs fixe, utilisez un paramètre return_facets sur votre requête.

Les valeurs de chaîne seront renvoyées individuellement. Les valeurs numériques d'un attribut découvert sont renvoyées dans une seule plage [min max). Vous pouvez examiner cette plage et créer une sous-gamme plus petite pour une requête ultérieure.

Sélectionner des attributs par nom

Pour obtenir des informations sur un attribut par son nom uniquement, ajoutez un paramètre return_facets à votre requête, en incluant le nom d'attribut dans la liste :

def facet_by_name(index):
    # Create the query and specify to only return the "type" and "ram_size_gb"
    # facets.
    query = search.Query("name:x86", return_facets=["type", "ram_size_gb"])
    results = index.search(query)

    for facet in results.facets:
        print("facet {}".format(facet.name))
        for value in facet.values:
            print(
                "{}: count={}, refinement_token={}".format(
                    value.label, value.count, value.refinement_token
                )
            )

Lorsque vous récupérez des attributs par nom, par défaut, seules les 10 valeurs les plus fréquentes d'un attribut sont renvoyées. Vous pouvez augmenter cette limite jusqu'à 20 à l'aide du paramètre discovery_value_limit de FacetOptions.

Sélectionner des attributs par nom et valeur

Pour extraire des informations uniquement sur les valeurs particulières d'un attributs, ajoutez un paramètre return_facets incluant un objet FacetRequest avec une liste de valeurs :

def facet_by_name_and_value(index):
    # Create the query and specify to return the "type" facet with values
    # "computer" and "printer" and the "ram_size_gb" facet with value in the
    # ranges [0,4), [4, 8), and [8, max].
    query = search.Query(
        "name:x86",
        return_facets=[
            search.FacetRequest("type", values=["computer", "printer"]),
            search.FacetRequest(
                "ram_size_gb",
                ranges=[
                    search.FacetRange(end=4),
                    search.FacetRange(start=4, end=8),
                    search.FacetRange(start=8),
                ],
            ),
        ],
    )

    results = index.search(query)
    for facet in results.facets:
        print("facet {}".format(facet.name))
        for value in facet.values:
            print(
                "{}: count={}, refinement_token={}".format(
                    value.label, value.count, value.refinement_token
                )
            )

Les valeurs d'un même FacetRequest doivent toutes être de même type, soit une liste de valeurs de chaîne, soit, pour les nombres, une liste de FacetRanges, qui sont des intervalles fermés à gauche (début) et ouverts à droite (fin). Si votre attribut comporte un mélange de valeurs de chaîne et de nombre, ajoutez des FacetRequests distinctes pour chacune.

Options

Vous pouvez contrôler la recherche par attributs en ajoutant le paramètre facet_options à un appel de requête. Ce paramètre prend une seule instance de FacetOptions. Utilisez ce paramètre pour remplacer le comportement par défaut de la recherche par attributs.

options = FacetOptions(discover_facet_limit=5,
                       discover_facet_value_limit=10,
                       depth=6000);
Paramètre Description Par défaut
discover_facet_limit Nombre d'attributs à découvrir si la découverte d'attributs est activée. Si 0, la découverte d'attributs sera désactivée. 10
discover_facet_value_limit Nombre de valeurs à renvoyer pour chacun des attributs les plus découverts. 10
depth Nombre minimal de documents à évaluer dans les résultats de la requête pour recueillir des informations sur les attributs. 1000

L'option depth s'applique aux trois types d'agrégation d'attributs : par nom, nom et valeur, et découverte automatique. Les autres options sont pour la découverte automatique uniquement.

Notez que la profondeur des attributs est généralement beaucoup plus grande que la limite de requête. Les résultats d'attributs sont calculés au moins en nombre de documents. Si vous avez défini une limite de notation supérieure à la profondeur pour les options de tri, la limite de notation sera utilisée à la place.

Récupérer les résultats d'attributs

Lorsque vous utilisez des paramètres de recherche à attributs dans une requête, les informations d'attributs agrégés sont fournies avec le résultat de la requête.

Une requête aura une liste de FacetResult. Il y aura un résultat dans la liste pour chaque attribut apparu dans un document correspondant à votre requête. Pour chaque résultat, vous obtiendrez :

  • le nom de l'attribut ;
  • une liste des valeurs les plus fréquentes pour l'attribut. Pour chaque valeur, il existe un décompte approximatif du nombre de fois où l'attribut apparaît, ainsi qu'une clé de raffinement pouvant être utilisée pour extraire les documents correspondant à cette requête.

Notez que la liste de valeurs inclura la chaîne et les valeurs numériques d'un attribut. Si l'attribut a été découvert automatiquement, ses valeurs numériques sont renvoyées sous la forme d'un intervalle unique [min max). Si vous avez explicitement demandé un attribut numérique avec une ou plusieurs plages dans votre requête, la liste contiendra un intervalle fermé-ouvert [début fin) pour chaque plage.

La liste des valeurs d'attribut peut ne pas inclure toutes les valeurs trouvées dans vos documents, car les options de requête déterminent le nombre de documents à examiner et le nombre de valeurs à renvoyer.

Les informations agrégées pour chaque attribut peuvent être lues à partir des résultats de la recherche :

query = search.Query(...)
results = index.search(query)
for facet_info in results.facets:
  ...

Par exemple, une requête peut avoir trouvé des documents contenant un attribut "taille" avec les valeurs de chaîne et les valeurs numériques. Le FacetResult pour cet attribut sera construit comme ceci :

FacetResult(name='size', values=[
  FacetResultValue(label='[8, 10)', 22, refinement=refinement_key),
  FacetResultValue(label='small', 100, refinement=refinement_key),
  FacetResultValue(label='medium', 300, refinement=refinement_key),
  FacetResultValue(label='large', 250, refinement=refinement_key)])

Le paramètre label est construit à partir d'une valeur d'attribut. Pour les valeurs numériques, label est la représentation d'une plage.

La chaîne refinement_key est une chaîne Web/URL sécurisée qui peut être utilisée dans une requête ultérieure pour extraire les documents correspondant au nom et à la valeur de l'attribut de ce résultat.

Utiliser des attributs pour affiner/filtrer une requête

Le filtre associé à chaque FacetResultValue peut être utilisé pour affiner davantage vos résultats afin d’inclure uniquement les documents possédant ces valeurs d'attribut. Pour affiner les requêtes avec une ou plusieurs de ces clés, transmettez-les à l'objet de requête :

query = search.Query(..., facet_refinements=[refinement_key1, refinement_key2, refinement_key3])

Vous pouvez combiner des améliorations pour un ou plusieurs attributs différents dans la même demande. Tous les raffinements appartenant au même attribut sont joints à un OR. Les raffinements pour différents attributs sont combinés avec AND.

Il est également possible de créer manuellement une clé FacetRefinement personnalisée. Veuillez consulter la documentation de la classe pour plus d'informations.