Penelusuran dengan Faset

Penelusuran dengan faset memungkinan Anda dapat melampirkan informasi berkategori ke dokumen. Faset merupakan pasangan atribut/nilai. Misalnya, faset bernama "size" dapat memiliki nilai "small", "medium", dan "large".

Dengan menggunakan faset pada penelusuran, Anda dapat mengambil informasi ringkasan untuk membantu menyaring kueri dan "melihat perincian" hasil dalam serangkaian langkah.

Hal ini berguna untuk aplikasi seperti situs belanja, tempat Anda ingin menawarkan serangkaian filter bagi pelanggan untuk mempersempit produk yang ingin mereka lihat.

Data gabungan untuk suatu faset menunjukkan kepada Anda bagaimana nilai sebuah faset didistribusikan. Misalnya, faset "size" dapat muncul di banyak dokumen dalam kumpulan hasil. Data gabungan untuk faset tersebut mungkin menunjukkan bahwa nilai "small" muncul 100 kali, "medium" 300 kali, dan "large" 250 kali. Setiap pasangan faset/nilai mewakili sebagian dokumen dalam hasil kueri. Kunci, yang disebut penajaman, dikaitkan dengan setiap pasangan. Anda dapat menyertakan penajaman dalam kueri untuk mengambil dokumen yang cocok dengan string kueri dan yang memiliki nilai faset yang terkait dengan satu atau beberapa penajaman.

Saat melakukan penelusuran, Anda dapat memilih faset yang akan dikumpulkan dan ditampilkan bersama hasilnya, atau Anda dapat mengaktifkan penemuan faset untuk secara otomatis memilih faset yang paling sering muncul dalam dokumen.

Menambahkan faset ke dokumen

Tambahkan faset ke dokumen sebelum menambahkan dokumen ke indeks. Lakukan hal ini bersamaan dengan menentukan kolom dokumen:

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

Faset mirip dengan kolom dokumen; memiliki nama, dan mengambil satu nilai.

Nama faset mengikuti aturan yang sama dengan kolom dokumen: Nama peka huruf besar/kecil dan hanya boleh berisi karakter ASCII. Nama ini harus diawali dengan huruf dan dapat berisi huruf, angka, atau garis bawah. Nama tidak boleh lebih dari 500 karakter.

Nilai faset dapat berupa string atom (maksimal 500 karakter) atau angka (nilai floating point presisi ganda antara -2.147.483.647 dan 2.147.483.647).

Anda dapat menetapkan beberapa nilai ke suatu faset di satu dokumen dengan menambahkan faset yang berisi nama dan jenis yang sama berkali-kali, dengan menggunakan nilai yang berbeda setiap saat.

Tidak ada batasan jumlah nilai yang dapat dimiliki oleh faset. Selain itu, tidak ada batasan jumlah faset yang dapat Anda tambahkan ke dokumen atau jumlah faset yang diberi nama unik dalam indeks.

Perhatikan bahwa setiap kali Anda menggunakan faset, faset dapat mengambil nilai atomik atau numerik. Faset dengan nama "size" dapat dilampirkan ke satu dokumen dengan nilai string "small" dan dokumen lainnya dengan nilai numerik 8. Bahkan, faset yang sama dapat muncul beberapa kali dalam dokumen yang sama dengan kedua jenis nilai. Sebaiknya jangan gunakan nilai atom dan angka untuk faset yang sama meskipun diperbolehkan.

Meskipun faset memiliki jenis tertentu saat Anda menambahkannya ke dokumen, hasil penelusuran mengumpulkan semua nilainya bersama-sama. Misalnya, hasil untuk faset "size" mungkin menunjukkan bahwa ada 100 instance nilai "small", 150 instance "medium", dan 135 instance nilai numerik dalam rentang [4, 8 ). Nilai numerik yang tepat dan distribusi frekuensinya tidak ditampilkan.

Saat mengambil dokumen menggunakan kueri, Anda tidak dapat langsung mengakses faset dan nilainya. Anda harus mengajukan permintaan agar informasi faset ditampilkan dengan kueri, seperti yang dijelaskan di bagian berikutnya.

Menggunakan penelusuran dengan faset untuk mengambil informasi faset

Anda dapat meminta backend penelusuran untuk menemukan faset yang paling sering digunakan. Hal ini disebut penemuan faset otomatis. Anda juga dapat mengambil informasi faset secara eksplisit dengan memilih faset berdasarkan nama, atau berdasarkan nama dan nilai. Anda dapat memadupadankan ketiga jenis pengambilan faset dalam satu kueri.

Meminta informasi faset tidak akan memengaruhi dokumen yang ditampilkan oleh kueri. Hal ini dapat memengaruhi performa. Melakukan penelusuran dengan faset dengan kedalaman default 1000 memiliki efek yang sama dengan menetapkan batas pencetak opsi pengurutan ke 1000.

Penemuan faset otomatis

Penemuan faset otomatis mencari faset yang paling sering muncul dalam agregat di dokumen Anda. Misalnya, dokumen yang cocok dengan kueri Anda berisi faset "color" yang muncul 5 kali dengan nilai "red", 5 kali dengan nilai "white", dan 5 kali dengan warna "blue". Faset ini memiliki jumlah total 15. Untuk tujuan penemuan, maka akan diberi peringkat lebih tinggi daripada faset "shade" lain yang muncul dalam dokumen pencocokan yang sama dengan nilai "dark" sebanyak 6 kali dan nilai "light" 7 kali.

Anda harus mengaktifkan penemuan faset dengan menyetelnya di Kueri Anda:

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

Ketika Anda mengambil faset berdasarkan penemuan, secara default hanya 10 nilai yang paling sering muncul di sebuah faset yang akan ditampilkan. Anda dapat meningkatkan batas ini hingga 100 menggunakan FacetOptions.Builder.setDiscoveryValueLimit().

Perlu diperhatikan bahwa penemuan faset otomatis tidak dimaksudkan untuk menampilkan semua kemungkinan faset dan nilainya. Faset yang ditampilkan dari penemuan dapat bervariasi dari tiap dilakukan penemuan. Jika menginginkan kumpulan faset tetap, gunakan parameter return_facets pada kueri Anda.

Nilai string akan ditampilkan satu per satu. Nilai numerik dari faset yang ditemukan ditampilkan dalam satu rentang [min maks). Anda dapat memeriksa rentang ini dan membuat subrentang yang lebih kecil untuk kueri berikutnya.

Memilih faset berdasarkan nama

Untuk mengambil informasi tentang faset berdasarkan namanya saja, tambahkan objek ReturnFacet ke kueri Anda, dengan menentukan nama faset:

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

Ketika Anda mengambil facet berdasarkan nama, secara default hanya 10 nilai yang paling sering muncul di sebuah faset yang akan ditampilkan. Anda dapat meningkatkan batas ini hingga 20 menggunakan FacetOptions.Builder.setDiscoveryValueLimit().

Memilih faset berdasarkan nama dan nilai

Untuk mengambil faset dengan nilai tertentu, tambahkan objek ReturnFacet yang menyertakan 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());
            }
        }
    }
}

Semua nilai dalam satu FacetRequest harus memiliki jenis yang sama, baik berupa daftar nilai string maupun, untuk angka, daftar FacetRanges yang merupakan interval yang ditutup di sebelah kiri (mulai), dan terbuka di sebelah kanan (akhir). Jika faset Anda memiliki campuran nilai string dan angka, tambahkan FacetRequests terpisah untuk masing-masing

Opsi

Anda dapat mengontrol penelusuran berfaset dengan menambahkan parameter FacetOptions ke panggilan Kueri. Parameter ini menggunakan satu instance FacetOptions. Gunakan parameter ini untuk mengganti perilaku default penelusuran dengan faset.

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 Deskripsi Default
DiscoveryLimit Jumlah faset yang akan ditemukan jika penemuan faset diaktifkan. Jika 0, penemuan faset akan dinonaktifkan. 10
DiscoveryValueLimit Jumlah nilai yang akan ditampilkan untuk setiap faset yang paling sering ditemukan. 10
Depth Jumlah minimum dokumen dalam hasil kueri yang akan dievaluasi untuk mengumpulkan informasi faset. 1000

Opsi Depth berlaku untuk ketiga jenis gabungan faset: berdasarkan nama, nama dan nilai, serta penemuan otomatis. Opsi lainnya hanya untuk penemuan otomatis.

Perhatikan bahwa kedalaman faset biasanya jauh lebih besar dari batas kueri. Hasil faset dihitung berdasarkan setidaknya jumlah kedalaman dokumen. Jika Anda telah menetapkan batas penskoran opsi pengurutan lebih tinggi dari kedalaman, batas penskoran akan digunakan.

Mengambil hasil faset

Saat Anda menggunakan parameter penelusuran dengan faset dalam kueri, informasi faset yang digabungkan akan muncul bersama hasil kueri itu sendiri.

Kueri akan memiliki daftar FacetResult. Akan ada satu hasil dalam daftar untuk setiap faset yang muncul dalam dokumen yang cocok dengan kueri Anda. Untuk setiap hasil, Anda akan mendapatkan:

  • Nama facet
  • Daftar nilai yang paling sering untuk faset. Untuk setiap nilai, terdapat perkiraan jumlah frekuensi munculnya nilai tersebut, dan kunci penajaman yang dapat digunakan untuk mengambil dokumen yang cocok dengan kueri dan nilai faset ini.

Perhatikan bahwa daftar nilai akan menyertakan string dan nilai numerik faset. Jika faset ditemukan secara otomatis, nilai numeriknya akan ditampilkan sebagai satu interval [min maks). Jika Anda secara eksplisit meminta faset numerik dengan satu atau beberapa rentang dalam kueri, daftar akan berisi satu interval tertutup-terbuka [awal akhir) untuk setiap rentang.

Daftar nilai faset mungkin tidak menyertakan semua nilai yang ditemukan dalam dokumen Anda, karena opsi kueri menentukan berapa banyak dokumen yang akan diperiksa dan berapa banyak nilai yang akan ditampilkan.

Informasi gabungan untuk setiap faset dapat dibaca dari hasil penelusuran:

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

Misalnya, suatu kueri dapat menemukan dokumen yang menyertakan faset "size" dengan nilai string dan nilai numerik. FacetResult untuk faset ini akan dikonstruksi seperti ini:

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 dikonstruksi dari nilai facet. Nilai numerik ditampilkan sebagai representasi "string" dari sebuah rentang.

refinement_key adalah string aman web/url yang dapat digunakan dalam kueri berikutnya untuk mengambil dokumen yang cocok dengan nama dan nilai faset hasil tersebut.

Menggunakan faset untuk menyaring/memfilter kueri

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

Anda dapat menggabungkan penajaman untuk satu atau beberapa faset yang berbeda dalam permintaan yang sama. Semua penajaman yang dimiliki faset yang sama digabungkan dengan OR. Penajaman untuk faset yang berbeda digabungkan dengan AND.

Anda juga dapat membuat kunci FacetRefinement kustom secara manual. Lihat dokumentasi kelas untuk informasi selengkapnya.