分享方式:


Azure AI 搜尋服務中 $filter$orderby$select 的 OData 語言概觀

本文提供 $filter$order-by$select 運算式 (用於在 Azure AI 搜尋服務中針對數值和字串 (非向量) 欄位進行關鍵字搜尋) 中使用的 OData 運算式語言概觀。

語言會以「由下而上」呈現,開頭為最基本的元素。 您可在查詢要求中建構的 OData 運算式範圍可從簡單到高度複雜,但這些運算式皆共用通用元素。 共用元素包含:

  • 欄位路徑,其會參考索引的特定欄位。
  • 常數,其是特定資料類型的常值。

了解這些常見概念之後,您可繼續進行每個運算式的最上層語法:

  • $filter 在進行查詢剖析、將搜尋限定於特定欄位,或在索引掃描期間新增比對準則時,會評估篩選運算式。
  • $orderby 運算式會套用作為結果集的後續處理步驟以排序傳回的文件。
  • $select 運算式會決定結果集中包含的文件欄位。

這些運算式的語法與搜尋參數中使用的簡單完整查詢語法不同,即使參考欄位的語法有某些重疊。

如需其他語言的範例,例如 Python 或 C#,請參閱 azure-search-vector-samples 存放庫中的範例。

注意

Azure AI 搜尋服務的詞彙與 OData 標準的詞彙有一些不同的地方。 Azure AI 搜尋服務中稱為欄位,在 OData 中則稱為屬性;同理,欄位路徑屬性路徑亦是如此。 在 Azure AI 搜尋服務中包含文件索引,在 OData 中通常稱為包含實體實體集。 此參考會使用 Azure AI 搜尋服務的詞彙。

欄位路徑

下列 EBNF (延伸的巴克斯格式) 會定義欄位路徑的語法。

field_path ::= identifier('/'identifier)*

identifier ::= [a-zA-Z_][a-zA-Z_0-9]*

我們也提供互動式語法圖表:

注意

如需完整的 EBNF,請參閱 Azure AI 搜尋服務的 OData 運算式語法參考

欄位路徑包含一或多個斜線分隔的識別碼。 每個識別碼都是字元序列,開頭必須為 ASCII 字母或底線,且僅包含 ASCII 字母、數字或底線。 字母可是大寫或小寫。

識別碼可參考欄位名稱,或篩選條件中集合運算式 (anyall) 內容的範圍變數。 範圍變數如同迴圈變數,表示集合的目前元素。 針對複雜集合,該變數則表示物件,如此您可使用欄位路徑來參考變數的子欄位。 這類似於多個程式設計語言中的點標計法。

下表顯示欄位路徑的範例:

欄位路徑 描述
HotelName 指的是索引的最上層欄位
Address/City 指的是索引中複雜欄位的 City 子欄位;在此範例中,Address 屬於類型 Edm.ComplexType
Rooms/Type 指的是索引中複雜集合欄位的 Type 子欄位;在此範例中,Rooms 屬於類型 Collection(Edm.ComplexType)
Stores/Address/Country 指的是索引中複雜集合欄位 Address 子欄位的 Country 子欄位;在此範例中,Stores 屬於類型 Collection(Edm.ComplexType)Address 屬於類型 Edm.ComplexType
room/Type 指的是 room 範圍變數的 Type 子欄位,例如篩選條件運算式為 Rooms/any(room: room/Type eq 'deluxe')
store/Address/Country 指的是 store 範圍變數 Address 子欄位的 Country 子欄位,例如篩選條件運算式為 Stores/any(store: store/Address/Country eq 'Canada')

欄位路徑的亦亦會根據內容而有所不同。 在篩選條件中,欄位路徑指的是目前文件中欄位單一執行個體的值。 在其他內容 (例如 $orderby$select) 或在完整 Lucene 語法的欄位搜尋中,欄位路徑指的是欄位本身。 此差異對於如何在篩選條件中使用欄位路徑會有某些結果。

考量欄位路徑 Address/City。 在篩選條件中,這指的是目前文件的單一城市,例如「舊金山」。 相反地,Rooms/Type 指的是多個房間的 Type 子欄位 (例如第一個房間為「標準」、第二個房間為「豪華」等)。 由於 Rooms/Type 並非是子欄位 Type單一執行個體,因此無法在篩選條件中直接使用。 為了篩選房間類型,您會使用 Lambda 運算式搭配範圍變數,如下所示:

Rooms/any(room: room/Type eq 'deluxe')

在此範例中,範圍變數 room 會顯示在 room/Type 欄位路徑中。 如此,room/Type 指的是目前文件中目前房間的類型。 這是 Type 子欄位的單一執行個體,因此可在篩選條件中直接使用。

使用欄位路徑

欄位路徑會用於 Azure AI 搜尋服務 REST API 的多個參數中。 下表列出可使用欄位路徑的所有位置,以及使用方式的限制:

API 參數名稱 限制
建立更新索引 suggesters/sourceFields
建立更新索引 scoringProfiles/text/weights 僅可參考可搜尋欄位
建立更新索引 scoringProfiles/functions/fieldName 僅可參考可篩選欄位
Search queryTypefull 時的 search 僅可參考可搜尋欄位
Search facet 僅可參考可面向化欄位
Search highlight 僅可參考可搜尋欄位
Search searchFields 僅可參考可搜尋欄位
建議自動完成 searchFields 僅可參考屬於建議工具的欄位
搜尋建議自動完成 $filter 僅可參考可篩選欄位
搜尋建議 $orderby 僅可參考可排序欄位
搜尋建議查閱 $select 僅可參考可擷取欄位

常數

OData 中的常數是指定實體資料模型 (EDM) 類型的常值。 如需 Azure AI 搜尋服務中支援類型的清單,請參閱支援的資料類型。 不支援集合類型的常數。

下表顯示支援 OData 運算式的每個非向量資料類型的常數範例:

資料類型 範例常數
Edm.Boolean true, false
Edm.DateTimeOffset 2019-05-06T12:30:05.451Z
Edm.Double 3.14159, -1.2e7, NaN, INF, -INF
Edm.GeographyPoint geography'POINT(-122.131577 47.678581)'
Edm.GeographyPolygon geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'
Edm.Int32 123, -456
Edm.Int64 283032927235
Edm.String 'hello'

逸出字串常數中的特殊字元

OData 中的字串常數會以單引號分隔。 若您必須以可能自身包含單引號的字串常數來建構查詢,您可使用雙引號來逸出內嵌的引號。

例如,含未格式化單引號 (例如 "Alice's car") 的片語會在 OData 中以字串常數 'Alice''s car' 呈現。

重要

以程式設計的方式來建構篩選條件時,請務必記得逸出來自使用者輸入的字串常數。 這是為了降低插入式攻擊的可能性,特別是在使用篩選條件來實作安全性調整時。

常數語法

下列 EBNF (延伸的巴克斯格式) 會定義上表中顯示的大部分常數文法。 您可在 Azure AI 搜尋服務中的 OData 地理空間函式中找到地理空間類型的語法。

constant ::=
    string_literal
    | date_time_offset_literal
    | integer_literal
    | float_literal
    | boolean_literal
    | 'null'

string_literal ::= "'"([^'] | "''")*"'"

date_time_offset_literal ::= date_part'T'time_part time_zone

date_part ::= year'-'month'-'day

time_part ::= hour':'minute(':'second('.'fractional_seconds)?)?

zero_to_fifty_nine ::= [0-5]digit

digit ::= [0-9]

year ::= digit digit digit digit

month ::= '0'[1-9] | '1'[0-2]

day ::= '0'[1-9] | [1-2]digit | '3'[0-1]

hour ::= [0-1]digit | '2'[0-3]

minute ::= zero_to_fifty_nine

second ::= zero_to_fifty_nine

fractional_seconds ::= integer_literal

time_zone ::= 'Z' | sign hour':'minute

sign ::= '+' | '-'

/* In practice integer literals are limited in length to the precision of
the corresponding EDM data type. */
integer_literal ::= digit+

float_literal ::=
    sign? whole_part fractional_part? exponent?
    | 'NaN'
    | '-INF'
    | 'INF'

whole_part ::= integer_literal

fractional_part ::= '.'integer_literal

exponent ::= 'e' sign? integer_literal

boolean_literal ::= 'true' | 'false'

我們也提供互動式語法圖表:

注意

如需完整的 EBNF,請參閱 Azure AI 搜尋服務的 OData 運算式語法參考

從欄位路徑和常數建置運算式

欄位路徑和常數是 OData 運算式的最基本部分,但本身已是完整的運算式。 事實上,Azure AI 搜尋服務中的 $select 參數僅是欄位路徑的逗點分隔清單,而相較於 $select$orderby 較不複雜。 若在索引中有類型 Edm.Boolean 的欄位,您甚至可僅撰寫該欄位路徑的篩選條件。 常數 truefalse 同是有效篩選條件。

不過,參考多個欄位和常數的複雜運算式比較常見。 這些運算式會根據參數,以不同方式來建置。

下列 EBNF (延伸的巴克斯格式) 會定義 $filter$orderby$select 參數的文法。 這些皆是從參考欄位路徑和常式的較簡單運算式所建置:

filter_expression ::= boolean_expression

order_by_expression ::= order_by_clause(',' order_by_clause)*

select_expression ::= '*' | field_path(',' field_path)*

我們也提供互動式語法圖表:

注意

如需完整的 EBNF,請參閱 Azure AI 搜尋服務的 OData 運算式語法參考

下一步

$orderby$select 參數皆是較簡單運算式的逗號分隔清單。 $filter 參數是布林運算式,其中包含較簡單的子運算式。 這些子運算式會使用下列運算子進行合併:邏輯運算子 (例如 andornot)、比較運算子 (例如 eqltgt) 和集合運算子 (例如 anyall)。

下列文章會更詳細探索 $filter$orderby$select 參數: