Azure AI 搜尋中的 OData $filter語法

在 Azure AI 搜尋中, $filter 參數會指定在搜尋結果中傳回相符專案的包含或排除準則。 本文說明$filterOData 語法,並提供範例。

欄位路徑建構和常數會在 Azure AI 搜尋的 OData 語言概觀中描述。 如需篩選案例的詳細資訊,請參閱 Azure AI 搜尋中的篩選。

語法

OData 語言中的篩選條件是布爾表達式,這反過來又可以是數種類型的表達式之一,如下列 EBNF 所示(Extended Backus-Naur Form):

boolean_expression ::=
    collection_filter_expression
    | logical_expression
    | comparison_expression
    | boolean_literal
    | boolean_function_call
    | '(' boolean_expression ')'
    | variable

/* This can be a range variable in the case of a lambda, or a field path. */
variable ::= identifier | field_path

您也可以使用互動式語法圖表:

注意

如需完整的EBNF,請參閱 Azure AI 搜尋 的 OData 表達式語法參考。

布林運算式的類型包括:

  • 使用 anyall的集合篩選表達式。 這些條件會將篩選準則套用至集合欄位。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 集合運算符。
  • 使用運算子 andornot結合其他布爾表達式的邏輯表達式。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 邏輯運算符。
  • 比較表達式,使用運算符 eq、、ne、、gtltgele來比較字段或範圍變數與常數值。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 比較運算符。 比較表達式也可用來使用 geo.distance 函式來比較地理空間座標之間的距離。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 地理空間函式。
  • 布林常值 truefalse。 有時候,以程式設計方式產生篩選時,這些常數可能很有用,但實際上不會使用。
  • 對布爾函式的呼叫,包括:
    • geo.intersects,其會測試指定的點是否在指定的多邊形內。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 地理空間函式。
    • search.in,它會比較欄位或範圍變數與值清單中的每個值。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData search.in 函式。
    • search.ismatchsearch.ismatchscoring,它會在篩選內容中執行全文搜索作業。 如需詳細資訊,請參閱 Azure AI 搜尋服務中的 OData 全文搜索函式。
  • 類型的 Edm.Boolean欄位路徑或範圍變數。 例如,如果您的索引具有名為 IsEnabled 的布林值欄位,而且您想要傳回此欄位為 true的所有檔案,則篩選表示式只能是名稱 IsEnabled
  • 括弧中的布爾表達式。 使用括弧有助於明確判斷篩選中作業的順序。 如需 OData 運算符預設優先順序的詳細資訊,請參閱下一節。

篩選條件中的運算符優先順序

如果您撰寫的篩選表達式在其子表達式周圍沒有括號,Azure AI 搜尋會根據一組運算符優先順序規則來評估它。 這些規則是根據哪些運算子用來合併子表達式。 下表列出運算子群組,順序從最高到最低優先順序:

群組 運算子(秒)
邏輯運算子 not
比較運算子 eq、、negtlt、、gele
邏輯運算子 and
邏輯運算子 or

在上述數據表中較高的運算符,會比其他運算符更緊密地系結至其操作數。 例如, and 優先順序高於 or,而比較運算符的優先順序高於其中一個,因此下列兩個表達式相等:

    Rating gt 0 and Rating lt 3 or Rating gt 7 and Rating lt 10
    ((Rating gt 0) and (Rating lt 3)) or ((Rating gt 7) and (Rating lt 10))

運算符 not 的優先順序最高,甚至高於比較運算符。 這就是為什麼如果您嘗試撰寫如下的篩選:

    not Rating gt 5

您會收到此錯誤訊息:

    Invalid expression: A unary operator with an incompatible type was detected. Found operand type 'Edm.Int32' for operator kind 'Not'.

之所以發生此錯誤,是因為 運算符只 Rating 與 類型為 Edm.Int32的欄位相關聯,而不是與整個比較表達式相關聯。 修正方式是將 的操作數 not 放在括弧中:

    not (Rating gt 5)

篩選大小限制

篩選表達式的大小和複雜度有限制,您可以傳送至 Azure AI 搜尋服務。 這些限制大致是以篩選表達式中的子句數目為基礎。 良好的指導方針是,如果您有數百個子句,您有可能超過限制。 我們建議以這種方式設計您的應用程式,使其不會產生未系結大小的篩選。

提示

使用 search.in式而非長時間分離相等比較有助於避免篩選子句限制,因為函式呼叫會算作單一子句。

範例

尋找至少有一間基本費率低於 $200 且評為 4 以上之基本費率的所有酒店:

    $filter=Rooms/any(room: room/BaseRate lt 200.0) and Rating ge 4

尋找自 2010 年以來一直翻新的 “Sea View Motel” 以外的所有酒店:

    $filter=HotelName ne 'Sea View Motel' and LastRenovationDate ge 2010-01-01T00:00:00Z

尋找 2010 年或更新版本裝修的所有酒店。 datetime 常值包含太平洋標準時間的時區資訊:

    $filter=LastRenovationDate ge 2010-01-01T00:00:00-08:00

尋找包含停車的所有酒店,以及所有房間都禁止吸煙的地方:

    $filter=ParkingIncluded and Rooms/all(room: not room/SmokingAllowed)

- 或 -

    $filter=ParkingIncluded eq true and Rooms/all(room: room/SmokingAllowed eq false)

尋找所有豪華或包含停車場且評分為 5 的旅館:

    $filter=(Category eq 'Luxury' or ParkingIncluded eq true) and Rating eq 5

在至少一個房間尋找具有 “wifi” 卷標的所有酒店(其中每個房間都有儲存在欄位中的 Collection(Edm.String) 標籤):

    $filter=Rooms/any(room: room/Tags/any(tag: tag eq 'wifi'))

尋找具有任何房間的所有酒店:

    $filter=Rooms/any()

尋找沒有房間的所有酒店:

    $filter=not Rooms/any()

指定參考點的 10 公里內尋找所有酒店(其中 Location 是 類型的 Edm.GeographyPoint欄位):

    $filter=geo.distance(Location, geography'POINT(-122.131577 47.678581)') le 10

尋找指定檢視區內描述為多邊形的所有酒店(其中 Location 是Edm.GeographyPoint類型的欄位)。 多邊形必須關閉,這表示第一個和最後一個點集合必須相同。 此外, 點必須以逆時針順序列出。

    $filter=geo.intersects(Location, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))')

尋找 「Description」 字段為 Null 的所有旅館。 如果字段從未設定,或明確設定為 null,則字段會是 Null:

    $filter=Description eq null

尋找名稱等於 'Sea View hotel' 或 'Budget hotel' 的所有酒店。 這些片語包含空格,而空格是預設分隔符。 您可以將單引號中的替代分隔符指定為第三個字串參數:

    $filter=search.in(HotelName, 'Sea View motel,Budget hotel', ',')

尋找名稱等於 'Sea View hotel' 或以 '|' 分隔的 'Budget hotel' 的所有酒店:

    $filter=search.in(HotelName, 'Sea View motel|Budget hotel', '|')

尋找所有房間都有 'wifi' 或 'tub' 卷標的所有酒店:

    $filter=Rooms/any(room: room/Tags/any(tag: search.in(tag, 'wifi, tub')))

在集合內的片語上尋找相符專案,例如標籤中的「加熱毛巾架」或「隨附的」等。

    $filter=Rooms/any(room: room/Tags/any(tag: search.in(tag, 'heated towel racks,hairdryer included', ','))

使用「海濱」一詞尋找檔。 此篩選查詢與 搭配search=waterfront搜尋要求相同。

    $filter=search.ismatchscoring('waterfront')

尋找 「hostel」 一字且評分大於或等於 4 的檔,或具有 「motel」 一字且評等為 5 的檔。 由於此要求會使用 or結合全文搜索與篩選作業,所以無法在沒有函式的情況下search.ismatchscoring表示。

    $filter=search.ismatchscoring('hostel') and rating ge 4 or search.ismatchscoring('motel') and rating eq 5

尋找沒有「豪華」一詞的檔。

    $filter=not search.ismatch('luxury')

尋找片語 「ocean view」 或 rating 等於 5 的檔。 查詢 search.ismatchscoring 只會針對欄位 HotelNameDescription執行。 只比對分離第二個子句的檔也會傳回 -- 等於 5 的旅館 Rating 。 這些檔會以等於零的分數傳回,以明確表示它們不符合表達式的任何評分部分。

    $filter=search.ismatchscoring('"ocean view"', 'Description,HotelName') or Rating eq 5

在描述中尋找 「hotel」 和 「airport」 一詞不超過五個字的旅館,以及所有房間都是不吸煙的。 此查詢會使用 完整的 Lucene 查詢語言

    $filter=search.ismatch('"hotel airport"~5', 'Description', 'full', 'any') and not Rooms/any(room: room/SmokingAllowed)

尋找具有以 [描述] 字段中字母 “lux” 開頭之單字的檔。 此查詢會搭配 search.ismatch使用前置詞搜尋

    $filter=search.ismatch('lux*', 'Description')

下一步