將多面向導覽新增至搜尋應用程式

多面向導覽用於搜尋應用程式中查詢結果的自我導向向下鑽研篩選,其中您的應用程式會提供表單控件,以將搜尋範圍設定為檔群組(例如類別或品牌),而 Azure AI 搜尋會提供數據結構和篩選來支持體驗。

在本文中,瞭解在 Azure AI 搜尋服務中建立多面向導覽結構的基本步驟。

  • 在索引中設定欄位屬性
  • 建構要求和回應
  • 在呈現層中新增導覽控件和篩選

表示層中的程式代碼會在多面向導覽體驗中執行繁重的工作。 本文結尾所列的示範和範例會提供可說明如何將所有專案整合在一起的工作程序代碼。

搜尋頁面中多面向導覽

Facet 是動態的,並在查詢上傳回。 搜尋回應會隨附用來巡覽結果中檔的所有 Facet 類別。 查詢會先執行,然後從目前的結果提取Facet,並組合成多面向導覽結構。

在 Azure AI 搜尋中,Facet 深度為一層,而且不能是階層式。 如果您不熟悉多面向導覽結構,下列範例會顯示左側的一個。 計數表示每個 Facet 的相符項目數目。 同一份檔可以在多個 Facet 中表示。

Screenshot of faceted search results.

Facet 可協助您尋找您要尋找的內容,同時確保您不會得到零的結果。 身為開發人員,Facet 可讓您公開瀏覽搜尋索引的最有用搜尋準則。

在索引中啟用Facet

當您將 「facetable」 屬性設定為 true 時,會在索引定義中逐欄位啟用 Facet。

雖然並非絕對必要,但您也應該設定「可篩選」屬性,以便建置必要的篩選,以在搜尋應用程式中建置多面向導覽體驗。

下列 「hotels」 範例索引範例會在包含單一值或簡短片語的低基數位段上顯示「可 Facet」和「可篩選」:“Category”、“Tags”、“Rating”。

{
  "name": "hotels",  
  "fields": [
    { "name": "hotelId", "type": "Edm.String", "key": true, "searchable": false, "sortable": false, "facetable": false },
    { "name": "Description", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false },
    { "name": "HotelName", "type": "Edm.String", "facetable": false },
    { "name": "Category", "type": "Edm.String", "filterable": true, "facetable": true },
    { "name": "Tags", "type": "Collection(Edm.String)", "filterable": true, "facetable": true },
    { "name": "Rating", "type": "Edm.Int32", "filterable": true, "facetable": true },
    { "name": "Location", "type": "Edm.GeographyPoint" }
  ]
}

選擇欄位

Facet 可以透過單一值欄位和集合來計算。 在多面向導覽中效果最佳的欄位具有下列特性:

  • 低基數 (在搜尋主體中在整個文件中重複的少數相異值)

  • 簡短的描述性值(一或兩個單字)將會在導覽樹狀結構中呈現良好

欄位內的值,而不是功能變數名稱本身,會在多面向導覽結構中產生 Facet。 如果 Facet 是名為 Color 的字串欄位,Facet 會是藍色、綠色,以及該字段的任何其他值。

最佳做法是檢查 Null 值的欄位、拼錯或大小寫不一致,以及相同單字的單一和複數版本。 根據預設,篩選和 Facet 不會進行語彙分析或 拼字檢查,這表示「可多面向」欄位的所有值都是潛在的 Facet,即使單字不同也一個字元。 您可以選擇性 地將正規化程式 指派給「可篩選」和「可 Facet」欄位,以平滑大小寫和字元的變化。

REST 和 Azure SDK 中的預設值

如果您使用其中一個 Azure SDK,您的程式代碼必須明確設定欄位屬性。 相反地,REST API 具有根據 數據類型的欄位屬性預設值。 根據預設,下列數據類型為「可篩選」和「可 Facet」:

  • Edm.String
  • Edm.DateTimeOffset
  • Edm.Boolean
  • Edm.Int32、 、 Edm.Int64Edm.Double
  • 上述任何類型的集合,例如 Collection(Edm.String)Collection(Edm.Double)

您無法在多面向導覽中使用 Edm.GeographyPointCollection(Edm.GeographyPoint) 欄位。 Facet 最適合具有低基數的欄位。 由於地理座標的解析度,在指定的數據集中,任何兩組座標都相等是罕見的。 因此,地理座標不支援Facet。 您需要城市或區域欄位,才能依位置進行 Facet。

提示

作為效能和記憶體優化的最佳作法,請關閉不應該當做 Facet 使用的字段 Facet。 特別是,應設定 "facetable": false 唯一值的字串字段,例如標識碼或產品名稱,以避免在多面向導覽中使用其意外或無效。 這特別適用於默認啟用篩選和 Facet 的 REST API。

Facet 要求和回應

Facet 是在查詢上指定,而多面向導覽結構會在回應頂端傳回。 要求和回應的結構相當簡單。 事實上,多面向導覽背後的實際工作在於呈現層,涵蓋於稍後的章節中。

下列 REST 範例是限定到整個索引範圍的未限定查詢("search": "*"請參閱 內建旅館範例)。 Facet 通常是欄位清單,但此查詢只會顯示以下一個可讀取的回應。

POST https://{{service_name}}.search.windows.net/indexes/hotels/docs/search?api-version={{api_version}}
{
    "search": "*",
    "queryType": "simple",
    "select": "",
    "searchFields": "",
    "filter": "",
    "facets": [ "Category"], 
    "orderby": "",
    "count": true
}

使用開啟的查詢來初始化搜尋頁面,以完整填入多面向導覽結構相當實用。 一旦您在要求中傳遞查詢字詞,多面向導覽結構就會限定為結果中的相符專案,而不是整個索引。

上述範例的回應包含頂端多面向導覽結構。 結構包含「類別」值,以及每一個旅館的計數。 接著是其餘的搜尋結果,為了簡潔起見,請修剪這裡。 此範例適用於數個原因。 此欄位的 Facet 數目落在限制之下(預設值為 10),因此它們全部出現,而 50 家酒店索引中的每個旅館都以這其中一個類別來表示。

{
    "@odata.context": "https://demo-search-svc.search.windows.net/indexes('hotels')/$metadata#docs(*)",
    "@odata.count": 50,
    "@search.facets": {
        "Category": [
            {
                "count": 13,
                "value": "Budget"
            },
            {
                "count": 12,
                "value": "Resort and Spa"
            },
            {
                "count": 9,
                "value": "Luxury"
            },
            {
                "count": 7,
                "value": "Boutique"
            },
            {
                "count": 5,
                "value": "Suite"
            },
            {
                "count": 4,
                "value": "Extended-Stay"
            }
        ]
    },
    "value": [
        {
            "@search.score": 1.0,
            "HotelId": "1",
            "HotelName": "Secret Point Motel",
            "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
            "Category": "Boutique",
            "Tags": [
                "pool",
                "air conditioning",
                "concierge"
            ],
            "ParkingIncluded": false,
        }
    ]
}

Facet 語法

Facet 查詢參數會設定為以逗號分隔的「可面向」欄位清單,而且視數據類型而定,可以進一步參數化來設定計數、排序順序和範圍: count:<integer>sort:<>interval:<integer>values:<list>。 如需 Facet 參數的詳細資訊,請參閱 REST API 中的「查詢參數」。

POST https://{{service_name}}.search.windows.net/indexes/hotels/docs/search?api-version={{api_version}}
{
    "search": "*",
    "facets": [ "Category", "Tags,count:5", "Rating,values:1|2|3|4|5"],
    "count": true
}

針對每個多面向導覽樹狀結構,前十個 Facet 的預設限制。 此預設值對於導覽結構來說很合理,因為它會將值清單保留為可管理的大小。 您可以將值指派給 「count」 來覆寫預設值。 例如, "Tags,count:5" 將Tags區段下的標籤數目縮減為前五名。

僅針對 Numeric 和 DateTime 值,您可以在 Facet 欄位上明確設定值(例如 facet=Rating,values:1|2|3|4|5),將結果分成連續範圍(以數值或時間週期為基礎的範圍)。 或者,您可以新增 「interval」,如 中所示 facet=Rating,interval:1

每個範圍都是使用 0 作為起點、清單的值做為端點來建置,然後修剪前一個範圍以建立離散間隔。

Facet 計數的差異

在某些情況下,您可能會發現 Facet 計數因分區化架構而無法完全精確。 每個搜尋索引會分散到多個分區,而每個分區會依檔計數報告前 N 個 Facet,然後合併成單一結果。 因為它只是每個分區的前 N 個 Facet,所以在 Facet 回應中可能會遺漏或計數不足的相符檔。

為了保證正確性,您可以人為地將 count:<number> 擴充為大量,以強制從每個分區完整報告。 您可以 "count": "0" 指定無限制 Facet。 或者,您可以將 「count」 設定為大於或等於多面向字段唯一值數目的值。 例如,如果您是使用具有五個唯一值的「大小」欄位進行 Facet 處理,您可以設定 "count:5" 以確保所有相符專案都以 Facet 回應表示。

此因應措施的取捨會增加查詢延遲,因此只有在需要時才使用它。

展示層

在應用程式程式代碼中,模式是使用Facet查詢參數來傳回多面向導覽結構以及Facet結果,以及$filter表達式。 篩選表達式會處理 click 事件,並根據 Facet 選取範圍進一步縮小搜尋結果。

Facet 和篩選組合

如果您從 Business Title Facet 選取值,則 NYCJobs 示範中檔案的下列代碼段 JobsSearch.cs 會將選取的商務標題新增至篩選。

if (businessTitleFacet != "")
  filter = "business_title eq '" + businessTitleFacet + "'";

以下是酒店範例的另一個範例。 如果使用者從類別 Facet 選取值,下列代碼段會新增 categoyrFacet 至篩選。

if (!String.IsNullOrEmpty(categoryFacet))
    filter = $"category eq '{categoryFacet}'";

多面向導覽的 HTML

下列範例取自 index.cshtml NYCJobs 範例應用程式的檔案,會顯示靜態 HTML 結構,用於在搜尋結果頁面上顯示多面向導覽。 當您提交搜尋字詞或選取或清除 Facet 時,會以動態方式建置或重建 Facet 清單。

<div class="widget sidebar-widget jobs-filter-widget">
  <h5 class="widget-title">Filter Results</h5>
    <p id="filterReset"></p>
    <div class="widget-content">

      <h6 id="businessTitleFacetTitle">Business Title</h6>
      <ul class="filter-list" id="business_title_facets">
      </ul>

      <h6>Location</h6>
      <ul class="filter-list" id="posting_type_facets">
      </ul>

      <h6>Posting Type</h6>
      <ul class="filter-list" id="posting_type_facets"></ul>

      <h6>Minimum Salary</h6>
      <ul class="filter-list" id="salary_range_facets">
      </ul>

  </div>
</div>

動態建置 HTML

下列代碼段來自 (也來自 index.cshtml NYCJobs 示範) 會動態建置 HTML 以顯示第一個 Facet Business Title。 類似的函式會動態建置其他 Facet 的 HTML。 每個 Facet 都有標籤和計數,其會顯示針對該 Facet 結果找到的項目數目。

function UpdateBusinessTitleFacets(data) {
  var facetResultsHTML = '';
  for (var i = 0; i < data.length; i++) {
    facetResultsHTML += '<li><a href="javascript:void(0)" onclick="ChooseBusinessTitleFacet(\'' + data[i].Value + '\');">' + data[i].Value + ' (' + data[i].Count + ')</span></a></li>';
  }

  $("#business_title_facets").html(facetResultsHTML);
}

使用 Facet 的 提示

本節是可能有幫助的秘訣和因應措施集合。

以異步方式保留篩選結果的Facet導覽結構

Azure AI 搜尋中多面向導覽的其中一個挑戰是,面向僅適用於目前的結果。 在實務上,通常會保留一組靜態 Facet,讓使用者可以反向巡覽,並回溯步驟,透過搜尋內容探索替代路徑。

雖然這是常見的使用案例,但它不是多面向導覽結構目前提供的現成功能。 想要靜態 Facet 的開發人員通常會藉由發出兩個篩選的查詢來因應限制:一個範圍限定於結果,另一個則用來建立用於導覽之 Facet 的靜態清單。

清除Facet

當您設計搜尋結果頁面時,請記得新增清除 Facet 的機制。 如果您新增複選框,您可以輕鬆地查看如何清除篩選。 針對其他版面配置,您可能需要階層連結模式或其他創意方法。 在 Hotels C# 範例中,您可以傳送空白搜尋來重設頁面。 相反地,NYCJobs 範例應用程式會在選取的 Facet 之後提供可點選的 [X] 可點選,以清除面向,這是使用者更強大的視覺佇列。

使用更多篩選來修剪 Facet 結果

Facet 結果是在符合 Facet 字詞的搜尋結果中找到的檔。 在下列範例中,在雲端運算搜尋結果中,254 個專案也有內部規格做為內容類型。 專案不一定互斥。 如果專案符合這兩個篩選條件的準則,則會在每個篩選條件中計算。 在欄位上進行 Collection(Edm.String) 多面向處理時,通常用來實作文件標記時,可能會重複此重複。

Search term: "cloud computing"
Content type
   Internal specification (254)
   Video (10)

一般而言,如果您發現 Facet 結果一致太大,建議您新增更多篩選,讓使用者有更多選項來縮小搜尋範圍。

僅限 Facet 的搜尋體驗

如果您的應用程式以獨佔方式使用多面向導覽(也就是沒有搜尋方塊),您可以將欄位標示為 searchable=falsefilterable=truefacetable=true以產生更精簡的索引。 您的索引不會包含反向索引,而且不會有文字分析或標記化。 篩選是在字元層級的完全相符項目上進行。

在查詢時間驗證輸入

如果您根據不受信任的使用者輸入動態建置 Facet 清單,請驗證多面向字段的名稱是否有效。 或者,在 Uri.EscapeDataString() .NET 中使用 或您選擇的平臺中的對等專案,在建置URL時逸出名稱。

示範和範例

數個範例包括多面向導覽。 本節包含範例的連結,也會記下每個範例所使用的用戶端連結庫和語言。

將搜尋新增至 Web 應用程式 (React)

C#、Python 和 JavaScript 中的教學課程和範例包含多面向導覽,以及篩選、建議和自動完成。 這些範例會針對呈現層使用 React。

NYCJobs 範例程式代碼和示範 (Ajax)

NYCJobs 範例是 ASP.NET MVC 應用程式,在呈現層中使用 Ajax。 其可作為即時示範應用程式,以及 GitHub 上的 Azure 範例存放庫原始程式碼