多面向搜尋

多面向 (Facet) 搜尋可讓您將類別資訊附加至文件。Facet 是指屬性/值組合,例如名為「size」的 Facet,可能擁有「small」、「medium」及「large」等值。

使用 Facet 搭配搜尋可擷取匯總資訊,協助您透過一系列步驟修正查詢及「細查」結果。

這非常適合用於購物網站等應用,您可於其中提供一組篩選條件,協助客戶縮小範圍,找出希望瀏覽的產品。

Facet 匯總資料可顯示 Facet 值的分佈情形。舉例來說,「size」Facet 可能出現在結果集的許多文件之中。該 Facet 的匯總資料可能顯示「small」值出現 100 次、「medium」值出現 300 次,以及「large」值出現 250 次。每個 Facet/值組合都代表查詢結果之中的子集。名為「分類標籤」的鍵與各個組合有關。您可在查詢之中納入分類標籤,擷取符合查詢字串,且具有對應至一項以上分類標籤 Facet 值的文件。

您在執行搜尋時,可選擇用於收集的 Facet 以顯示於結果,或是可以啟用 Facet 探索功能,自動選擇最常出現在文件中的 Facet。

新增 Facet 至文件

請在將文件新增至索引之前,先將 Facet 新增至文件。在指定文件欄位時,請同時執行這項作業:

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.
}

Facet 類似於文件欄位,其中具有名稱,並取用一個值。

Facet 名稱遵循與文件欄位相同的規則:名稱會區分大小寫,並且只能包含 ASCII 字元。名稱必須以字母為開頭,可包含字母、數字或底線。名稱長度不得超過 500 個字元。

Facet 值可為不可分割字串 (不得超過 500 個字元) 或數字 (介於 -2,147,483,647 及2,147,483,647 之間的雙精度浮點值)。

您可在單一文件指派多個值至單一 Facet,方法為新增相同名稱的 Facet 並輸入多次,每次使用不同的值。

Facet 可擁有無限數量的值。您可以新增至文件的 Facet 數量,或是索引之中不重複名稱 Facet 的數量,都不會受到限制。

請注意,每次使用 Facet 時,Facet 可能取得不可分割值或數值。名為「size」的 Facet,可利用「small」字串值附加至一份文件,並以數值 8 附加至另一份文件。事實上,相同的 Facet 可利用這兩種值,在同一份文件出現多次。雖然允許使用,但我們不建議針對相同的 Facet 同時使用 atom 及數值。

雖然 Facet 新增至文件時具有特定類型,但搜尋結果會將 Facet 的「所有」值收集在一起。例如,「size」Facet 可能顯示「small」值有 100 個執行個體、「medium」值有 150 個執行個體,以及範圍 [4, 8) 數值的 135 個執行個體。其中並不會顯示確切數值及其頻率分佈。

您使用查詢功能擷取文件時,無法直接存取其 Facet 與值。您必須要求查詢傳回該 Facet 資訊,作法將於下節說明。

使用多面向 (Facet) 搜尋擷取 Facet 資訊

您可要求搜尋後端探索最常用的 Facet;這稱為自動 Facet 探索。您也可以依據名稱或是名稱與值,明確地擷取 Facet 資訊。您可在單一查詢之中混搭使用所有三種 Facet 擷取。

要求 Facet 資訊不會影響查詢傳回的文件,這可能會影響效能。以預設深度 1000 執行多面向 (Facet) 搜尋,與設定排序選項計分器限制為 1000 的效果相同。

自動 Facet 探索

自動 Facet 探索會尋找文件「匯總」之中最常出現的 Facet。舉例來說,假設符合查詢的文件包含「color」Facet,以「red」值出現五次、「white」值出現五次,以及「blue」顏色出現五次。此 Facet 的總數為 15。就探索目的而言,相較於在同一個符合文件之中以「dark」值出現 6 次及以「light」值出現 7 次的 Facet「shade」,「color」Facet 的排名可能較高。

您必須在查詢之中設定,以啟用 Facet 探索功能:

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

您以探索功能擷取 Facet 時,依據預設只會傳回 10 個最常產生的 Facet 值。您可以使用 AutoFacetDiscovery 的第一個參數,將此限制提高至 100。

請注意,自動 Facet 探索未必能傳回所有可能的 Facet 及其值。探索功能傳回的 Facet 值在每次執行之間可能不同。如果需要固定的 Facet 組合,請在查詢使用 return_facets 參數。

字串值將會個別傳回。探索 Facet 的數值將以單一範圍傳回 [最小值 最大值)。您可檢驗此項範圍,並建立更小的子範圍供後續查詢使用。

依名稱選擇 Facet

如需僅依據名稱擷取 Facet 資訊,請將 FacetDiscovery 及 Facet 名稱新增至查詢的搜尋選項:

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

您依據名稱擷取 Facet 時,只會傳回 10 個最常產生的 Facet 值。

依名稱與值選擇 Facet

如需僅擷取特定 Facet 值相關資訊,請新增 FacetDiscovery 及 Facet 名稱與需要關注的值:

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

單一 FacetDiscovery 的值都必須屬於相同類型,可為 search.Atom 值清單或 {0}FacetRanges{/0} 清單 (若為數字),也就是在左側 (開始) 關閉,右側 (結束) 開啟的間隔。search.Range如果 Facet 混合字串值與數值,請針對每個類型的值新增獨立的 FacetDisovery 選項。

選項

您可控制收集 Facet 資訊時評估文件數量的最小值,方法為在 SearchOptions 中新增 FacetDocumentDepth 選項進行查詢。如未指定,此深度預設為 1000。

請注意,該 Facet 深度通常遠高於查詢限制。Facet 結果至少會運算至文件的深度數。如果您讓排序選項計分限制設定高於深度,就會改為使用計分限制。

擷取 Facet 結果

您在查詢中使用多面向 (Facet) 搜尋參數時,匯總 Facet 資訊會隨著查詢結果本身提供。

搜尋 IteratorFacets 方法,可傳回匯總的切面資訊,格式為 [][]FacetResult。系統會將結果分門別類,每個 Facet 都會顯示一個切片,而這些 Facet 出現在符合查詢的文件中。您可以在各項結果中獲得下列資訊:

  • Facet 名稱
  • 最常見值清單中的一個 Facet 值
  • 值出現次數的近似計數

請注意,值清單包含 Facet 字串值「及」數字值。若 Facet 為自動探索,其數值將以單一間隔 [最小值 最大值) 傳回。若您在查詢之中明確要求一個或多個範圍的數值 Facet,清單將包含各個範圍的關閉開啟間隔 [開始 結束)。

Facet 值清單可能並未包含在文件發現的所有值,因為查詢選項會判定要檢驗多少文件,以及傳回多少值。

各個 Facet 的匯總資訊可由疊代器讀取:

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

例如查詢可能發現文件,其中具有含字串值和數值的「size」Facet。此 Facet 結果的結構如下:

[][]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},
    },
}

使用 Facet 修正/篩選查詢

每個 FacetResult 可用來進一步縮小結果範圍,僅顯示含有這些 Facet 值的文件。如需以一個或多個這類鍵修正查詢,請將其傳送做為搜尋選項:

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

您可在同一個要求中,將用於一或多個不同 Facet 的分類標籤加以合併。屬於相同 Facet 的所有分類標籤會以 OR 彙整;屬於不同 Facet 的分類標籤會以 AND 合併。

您也可以手動建立自訂 Facet,做為精緻化使用。詳情請參閱參考資料。