了解 OData 集合篩選條件如何在 Azure AI 搜尋服務中運作

注意

Azure AI 搜尋服務 可透過 Azure 入口網站、REST API 及 Azure SDK 取得。 它同時也是 Foundry IQ 的基礎,這是一個管理式知識層,能將企業內容轉化為可重複使用、權限感知的知識庫,供 Microsoft Foundry 入口網站中的代理使用。

本文為使用複雜 Lambda 表達式撰寫進階篩選條件的開發人員提供了背景知識。 本文會透過探索 Azure AI 搜尋服務如何執行這些篩選條件,進一步說明集合篩選條件的規則存在原因。

在 Azure AI 搜尋服務上針對集合欄位建立篩選條件時,您可使用 any 和 all 運算子搭配 Lambda 運算式。 Lambda 運算式是參考範圍變數的布林運算式。 在使用 Lambda 表達式的篩選條件中,any 和 all 運算子類似於大部分程式設計語言中的 for 迴圈,其範圍變數會採用迴圈變數的角色並將 Lambda 運算式視為迴圈主體。 在迴圈反覆運算的過程中,範圍變數會取得集合的「目前」值。

至少在概念上是這樣運作的。 實際上,Azure AI 搜尋服務實作篩選條件的方式與 for 迴圈運作方式大不相同。 在理想情況下,您不會察覺差異,但在某些情況下,則顯而易見。 最終結果是撰寫 Lambda 運算式時必須遵循規則。

注意

如需集合篩選條件規則用途的相關資訊和範例,請參閱針對 Azure AI 搜尋服務中的 OData 集合篩選條件進行疑難排解。

為何限制集合篩選條件

並非所有集合類型都支援篩選功能,三個基本原因如下:

  1. 特定資料類型僅支援某些運算子。 例如,使用像 true 和 false 這樣的比較運算子來比較布林值 lt 和 gt 是沒有意義的。
  2. Azure AI 搜尋服務 支援對類型Collection(Edm.ComplexType)欄位 的相關篩選,但對這些欄位進行全文搜尋時,則是無相關性。
  3. Azure AI 搜尋服務會使用反向索引來對包含集和在內的所有類型資料執行篩選。

第一個原因僅是定義 OData 語言和 EDM 類型系統的結果。 本節的其餘部分將詳細說明後續兩個原因。

當您對複雜物件集套用多個篩選準則時,準則將相關聯,因為會套用至集合中的每個物件。 例如,下列篩選條件將傳回至少有一間豪華客房且價格低於 100 的旅館:

    Rooms/any(room: room/Type eq 'Deluxe Room' and room/BaseRate lt 100)

如果篩選無關聯,則上述篩選可能會傳回包含一間豪華客房和另一間基本房價低於 100 的不同房間的飯店。 這並不合理,因為 Lambda 運算式的兩個子句都套用至相同的範圍變數,亦即 room。 這便是為何這類篩選條件相關聯的原因。

然而,針對全文檢索搜尋,則無法參考特定範圍變數。 如果您使用欄位式搜尋來發出像這樣的完整 Lucene 查詢:

    Rooms/Type:deluxe AND Rooms/Description:"city view"

您可能會得到一些旅館結果,其中某一個房間是 deluxe,而另一個不同的房間則在描述中提到「city view」。 例如,下方文件中 Id 與 1 的組合可能符合查詢條件。

{
  "value": [
    {
      "Id": "1",
      "Rooms": [
        { "Type": "deluxe", "Description": "Large garden view suite" },
        { "Type": "standard", "Description": "Standard city view room" }
      ]
    },
    {
      "Id": "2",
      "Rooms": [
        { "Type": "deluxe", "Description": "Courtyard motel room" }
      ]
    }
  ]
}

原因是 Rooms/Type 會參考整個文件中 Rooms/Type 欄位的所有分析字詞,Rooms/Description 亦是如此,如下表所示。

如何儲存Rooms/Type以進行全文搜尋:

Rooms/Type 中的字詞 文件識別碼
豪華 1, 2
標準 1

如何儲存Rooms/Description以進行全文搜尋:

Rooms/Description 中的字詞 文件識別碼
庭院 2
city 1
花園 1
大型 1
汽車旅館 2
房間 1, 2
標準 1
套件 1
檢視表 1

因此,與上述篩選條件不同,其基本上表示「比對文件,其中客房的 Type 等於「豪華客房」,且該相同客房的 BaseRate 少於 100」,而搜尋查詢則表示「比對文件,其中 Rooms/Type 包含字詞「豪華」,且Rooms/Description 包含片語「市景」。 在後者情況下,並沒有可將欄位彼此關聯的個別房間概念。

反向索引和集合

你可能會注意到,lambda 表達式對複雜集合的限制遠少於簡單集合 Collection(Edm.Int32) ,例如 和 Collection(Edm.GeographyPoint)。 這個差異在於 Azure AI 搜尋服務 將複雜的集合存放為子文件的實際集合,而簡單的集合則根本不會被儲存為集合。

例如,請針對線上零售商考慮可篩選的字串集合欄位 (如索引中的 seasons)。 上傳至此索引的某些文件可能會如下所示:

{
  "value": [
    {
      "id": "1",
      "name": "Hiking boots",
      "seasons": ["spring", "summer", "fall"]
    },
    {
      "id": "2",
      "name": "Rain jacket",
      "seasons": ["spring", "fall", "winter"]
    },
    {
      "id": "3",
      "name": "Parka",
      "seasons": ["winter"]
    }
  ]
}

seasons 欄位的值會儲存在名為反向索引的結構中,如下所示:

詞彙 文件識別碼
spring 1, 2
夏天 1
秋天 1, 2
冬天 2、3

此資料結構專設計用來即時回答一個問題:哪些文件會顯示指定的字詞? 回答這個問題的方式,比較像是一般相等檢查,而不是對集合進行迴圈。 事實上,這就是為什麼針對字串集合,Azure AI 搜尋只允許 eq 在 Lambda 運算式中作為 any 的比較運算符。

接下來,我們將探討如何使用 or 在相同範圍變數上組合多個相等檢查。 由於代數和量詞的分配律,而可順利運作。 此表達式:

    seasons/any(s: s eq 'winter' or s eq 'fall')

等於:

    seasons/any(s: s eq 'winter') or seasons/any(s: s eq 'fall')

而且,兩個 any 子運算式都可以使用反向索引有效率地執行。 另外,根據量詞的否定律,這個運算式:

    seasons/all(s: s ne 'winter' and s ne 'fall')

等於:

    not seasons/any(s: s eq 'winter' or s eq 'fall')

這就是為什麼可以使用 all、ne 和 and。

注意

即使詳細資料超出本文件的範圍,但這些相同原則也會延伸至地理空間點集合的距離和交集測試。 這就是為什麼在 any 中:

  • geo.intersects 無法否定
  • geo.distance 必須使用 lt 或 le 進行比較
  • 表達式必須與 or 組合,而不是與 and 組合。

相反規則適用於 all。

當針對支援 lt、gt、le 和 ge 等運算子的資料類型集合進行篩選時,例如 Collection(Edm.Int32),允許使用更廣泛的運算式。 具體而言,在 and 中,您可以使用 or 和 any,但前提是必須將基本比較運算式透過 合併成and,然後再使用 or 進一步合併。 此布林運算式的結構稱為析取正規式 (DNF),也稱為 "ORs of ANDs"。 相反地,針對這些資料類型的 all 運算式,必須採用合取正規形 (CNF),也就是所謂的「OR 的 AND」。 Azure AI 搜尋服務允許這類範圍比較,因為它可以像對字串進行快速詞彙查閱一樣,使用反向索引有效率地執行這些比較。

總而言之,以下是 Lambda 運算式中允許內容的經驗法則:

  • 在 any 內部,永遠允許正向檢查,例如相等、範圍比較、geo.intersects,或與 geo.distance 或 lt 比較的 le (可以把「接近程度」視為距離檢查中的相等)。
  • 在 any 內部,永遠允許 or。 只在使用 ORs of ANDs (DNF) 時,您才可將 and 用於可表示範圍檢查的資料類型。
  • 在 all 內,規則為反向。 只允許負向檢查,您永遠可以使用 and,而 or 只能用於表達為 OR 的 AND (CNF) 之範圍檢查。

實際上,這些是您最可能使用的篩選條件類型。 不過,瞭解可能的界限,仍對您有所幫助。

如需允許和不允許篩選條件類型的特定範例,請參閱如何撰寫有效集合篩選條件。

下一步