Mit Attributen suchen

Durch die Suche mit Attributen können Sie Ihren Dokumenten Kategoriedaten anhängen. Beim Suchvorgang wird ein Attribut/Wert-Paar verwendet. Das Attribut "Größe" kann beispielsweise die Werte "klein", "mittel" und "groß" haben.

Durch die Verwendung von Attributen bei der Suche können Sie zusammenfassende Informationen abrufen, die Ihnen bei der Verfeinerung einer Abfrage helfen und eine Aufschlüsselung der Ergebnisse in mehreren Schritten ermöglichen.

Dies ist bei Anwendungen wie Shoppingwebsites nützlich, auf denen Sie eine Reihe von Filtern anbieten möchten, damit Kunden die angezeigten Produkte eingrenzen können.

Die aggregierten Daten für ein Attribut geben Auskunft über die Verteilung seiner Werte. Das Attribut „Größe” kann beispielsweise in zahlreichen Dokumenten Ihrer Ergebnisse auftauchen. Die aggregierten Daten für dieses Attribut können etwa Auskunft darüber geben, dass der Wert „klein” 100-mal, der Wert „mittel” 300-mal und der Wert „groß” 250-mal vorkommt. Jedes Attribut/Wert-Paar stellt eine Teilmenge von Dokumenten im Abfrageergebnis dar. Jedem Paar ist ein Schlüssel zugeordnet, der als Suchfilter bezeichnet wird. Sie können Suchfilter in eine Abfrage aufnehmen, um Dokumente abzurufen, die mit dem Abfragestring übereinstimmen und deren Attributwerte einem oder mehreren Suchfiltern entsprechen.

Bei einer Suche können Sie wählen, welche Attribute erfasst und in den Ergebnissen angezeigt werden sollen. Sie haben auch die Möglichkeit, die Attributerkennung zu aktivieren, sodass automatisch die am häufigsten in Ihren Dokumenten vorkommenden Attribute ausgewählt werden.

Einem Dokument Attribute hinzufügen

Weisen Sie einem Dokument Attribute zu, bevor Sie es einem Index hinzufügen. Sie sollten dies dann tun, wenn Sie die Felder des Dokuments angeben:

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);
  }
}

Ein Attribut ähnelt einem Dokumentfeld, es hat einen Namen und einen Wert.

Attribute werden nach denselben Regeln wie Dokumentfelder benannt: Es wird zwischen Groß- und Kleinschreibung unterschieden und sie dürfen nur ASCII-Zeichen enthalten. Sie müssen mit einem Buchstaben beginnen und können Buchstaben, Ziffern oder Unterstriche enthalten. Ein Name darf maximal 500 Zeichen lang sein.

Der Wert eines Attributs kann entweder ein atomarer String (maximal 500 Zeichen lang) oder eine Zahl (Gleitkommawert mit doppelter Genauigkeit zwischen -2.147.483.647 und 2.147.483.647) sein.

Sie können einem Attribut in einem Dokument mehrere Werte zuweisen. Fügen Sie zu diesem Zweck das Attribut mit demselben Namen und Typ mehrmals hinzu und verwenden Sie dabei jedes Mal einen anderen Wert.

Ein Attribut kann eine unbegrenzte Anzahl von Werten haben. Auch die Anzahl der Attribute, die Sie einem Dokument hinzufügen können, oder die Anzahl der Attribute mit eindeutigen Namen in einem Index ist unbegrenzt.

Beachten Sie, dass ein Attribut bei jeder Verwendung entweder einen atomaren oder einen numerischen Wert annehmen kann. Ein Attribut namens „Größe” kann an ein Dokument mit dem Stringwert „klein” und an ein anderes Dokument mit dem numerischen Wert „8” angehängt werden. Dasselbe Attribut kann sogar mit beiden Werttypen mehrmals in demselben Dokument auftauchen. Es wird jedoch davon abgeraten, für ein Attribut sowohl atomare als auch numerische Werte zu verwenden.

Obgleich ein Attribut, das Sie einem Dokument hinzufügen, einen bestimmten Typ hat, werden in den Suchergebnissen alle Werte des Attributs zusammengefasst. Zum Beispiel könnten die Ergebnisse für das Attribut „Größe” zeigen, dass es 100 Instanzen des Werts „klein”, 150 Instanzen des Werts „mittel” und 135 Instanzen von numerischen Werten im Bereich [4, 8) gab. Die genauen numerischen Werte und die Häufigkeit ihrer Verteilung werden nicht angezeigt.

Wenn Sie ein Dokument mithilfe einer Abfrage abrufen, können Sie nicht direkt auf seine Attribute und Werte zugreifen. Sie müssen angeben, dass mit Ihrer Abfrage Attributinformationen zurückgegeben werden. Dies wird im nächsten Abschnitt erläutert.

Attributinformationen mit einer Attributsuche abrufen

Sie können angeben, dass das Backend für die Suche die am häufigsten verwendeten Attribute für Sie ermitteln soll. Dies wird als „automatische Attributerkennung” bezeichnet. Sie können Attributinformationen auch explizit abrufen, indem Sie ein Attribut nach Name oder nach Name und Wert auswählen. Sie können alle drei Arten des Attributabrufs in einer einzigen Abfrage mischen und abgleichen.

Die Abfrage von Attributinformationen hat keinen Einfluss darauf, welche Dokumente durch die Abfrage zurückgegeben werden. Sie kann jedoch die Leistung beeinträchtigen. Sie erzielen durch eine Suche mit Attributen mit der Standardtiefe 1.000 denselben Effekt, wie wenn Sie als Scorer-Limit für Sortieroptionen 1.000 festlegen.

Automatische Attributerkennung

Bei der automatischen Attributerkennung werden die Attribute gesucht, die in der Zusammenfassung Ihrer Dokumente am häufigsten angezeigt werden. Angenommen, die zu Ihrer Abfrage passenden Dokumente enthalten das Attribut „Farbe”, das fünfmal mit dem Wert „rot”, fünfmal mit dem Wert „weiß” und fünfmal mit dem Wert „blau” vorkommt. Dieses Attribut kommt insgesamt 15-mal vor. Für die Erkennung würde es höher eingestuft werden als das Attribut „Farbton”, das in denselben übereinstimmenden Dokumenten sechsmal mit dem Wert „dunkel” und siebenmal mit dem Wert „hell” auftaucht.

Sie müssen die Attributerkennung aktivieren, indem Sie sie in Ihrer Abfrage festlegen:

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());
        }
      }
  }
}

Wenn Sie Attribute durch Erkennung abrufen, werden standardmäßig nur die zehn am häufigsten vorkommenden Werte eines Attributs zurückgegeben. Dieses Limit kann auf bis zu 100 erhöht werden. Verwenden Sie hierfür FacetOptions.Builder.setDiscoveryValueLimit().

Die automatische Attributerkennung dient nicht dazu, alle möglichen Attribute und deren Werte zurückzugeben. Welche Attribute durch Erkennung zurückgegeben werden, kann von Ausführung zu Ausführung variieren. Wenn Sie nach bestimmten Attributen suchen möchten, verwenden Sie in der Abfrage den Parameter return_facets.

Stringwerte werden einzeln zurückgegeben. Die numerischen Werte eines erkannten Attributs werden innerhalb eines einzelnen Bereichs [min max) zurückgegeben. Sie können diesen Bereich überprüfen und für eine spätere Abfrage einen kleineren Teilbereich erstellen.

Facetten nach Name auswählen

Um Informationen zu einem Attribut nur nach dessen Namen abzurufen, fügen Sie Ihrer Abfrage das Objekt ReturnFacet mit dem Namen des Attributs hinzu:

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());
        }
      }
  }
}

Wenn Sie Attribute nach ihrem Namen abrufen, werden standardmäßig nur deren zehn am häufigsten auftretende Werte zurückgegeben. Dieses Limit kann auf bis zu 20 erhöht werden. Verwenden Sie hierfür FacetOptions.Builder.setDiscoveryValueLimit().

Attribute nach Name und Wert auswählen

Um ein Attribut mit einem bestimmten Wert abzurufen, fügen Sie ein ReturnFacet-Objekt hinzu, das eine FacetRequest enthält:

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());
            }
        }
    }
}

Die Werte in einer einzelnen FacetRequest müssen alle vom gleichen Typ sein, entweder eine Liste mit Stringwerten oder, bei Zahlen, eine Liste von FacetRanges, also Intervalle, die links geschlossen (Start) und rechts offen (Ende) sind. Wenn das Attribut sowohl String- als auch Zahlenwerte enthält, fügen Sie jeweils separate FacetRequest-Objekte hinzu.

Optionen

Sie können die Facettensuche steuern, indem Sie dem Query-Aufruf einen Parameter FacetOptions hinzufügen. Für diesen Parameter wird eine einzelne Instanz von FacetOptions verwendet. Mit diesem Parameter können Sie das Standardverhalten der Suche mit Attributen überschreiben.

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");
Parameter Beschreibung Standard
DiscoveryLimit Anzahl der erkannten Facetten, wenn die Facettenerkennung aktiviert ist. Wenn 0, wird die Facettenerkennung deaktiviert. 10
DiscoveryValueLimit Anzahl der Werte, die für jedes der am häufigsten erkannten Attribute zurückgegeben werden. 10
Depth Mindestanzahl von Dokumenten in Abfrageergebnissen, die zum Erfassen von Attributinformationen ausgewertet werden. 1000

Die Option Depth gilt für alle drei Arten der Attributaggregation: nach Name, Name und Wert und automatischer Erkennung. Die anderen Optionen dienen nur der automatischen Erkennung.

Beachten Sie, dass die Attributtiefe normalerweise viel größer als das Abfragelimit ist. Die Attributergebnisse werden mindestens bis zur Tiefe der Dokumente berechnet. Wenn Sie für die Sortieroptionen ein höheres Scoring-Limit als die Tiefe festgelegt haben, wird stattdessen das Scoring-Limit verwendet.

Attributergebnisse abrufen

Wenn Sie in einer Abfrage Attributsuchparameter verwenden, enthalten die aggregierten Attributinformationen auch das Abfrageergebnis selbst.

Eine Abfrage enthält eine Liste mit FacetResult. In der Liste wird für jedes Attribut, das in einem mit Ihrer Abfrage übereinstimmenden Dokument enthalten ist, ein Ergebnis angezeigt. Sie erhalten für jedes Ergebnis Folgendes:

  • Den Attributnamen
  • Eine Liste der häufigsten Werte für das Attribut. Zu jedem Wert wird die ungefähre Häufigkeit angezeigt, mit der er aufgetreten ist, sowie ein Suchfilterschlüssel, mit dem Sie die mit der Abfrage und dem Attributwert übereinstimmenden Dokumente abrufen können.

Beachten Sie, dass die Werteliste den String und die numerischen Werte eines Attributs enthält. Bei automatischer Erkennung des Attributs werden dessen numerische Werte als ein Intervall [min max) zurückgegeben. Wenn Sie explizit ein numerisches Attribut mit einem oder mehreren Bereichen abgefragt haben, enthält die Liste für jeden Bereich ein am Anfang geschlossenes und am Ende offenes Intervall [Anfang Ende).

Die Liste der Attributwerte enthält möglicherweise nicht alle in Ihren Dokumenten gefundenen Werte. Es hängt von den Abfrageoptionen ab, wie viele Dokumente untersucht und wie viele Werte zurückgegeben werden.

Die zusammengefassten Informationen zu jedem Attribut finden Sie in den Suchergebnissen:

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

Bei einer Abfrage können beispielsweise Dokumente zurückgegeben werden, die das Attribut "Größe" mit Stringwerten und numerischen Werten enthalten. Das FacetResult für diese Facette wird folgendermaßen aufgebaut:

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 wird aus einem Facettenwert konstruiert. Numerische Werte werden als String zurückgegeben, der einen Bereich darstellt.

refinement_key ist ein sicherer Web-/URL-String, mit dem sich bei einer späteren Abfrage die Dokumente abrufen lassen, die dem Attributnamen und -wert des Ergebnisses entsprechen.

Mit Attributen Abfragen verfeinern/filtern

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

Sie können innerhalb derselben Abfrage Suchfilter für ein oder mehrere Attribute kombinieren. Alle Suchfilter eines Attributs werden mit OR verknüpft. Suchfilter für unterschiedliche Attribute werden mit AND verknüpft.

Ein benutzerdefinierter FacetRefinement-Schlüssel kann auch manuell erstellt werden. Weitere Informationen finden Sie in der Dokumentation zu Klassen.