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ée "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 com.google.test.facet;

import java.io.IOException;
import javax.servlet.http.*;
import com.google.appengine.api.search.*;

public class FacetsearchjavaServlet extends HttpServlet {
  public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    Document doc1 = Document.newBuilder()
      .setId("doc1")
      .addField(Field.newBuilder().setName("name").setAtom("x86"))
      .addFacet(Facet.withAtom("type", "computer"))
      .addFacet(Facet.withNumber("ram_size_gb", 8.0))
      .build();
    IndexSpec indexSpec = IndexSpec.newBuilder().setName("products").build();
      Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);
    index.put(doc1);
  }
}

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 attributs 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ées 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 attaché à 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ées, 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 :

package com.google.test.facet;

import java.io.IOException;
import javax.servlet.http.*;
import com.google.appengine.api.search.*;

public class FacetsearchjavaServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    IndexSpec indexSpec = IndexSpec.newBuilder().setName("products").build();
      Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);
      Results<ScoredDocument> result = index.search(
          Query.newBuilder().setEnableFacetDiscovery(true) // enable discovery
          .build("name:x86"));
      for(FacetResult facetResult : result.getFacets()) {
        resp.getWriter().printf("Facet %s:\n", facetResult.getName());
        for (FacetResultValue facetValue : facetResult.getValues()) {
          resp.getWriter().printf("   %s: Count=%s, RefinementKey=%s\n",
              facetValue.getLabel(),
              facetValue.getCount(),
              facetValue.getRefinementToken());
        }
      }
  }
}

Lorsque vous recherchez des attributs grâce à la détection, seules les 10 valeurs les plus fréquentes d'un attribut sont renvoyées par défaut. Vous pouvez augmenter cette limite jusqu'à 100 en utilisant FacetOptions.Builder.setDiscoveryValueLimit().

Sachez que la détection 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 en n'indiquant que son nom, ajoutez un objet ReturnFacet à la requête, en spécifiant le nom de l'attribut :

package com.google.test.facet;

import java.io.IOException;
import javax.servlet.http.*;
import com.google.appengine.api.search.*;

public class FacetsearchjavaServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    IndexSpec indexSpec = IndexSpec.newBuilder().setName("products").build();
      Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);
      Results<ScoredDocument> result = index.search(Query.newBuilder()
        .addReturnFacet("type")
        .addReturnFacet("ram_size_gb")
        .build("name:x86"));
      for(FacetResult facetResult : result.getFacets()) {
        resp.getWriter().printf("Facet %s:\n", facetResult.getName());
        for (FacetResultValue facetValue : facetResult.getValues()) {
          resp.getWriter().printf("   %s: Count=%s, RefinementKey=%s\n",
              facetValue.getLabel(),
              facetValue.getCount(),
              facetValue.getRefinementToken());
        }
      }
  }
}

Lorsque vous recherchez des attributs par leur nom, seules les 10 valeurs les plus fréquentes d'un attribut sont renvoyées par défaut. Vous pouvez augmenter cette limite jusqu'à 20 en utilisant FacetOptions.Builder.setDiscoveryValueLimit().

Sélectionner des attributs par nom et par valeur

Pour récupérer un attribut avec une valeur particulière, ajoutez un objet ReturnFacet qui inclut une FacetRequest :

package com.google.test.facet;

import java.io.IOException;
import javax.servlet.http.*;
import com.google.appengine.api.search.*;

public class FacetsearchjavaServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        IndexSpec indexSpec = IndexSpec.newBuilder().setName("products").build();
        Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);
        // Fetch the "type" facet with values "computer and "printer"
        // along with the "ram_size_gb" facet with values in the ranges [0,4), [4, 8), and [8, max]
        Results<ScoredDocument> result = index.search(Query.newBuilder()
            .addReturnFacet(FacetRequest.newBuilder()
                .setName("type")
                .addValueConstraint("computer")
                .addValueConstraint("printer"))
            .addReturnFacet(FacetRequest.newBuilder()
                .setName("ram_size_gb")
                .addRange(FacetRange.withEnd(4.0))
                .addRange(FacetRange.withStartEnd(4.0, 8.0))
                .addRange(FacetRange.withStart(8.0)))
            .build("name:x86"));
        for(FacetResult facetResult : result.getFacets()) {
            resp.getWriter().printf("Facet %s:\n", facetResult.getName());
            for (FacetResultValue facetValue : facetResult.getValues()) {
                resp.getWriter().printf("   %s: Count=%s, RefinementKey=%s\n",
                        facetValue.getLabel(),
                        facetValue.getCount(),
                        facetValue.getRefinementToken());
            }
        }
    }
}

Les valeurs d'une même FacetRequest doivent toutes avoir le même type. Il peut s'agir soit d'une liste de valeurs de chaîne, soit, pour les nombres, d'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 attribut en ajoutant un paramètre FacetOptions à un appel de requête. Ce paramètre nécessite une seule instance de FacetOptions. Utilisez ce paramètre pour remplacer le comportement par défaut de la recherche par attributs.

Results<ScoredDocument> results = index.search(Query.newBuilder()
  .addReturnFacet(FacetRequest.newBuilder()
    .setName("type")
    .addValueConstraint("computer")
    .addValueConstraint("printer"))
  .addReturnFacet(FacetRequest.newBuilder()
    .setName("ram_size_gb")
    .addRange(FacetRange.withEnd(4.0))
    .addRange(FacetRange.withStartEnd(4.0, 8.0))
    .addRange(FacetRange.withStart(8.0)))
  .setFacetOptions(FacetOptions.newBuilder()
    .setDiscoveryLimit(5)
    .setDiscoveryValueLimit(10)
    .setDepth(6000).build());
  .build(“some_query”);
Réglage Description Valeur par défaut
DiscoveryLimit Nombre d'attributs à détecter si la détection d'attributs est activée. S'il n'y en a aucun, la détection d'attributs est désactivée. 10
DiscoveryValueLimit 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 s'appliquent à 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, un nombre de fois où il apparaît et une clé de raffinement pouvant être utilisée pour extraire les documents correspondant à cette requête et à la valeur de l'attribut.

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) 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 :

Results<ScoredDocument> results = index.search(...);
for (FacetResult facetInfo : results.getFacets()) {
  ...
}

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 de cet attribut apparaîtra comme décrit ci-dessous :

FacetResult.newBuilder()
        .setName("size")
        .addValue(FacetResultValue.create("[8, 10)", 22, refinement_key)
        .addValue(FacetResultValue.create("small", 100, refinement_key)
        .addValue(FacetResultValue.create("medium", 300, refinement_key)
        .addValue(FacetResultValue.create("large", 250, refinement_key).build());

FacetResultValue.label est construit à partir d'une valeur d'attribut. Les valeurs numériques sont renvoyées sous forme de représentation "concaténée" d'une plage.

La clé refinement_key est une chaîne Web/d'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.

Affiner ou filtrer une requête à l'aide d'attributs

Query query = Query.newBuilder()
  .addFacetRefinementFromToken(refinement_key1)
  .addFacetRefinementFromToken(refinement_key2)
  .addFacetRefinementFromToken(refinement_key3)
  .build(“some_query”);

Vous pouvez combiner des filtres pour un ou plusieurs attributs dans la même requête. Tous les filtres appartenant au même attribut sont reliés par l'opérateur "OR". Les filtres pour des attributs différents sont combinés à l'aide de l'opérateur "AND".

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

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Environnement standard App Engine pour Java