Azure AI 搜尋服務中的 OData $filter 語法
在 Azure AI 搜尋中, $filter 參數會指定在搜尋結果中傳回相符專案的包含或排除準則。 本文說明$filter的 OData 語法,並提供範例。
欄位路徑建構和常數會在 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 運算式語法參考。
布林運算式的類型包括:
- 使用
any
或all
的集合篩選表達式。 這些條件會將篩選準則套用至集合欄位。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 集合運算符。 - 使用運算子
and
、or
和not
結合其他布爾表達式的邏輯表達式。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 邏輯運算符。 - 比較表達式,使用運算符
eq
、、ne
、、gt
lt
、ge
和le
來比較字段或範圍變數與常數值。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 比較運算符。 比較表達式也可用來使用geo.distance
函式來比較地理空間座標之間的距離。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 地理空間函式。 - 布林常值
true
和false
。 有時候,以程式設計方式產生篩選時,這些常數可能很有用,但實際上不會使用。 - 對布爾函式的呼叫,包括:
geo.intersects
,其會測試指定的點是否在指定的多邊形內。 如需詳細資訊,請參閱 Azure AI 搜尋中的 OData 地理空間函式。search.in
,它會比較欄位或範圍變數與值清單中的每個值。 如需詳細資訊,請參閱 Azure AI 搜尋中的 ODatasearch.in
函式。search.ismatch
和search.ismatchscoring
,它會在篩選內容中執行全文搜索作業。 如需詳細資訊,請參閱 Azure AI 搜尋服務中的 OData 全文搜索函式。
- 類型的
Edm.Boolean
欄位路徑或範圍變數。 例如,如果您的索引具有名為IsEnabled
的布林值欄位,而且您想要傳回此欄位為true
的所有檔案,則篩選表示式只能是名稱IsEnabled
。 - 括弧中的布爾表達式。 使用括弧有助於明確判斷篩選中作業的順序。 如需 OData 運算符預設優先順序的詳細資訊,請參閱下一節。
篩選條件中的運算符優先順序
如果您撰寫的篩選表達式在其子表達式周圍沒有括號,Azure AI 搜尋會根據一組運算符優先順序規則來評估它。 這些規則是根據哪些運算子用來合併子表達式。 下表列出運算子群組,順序從最高到最低優先順序:
群組 | 運算子(秒) |
---|---|
邏輯運算子 | not |
比較運算子 | eq 、、ne gt 、lt 、、ge 、le |
邏輯運算子 | 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
只會針對欄位 HotelName
和 Description
執行。 只比對分離第二個子句的檔也會傳回 -- 等於 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')