分享方式:


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

多面向導覽適用於在搜尋應用程式中對查詢結果進行自我導向的向下鑽研篩選,您的應用程式可以在其中提供表單控制項來設定文件群組 (例如,類別或品牌) 的搜尋範圍,而 Azure AI 搜尋服務會提供資料結構和篩選條件來支持該體驗。

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

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

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

搜尋頁面中的多面向導覽

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

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

多面向搜尋結果的螢幕擷取畫面。

面向可協助您找到要找的項目,同時確保您不會得到空無一物的結果。 身為開發人員,面向可讓您將最有用的搜尋準則公開,以導覽您的搜尋索引。

在索引中啟用 Facet

當您將「可 Facet」屬性設定為 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,即使單字只有一個字元不同也一樣。 您可以選擇性地指派正規化程式 給「可篩選」和「可 Facet」欄位,讓大小寫和字元的變化平滑。

REST 和 Azure SDK 中的預設值

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

  • Edm.String
  • Edm.DateTimeOffset
  • Edm.Boolean
  • Edm.Int32Edm.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),因此會出現所有 Facet,而 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": "Stay-Kay City Hotel",
            "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 查詢參數會設定為逗號分隔的「可 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 的預設限制。 對於導覽結構來說,此項預設值相當合理,因為它維持值清單在一個可管理的大小。 您可以透過指派「計數」值來覆寫預設值。 例如,"Tags,count:5" 會將 [標記] 區段底下的標記數目減少為前五個。

針對 [數值] 和 [日期時間] 值,您可以明確設定 Facet 欄位的值 (例如,facet=Rating,values:1|2|3|4|5),將結果分成連續範圍 (根據數值或時間週期的範圍)。 或者,您也可以新增「間隔」,如同在 facet=Rating,interval:1 中一樣。

已使用 0 做為起始點,清單中的值做為結束點建置各範圍,並且修剪之前的範圍來建立離散間隔。

Facet 計數中的不一致

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

若要保證精確度,您可以人工將計數:<數目> 擴充為大數字,以強制從每個分區進行完整報告。 您可以針對無限制 Facet 指定 "count": "0"。 或者,您可以將「計數」設定為大於或等於多面向欄位唯一值數目的值。 例如,如果您要以具有五個唯一值的「大小」欄位進行 Facet 處理,您可以設定 "count:5" 以確保所有相符項目都會在 Facet 回應中表示。

此因應措施的代價是增加查詢延遲,因此只在需要時才使用。

展示層

在應用程式程式碼中,模式為使用面向查詢參數來傳回多面向導覽結構和面向結果,並外加一個 $filter 運算式。 篩選條件運算式會處理 Click 事件,並根據 Facet 選取範圍進一步縮小搜尋結果。

Facet 和篩選組合

下列來自 NYCJobs 示範中的 JobsSearch.cs 檔案會在您選取「職稱」Facet 的值時,在篩選中新增所選的職稱。

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

以下是旅館範例的另一個範例。 如果使用者從類別 Facet 選取值,下列程式碼片段就會將 categoryFacet 新增至篩選條件。

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

多面向導覽的 HTML

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

<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 (職稱)。 類似的函式會動態建置其他面向的 HTML。 每個面向都有標籤和計數,以顯示針對該面向結果所找到的項目數。

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 的秘訣

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

以非同步方式保留篩選結果的多面向導覽結構

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

儘管這是一個常見使用案例,但並不是多面向導覽目前預設提供的功能。 需要靜態 Facet 的開發人員通常可藉由發出兩個篩選查詢來解決限制:一個將範圍設為結果,另一個則基於導覽目的用來建立靜態的 Facet 清單。

清除 Facet

在設計搜尋結果頁面時,請記得加入清除面向的機制。 如果您新增核取方塊,即可輕鬆地了解如何清除篩選條件。 針對其他配置,您可能需要階層模式或其他具創意的方法。 在旅館 C# 範例中,您可以傳送空的搜尋來重設頁面。 相反地,NYCJobs 範例應用程式會在選取的 Facet 之後提供可點選的 [X] 以清除 Facet,這對使用者而言是更強大的視覺佇列。

使用更多篩選條件修剪 Facet 結果

面向結果是在符合面向字詞的搜尋結果中找到的文件。 在下列範例中,「雲端運算」的搜尋結果中有 254 個項目也具有做為內容類型的「內部規格」。 項目毋須互斥。 如果項目同時符合兩個篩選條件的條件,則會個別計數。 在 Collection(Edm.String) 欄位 (通常用來實作文件標記) 上進行面向化時可能發生此重複情形。

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

一般來說,如果您發現面向結果一直過大,建議您新增更多篩選條件,以便讓使用者有更多選項可縮小搜尋範圍。

僅限 Facet 的搜尋體驗

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

在查詢時間驗證輸入

如果您根據未受信任的使用者輸入動態建置面向清單,請驗證多面向欄位的名稱是否有效。 或者,請在建置 URL 時,使用 .NET 中的 Uri.EscapeDataString() 或所選平台的同等功能來逸出這些名稱。

範例

我們建議使用下列範例進行多面向導覽。 這些範例也包含篩選、建議和自動完成。 這些範例會針對呈現層使用 React。