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. Effectuez cette démarche au moment de spécifier les champs du document :

package app

import (
    "appengine"
    "appengine/search"
    "net/http"
)

type ComputerDoc struct {
    Name      search.Atom
    Type      search.Atom `search:",facet"`
    RAMSizeGB float64     `search:",facet"`
}

func handlePut(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    index, err := search.Open("products")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    _, err = index.Put(c, "doc1", &ComputerDoc{
        Name:      "x86",
        Type:      "computer",
        RAMSizeGB: 8.0,
    })
    // Handle err and write HTTP response.
}

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 :

func handleSearch(w http.ResponseWriter, r *http.Request) {
    index, err := search.Open("products")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    it := index.Search(c, "name:x86", &search.SearchOptions{
        Facets: {
            search.AutoFacetDiscovery(0, 0),
        },
    })
    facets, err := it.Facets()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    for _, results := range facets {
        for i, facet := range result {
            // The facet results are grouped by facet name.
            // Print the name of each group before its values.
            if i == 0 {
                fmt.Fprintf(w, "Facet %s:\n", facet.Name)
            }
            fmt.Fprintf(w, "    %v: count=%d", facet.Value, facet.Count)
        }
    }
}

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 définissant le premier paramètre sur AutoFacetDiscovery.

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 récupérer des informations sur un attribut en n'indiquant que son nom, ajoutez un FacetDiscovery aux options de recherche de votre requête, en indiquant le nom de l'attribut :

it := index.Search(c, "name:x86", &search.SearchOptions{
    Facets: {
        FacetDiscovery("Type"),
        FacetDiscovery("RAMSizeGB"),
    },
})

Lorsque vous recherchez des attributs par leur nom, seules les 10 valeurs les plus fréquentes d'un attribut sont renvoyées.

Sélectionner des attributs par nom et par valeur

Pour obtenir des informations concernant uniquement certaines valeurs d'un attribut, ajoutez une option FacetDiscovery en incluant le nom de l'attribut et les valeurs qui vous intéressent.

it := index.Search(c, "name:x86", &search.SearchOptions{
    Facets: {
        // Fetch the "Type" facet with Values "computer" and "printer"
        FacetDiscovery("Type",
            search.Atom("computer"),
            search.Atom("printer"),
        ),
        // Fetch the "RAMSizeGB" facet with values in the ranges [0, 4), [4, 8), and [8, max]
        FacetDiscovery("RAMSizeGB",
            search.Range{Start: 0, End: 4},
            search.Range{Start: 4, End: 8},
            search.AtLeast(8),
        ),
    },
})

Les valeurs d'une même option FacetDiscovery doivent toutes être du même type. Il peut soit s'agir d'une liste de valeurs search.Atom, soit, pour les nombres, d'une liste de search.Range, qui sont des intervalles fermés à gauche (début) et ouverts à droite (fin). Si votre attribut combine des valeurs de chaîne et numériques, ajoutez des options FacetDisovery distinctes pour chacune d'elles.

Options

Vous pouvez contrôler le nombre minimal de documents à évaluer pour collecter des informations sur les attributs en ajoutant l'option FacetDocumentDepth dans le fichier SearchOptions de votre requête. Si cette option n'est pas spécifiée, la valeur par défaut de la profondeur est de 1 000.

Sachez que la profondeur d'attribut est généralement bien plus élevée que la limite de requêtes. 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.

L'élément Iterator de la recherche dispose d'une méthode Facets qui renvoie les informations agrégées sur les attributs sous la forme [][]FacetResult. Les résultats sont organisés de façon à fournir un lot de résultats pour chaque attribut qui est apparu dans un document correspondant à votre requête. Pour chaque résultat, vous obtenez les informations suivantes :

  • Le nom de l'attribut
  • Une valeur pour l'attribut, issue de la liste des valeurs les plus fréquentes
  • Un nombre approximatif d'occurrences de cette valeur

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 comprendre toutes les valeurs trouvées dans vos documents, car les options de requête déterminent le nombre de documents à examiner ainsi que le nombre de valeurs à renvoyer.

Les informations agrégées pour chaque attribut peuvent être consultées depuis l'itérateur :

it := index.Search(...)
facets, err := it.Facets()  // And check err != nil.
for _, results := range facets {
    for _, facet := range results {
        ...
    }
}

Par exemple, une requête peut avoir trouvé des documents contenant l'attribut "size" (taille) avec les valeurs de chaîne et les valeurs numériques. Les résultats pour cet attribut apparaîtront comme décrit ci-dessous :

[][]search.FacetResult{
    {
        {Name: "size", Value: search.Range{Start: 8, End: 10}, Count: 22},
        {Name: "size", Value: search.Atom("small"), Count: 100},
        {Name: "size", Value: search.Atom("medium"), Count: 300},
        {Name: "size", Value: search.Atom("large"), Count: 250},
    },
}

Utiliser des attributs pour affiner/filtrer une requête

Chaque FacetResult peut être utilisé pour affiner davantage vos résultats afin de n'inclure que les documents ayant ces valeurs d'attribut. Pour affiner des requêtes avec une ou plusieurs de ces clés, transmettez-les en tant qu'options de recherche :

it := index.Search(c, "...", &search.SearchOptions{
    Refinements: []search.Facet{
        facetResult1.Facet,
        facetResult2.Facet,
    },
})

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 un Facet personnalisé à utiliser comme filtre. Consultez la documentation de référence pour en savoir plus.