Ricerca con facet

La ricerca per facet ti consente di collegare informazioni categoriche ai tuoi documenti. Un aspetto è una coppia attributo/valore. Ad esempio, il facet denominato "taglia" potrebbe avere i valori "small", "medium" e "large".

Utilizzando i facet con la ricerca, puoi recuperare informazioni di riepilogo che perfezionare una query e visualizzare in dettaglio nei risultati in una serie di passaggi.

Questa opzione è utile per applicazioni come i siti di shopping, in cui intendi offrire ai clienti un insieme di filtri per restringere i prodotti che vogliono visualizzare.

I dati aggregati di un facet mostrano come vengono distribuiti i valori di un facet. Ad esempio, il livello "dimensione" potrebbe essere visualizzato in molti dei documenti nel set di risultati. I dati aggregati per questa frazione potrebbero mostrare che il valore "piccolo" è apparso 100 volte, "medio" 300 volte e "grande" 250 volte. Ogni coppia espressione/valore rappresenta un sottoinsieme di documenti nel risultato della query. A ogni coppia è associata una chiave, chiamata affinamento. Puoi includere perfezionamenti in una query per recuperare i documenti corrispondenti alla stringa di query e con i valori delle sfaccettature corrispondenti a uno o più perfezionamenti.

Quando esegui una ricerca, puoi scegliere quali facet raccogliere e mostrare con i risultati o attivare il rilevamento dei facet seleziona i facet che compaiono più spesso nei tuoi documenti.

Aggiunta di facet a un documento

Aggiungi facet a un documento prima di aggiungere il documento a un indice. Esegui questa operazione nel momento in cui specifichi i campi del documento:

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 facet è simile a un campo documento; ha un nome e assume un valore.

I nomi delle sfaccettature seguono le stesse regole dei campi del documento: sono sensibili alle maiuscole e possono contenere solo caratteri ASCII. Devono iniziare con una lettera e possono contenere lettere, cifre o trattini bassi. Un nome non può contenere più di 500 caratteri.

Il valore di un facet può essere una stringa atomica (non più lunga di 500 caratteri) o un numero (un valore in virgola mobile a doppia precisione compreso tra -2.147.483.647 e 2.147.483.647).

Puoi assegnare più valori a una frazione in un documento aggiungendo una frazione con lo stesso nome e tipo più volte, utilizzando ogni volta un valore diverso.

Non esiste un limite al numero di valori che un facet può avere. Inoltre, non c'è limite al numero di facet che puoi aggiungere a un documento o al numero di facet con nomi univoci in un indice.

Tieni presente che ogni volta che utilizzi una frazione, questa può assumere un valore atomico o numerico. Un aspetto con il nome "size" può essere associato a un documento con il valore di stringa "small" e a un altro documento con il valore numerico 8. Infatti, la stessa espressione può essere visualizzata più volte nello stesso documento con entrambi i tipi di valori. Sconsigliamo di utilizzare valori atom e numerici per lo stesso facet, anche se è consentito.

Mentre un facet ha un tipo specifico quando lo aggiungi a un documento, la ricerca i risultati raccolgono tutti i valori corrispondenti. Ad esempio, i risultati per la dimensione "dimensione" potrebbero mostrare che sono state registrate 100 istanze del valore "piccolo", 150 istanze di "medio" e 135 istanze di valori numerici nell'intervallo [4, 8). I valori numerici esatti e la loro distribuzione di frequenza non vengono mostrati.

Quando recuperi un documento utilizzando una query, non puoi accedere direttamente alle sue sfacette e ai suoi valori. Devi richiedere che le informazioni sui facet vengano restituite con query, come spiegato nella sezione successiva.

Utilizzare una ricerca con facet per recuperare le informazioni sui facet

Puoi chiedere al backend di ricerca di scoprire i facet utilizzati più di frequente per te, chiamati il rilevamento automatico dei facet. Puoi anche recuperare le informazioni sulle sfaccettature in modo esplicito selezionando una sfacetta per nome o per nome e valore. Puoi combinare tutti e tre i tipi di recupero delle sfaccettature in una singola query.

La richiesta di informazioni sui vari aspetti non influisce sui documenti restituiti dalla query. Può influire sulle prestazioni. L'esecuzione di una ricerca facet con profondità predefinita di 1000 ha lo stesso effetto dell'impostazione del limite del punteggio delle opzioni di ordinamento su 1000.

Rilevamento automatico delle sfaccettature

La funzionalità di rilevamento automatico delle sfaccettature cerca le sfaccettature che compaiono più spesso in aggregato nei tuoi documenti. Ad esempio, supponiamo che i documenti corrispondenti la query include un "colore" facet che appare 5 volte con il valore "red", 5 volte con il valore "white" e cinque volte con il colore "blu". Questa espressione ha un conteggio totale di 15. Ai fini della scoperta, avrà un ranking più alto rispetto a un'altra sfumatura "shade" che compare negli stessi documenti corrispondenti 6 volte con il valore "dark" e 7 volte con il valore "light".

Devi attivare la scoperta delle sfaccettature impostandola nella query:

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

Quando recuperi i facet per rilevamento, per impostazione predefinita vengono restituiti solo i 10 valori più frequenti per un facet. Puoi aumentare questo limite fino a 100 utilizzando FacetOptions.Builder.setDiscoveryValueLimit().

Tieni presente che la scoperta automatica delle sfaccettature non è pensata per restituire tutte le sfaccettature possibili e i relativi valori. I facet restituiti dalla scoperta possono variare da una corsa all'altra. Se è preferibile un insieme fisso di facet. Utilizza un parametro return_facets nella query.

I valori di stringa verranno restituiti singolarmente. I valori numerici di un facet scoperto vengono restituiti in un singolo intervallo [min max]. Puoi esaminare questo intervallo e creare un sottointervallo più piccolo per una query successiva.

Selezione dei facet per nome

Per recuperare le informazioni su un aspetto solo dal nome, aggiungi un oggetto ReturnFacet alla query specificando il nome dell'aspetto:

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

Quando recuperi i facet per nome, per impostazione predefinita vengono restituiti solo i 10 valori più frequenti per un facet. Puoi aumentare questo limite fino a 20 utilizzando FacetOptions.Builder.setDiscoveryValueLimit().

Selezionare i facet per nome e valore

Per recuperare una frazione con un determinato valore, aggiungi un oggetto ReturnFacet che includa un 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());
            }
        }
    }
}

I valori di un singolo FacetRequest devono essere tutti dello stesso tipo, ovvero un elenco di valori di stringa o, per i numeri, un elenco di FacetRanges, ovvero intervalli chiusi a sinistra (inizio) e aperti a destra (fine). Se il tuo Facet ha una combinazione di valori di stringa e numeri, aggiungi FacetRequest separati per ciascuno.

Opzioni

Puoi controllare la ricerca filtrata aggiungendo un parametro FacetOptions a una chiamata Query. Questo parametro utilizza una singola istanza di FacetOptions. Utilizza questo parametro per ignorare il comportamento predefinito della ricerca con facet.

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");
Parametro Descrizione Predefinito
DiscoveryLimit Numero di facet da scoprire se la scoperta delle facet è attivata. Se è pari a 0, gli aspetti di scoperta verranno disattivati. 10
DiscoveryValueLimit Numero di valori da restituire per ciascuno dei principali facet scoperti. 10
Depth Il numero minimo di documenti da valutare nei risultati della query per raccogliere informazioni sui facet. 1000

L'opzione Depth si applica a tutti e tre i tipi di aggregazione dei facet: per nome, nome e valore e rilevamento automatico. Le altre opzioni sono solo per il rilevamento automatico.

Tieni presente che la profondità dei facet di solito è molto superiore al limite delle query. I risultati dei componenti vengono calcolati almeno fino al numero di documenti di profondità. Se hai impostato un limite di punteggio per le opzioni di ordinamento superiore alla profondità, verrà utilizzato il limite di punteggio.

Recupero dei risultati dei facet

Quando utilizzi parametri di ricerca facet in una query, le informazioni aggregate sui facet vengono fornite con il risultato della query stesso.

Una query avrà un elenco di FacetResult. Nell'elenco ci sarà un risultato per ogni facet visualizzate in un documento corrispondente alla tua query. Per ogni risultato, vedrai:

  • Il nome del facet
  • Un elenco dei valori più frequenti per il facet. Per ogni valore esiste una un conteggio approssimativo di quante volte è stato visualizzato e una chiave di perfezionamento che può da utilizzare per recuperare i documenti che corrispondono a questa query e al valore del facet.

Tieni presente che l'elenco dei valori includerà i valori numerici e di stringa di una frazione. Se il primo livello è stato rilevato automaticamente, i relativi valori numerici vengono restituiti come singolo intervallo [min max). Se hai richiesto esplicitamente una frazione numerica con uno o più intervalli nella query, l'elenco conterrà un intervallo chiuso-aperto [inizio fine) per ogni intervallo.

L'elenco dei valori dei facet potrebbe non includere tutti i valori trovati nei documenti, poiché la query determinano il numero di documenti da esaminare e di valori da restituire.

Le informazioni aggregate per ogni facet possono essere lette dai risultati di ricerca:

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

Ad esempio, una query potrebbe aver trovato documenti che includevano un facet "dimensioni" con valori di stringa e valori numerici. FacetResult per questa espressione verrà costruito come segue:

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 viene creato a partire da un valore del facet. I valori numerici vengono restituiti come "stringato" di un intervallo.

refinement_key è una stringa sicura per l'URL web/web che può essere utilizzata in una query successiva per recuperare i documenti che corrispondono al nome e al valore del facet di quel risultato.

Utilizzare i facet per perfezionare/filtrare una query

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

Puoi combinare i perfezionamenti per una o più sfaccettature diverse nella stessa richiesta. Tutti i perfezionamenti appartenenti alla stessa espressione vengono uniti con un operatore OR. I perfezionamenti per espressioni diverse vengono combinati con l'operatore AND.

È anche possibile creare manualmente una chiave FacetRefinement personalizzata. Per ulteriori informazioni, consulta la documentazione della classe.