針對 Azure AI 搜尋服務中的 OData 集合篩選條件進行疑難排解
若要篩選 Azure AI 搜尋服務上的集合欄位,您可使用 any
和 all
運算子搭配 Lambda 運算式。 Lambda 運算式是套用至集合中每個元素的子篩選。
並非所有篩選條件運算式的功能都可以在 Lambda 運算式內使用。 哪些功能可用會根據您想要篩選的集合欄位資料類型而有所不同。 如果您嘗試在該內容中不支援的 Lambda 運算式中使用功能,這可能會導致錯誤。 如果您在嘗試對集合欄位撰寫複雜篩選時遇到這類錯誤,本文可協助您針對問題進行疑難排解。
常見的集合篩選錯誤
下表列出嘗試執行集合篩選時可能會遇到的錯誤。 當您使用 Lambda 運算式內不支援的篩選運算式功能時,就會發生這些錯誤。 每個錯誤都會提供一些指導,說明如何重寫篩選,以避免發生錯誤。 下表也包含本文相關章節的連結,提供如何避免該錯誤的詳細資訊。
錯誤訊息 | 情況 | 詳細資料 |
---|---|---|
函式 ismatch 沒有繫結至範圍變數 's' 的參數。 Lambda 運算式內僅支援繫結欄位參考 ('any' 或 'all')。 不過,您可以變更您的篩選,讓 ismatch 函式在 Lambda 運算式之外,然後再試一次。 |
在 Lambda 運算式內使用 search.ismatch 或 search.ismatchscoring |
篩選複雜集合的規則 |
不正確 Lambda 運算式。 找到在 Lambda 運算式中預期相等或不相等的測試,該運算式會逐一查看 Collection(Edm.String) 類型的欄位。 針對 'any',請使用 'x eq y' 或 'search.in (...)' 格式的運算式。 針對 'all',請使用 'x ne y'、'not (x eq y)' 或 'not search.in(...)' 格式的運算式。 | 篩選 Collection(Edm.String) 類型的欄位 |
篩選字串集合的規則 |
不正確 Lambda 運算式。 找到不受支援的複雜布林運算式形式。 針對 'any',請使用 'ORs of ANDs' 的運算式,也稱為析取範式。 例如:(a and b) or (c and d) ,其中 a、b、c 和 d 是比較或等式子運算式。 針對 'all',請使用 'ANDs of ORs' 的運算式,也稱為合取範式。 例如:(a or b) and (c or d) ,其中 a、b、c 和 d 是比較或不等式子運算式。 比較運算式的範例:'x gt 5'、'x le 2'。 相等運算式的範例:'x eq 5'。 不相等運算式的範例:'x ne 5'。 |
篩選 Collection(Edm.DateTimeOffset) 、Collection(Edm.Double) 、Collection(Edm.Int32) 或 Collection(Edm.Int64) 類型的欄位 |
篩選可比較集合的規則 |
不正確 Lambda 運算式。 在 Lambda 運算式中找到不支援使用 geo.distance() 或 geo.intersects(),該運算式會逐一查看 Collection(Edm.GeographyPoint) 類型的欄位。 針對 'any',請務必使用 'lt' 或 'le' 運算子來比較 geo.distance(),並且確定未否定 geo.intersects() 的任何使用方式。 針對 'all',請務必使用 'gt' 或 'ge' 運算子來比較 geo.distance(),並且確定否定 geo.intersects() 的任何使用方式。 | 篩選 Collection(Edm.GeographyPoint) 類型的欄位 |
篩選 GeographyPoint 集合的規則 |
不正確 Lambda 運算式。 複雜布林運算式在 Lambda 運算式中不受支援,該運算式會逐一查看 Collection(Edm.GeographyPoint) 類型的欄位。 針對 'any',請使用 'or' 聯結子運算式;不支援 'and'。 針對 'all',請使用 'and' 聯結子運算式;不支援 'or'。 | 篩選 Collection(Edm.String) 或 Collection(Edm.GeographyPoint) 類型的欄位 |
篩選字串集合的規則 篩選 GeographyPoint 集合的規則 |
不正確 Lambda 運算式。 找到比較運算子 ('lt'、'le'、'gt' 或 'ge' 其中一項)。 Lambda 運算式中只允許相等運算子,其會逐一查看 Collection(Edm.String) 類型的欄位。 針對 'any',請使用 'x eq y' 格式的運算式。 針對 'all',請使用 'x ne y' 或 'not (x eq y)' 格式的運算式。 | 篩選 Collection(Edm.String) 類型的欄位 |
篩選字串集合的規則 |
如何撰寫有效的集合篩選
寫入有效集合篩選的規則會針對每個資料類型不同。 下列各節說明規則的方式是顯示哪些篩選功能受支援、哪些篩選功能不受支援的範例:
篩選字串集合的規則
在字串集合的 Lambda 運算式內,唯一可以使用的比較運算子是 eq
和 ne
。
注意
Azure AI 搜尋服務不支援字串的 lt
/le
/gt
/ge
運算子,無論是在 Lambda 運算式內部或外部。
any
的主體只能測試是否相等,而 all
的主體只能測試不相等。
您也可以透過 any
的主體中的 or
,以及透過 all
的主體中的 and
,合併多個運算式。 由於 search.in
函式相當於將相等檢查與 or
合併,因此也允許在 any
的主體中。 相反地,在 all
的主體中允許 not search.in
。
例如,允許這些運算式:
tags/any(t: t eq 'books')
tags/any(t: search.in(t, 'books, games, toys'))
tags/all(t: t ne 'books')
tags/all(t: not (t eq 'books'))
tags/all(t: not search.in(t, 'books, games, toys'))
tags/any(t: t eq 'books' or t eq 'games')
tags/all(t: t ne 'books' and not (t eq 'games'))
但是不允許這些運算式:
tags/any(t: t ne 'books')
tags/any(t: not search.in(t, 'books, games, toys'))
tags/all(t: t eq 'books')
tags/all(t: search.in(t, 'books, games, toys'))
tags/any(t: t eq 'books' and t ne 'games')
tags/all(t: t ne 'books' or not (t eq 'games'))
篩選布林集合的規則
Edm.Boolean
類型僅支援 eq
和 ne
運算子。 因此,允許合併檢查相同範圍變數的這類子句與 and
/or
並無太大意義,因為這一律會導致恆真式或矛盾。
以下是允許之布林集合的一些篩選範例:
flags/any(f: f)
flags/all(f: f)
flags/any(f: f eq true)
flags/any(f: f ne true)
flags/all(f: not f)
flags/all(f: not (f eq true))
不同於字串集合,布林集合對哪些運算子可以用於哪一種 Lambda 運算式類型沒有限制。 eq
和 ne
都可以在 any
或 all
的主體中使用。
布林集合不允許下列運算式:
flags/any(f: f or not f)
flags/any(f: f or f)
flags/all(f: f and not f)
flags/all(f: f and f eq true)
篩選 GeographyPoint 集合的規則
集合中 Edm.GeographyPoint
類型的值無法彼此直接比較。 而是必須當做 geo.distance
和 geo.intersects
函式的參數使用。 geo.distance
函式必須接著使用其中一個比較運算子 lt
、le
、gt
或 ge
來比較距離值。 這些規則也適用於非集合 Edm.GeographyPoint 欄位。
就像字串集合一樣,Edm.GeographyPoint
集合對於如何使用地理空間函式,以及在不同類型的 Lambda 運算式中合併,也有一些規則:
- 您可以搭配
geo.distance
函式使用的比較運算子取決於 Lambda 運算式的類型。 針對any
,您只能使用lt
或le
。 針對all
,您只能使用gt
或ge
。 您可以否定涉及geo.distance
的運算式,但是您必須變更比較運算子 (geo.distance(...) lt x
變成not (geo.distance(...) ge x)
以及geo.distance(...) le x
變成not (geo.distance(...) gt x)
)。 - 在
all
的主體中,geo.intersects
函式必須被否定。 相反地,在any
的主體中,geo.intersects
函式不得否定。 - 在
any
的主體中,可以使用or
來結合地理空間運算式。 在all
的主體中,可以使用and
來結合此類運算式。
上述限制存在,原因類似字串集合的相等/不相等限制。 如需這些原因的詳細資訊,請參閱了解 Azure AI 搜尋服務中的 OData 集合篩選條件。
以下是允許之 Edm.GeographyPoint
集合的一些篩選範例:
locations/any(l: geo.distance(l, geography'POINT(-122 49)') lt 10)
locations/any(l: not (geo.distance(l, geography'POINT(-122 49)') ge 10) or geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
locations/all(l: geo.distance(l, geography'POINT(-122 49)') ge 10 and not geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
Edm.GeographyPoint
集合不允許下列運算式:
locations/any(l: l eq geography'POINT(-122 49)')
locations/any(l: not geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
locations/all(l: geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
locations/any(l: geo.distance(l, geography'POINT(-122 49)') gt 10)
locations/all(l: geo.distance(l, geography'POINT(-122 49)') lt 10)
locations/any(l: geo.distance(l, geography'POINT(-122 49)') lt 10 and geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
locations/all(l: geo.distance(l, geography'POINT(-122 49)') le 10 or not geo.intersects(l, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'))
篩選可比較集合的規則
本節適用於下列所有資料類型:
Collection(Edm.DateTimeOffset)
Collection(Edm.Double)
Collection(Edm.Int32)
Collection(Edm.Int64)
例如 Edm.Int32
和 Edm.DateTimeOffset
的類型支援所有六個比較運算子:eq
、ne
、lt
、le
、gt
和 ge
。 這些類型集合的 Lambda 運算式可以使用任何運算子來包含簡單運算式。 這同時適用於 any
與 all
。 例如,允許這些篩選:
ratings/any(r: r ne 5)
dates/any(d: d gt 2017-08-24T00:00:00Z)
not margins/all(m: m eq 3.5)
不過,在 Lambda 運算式內,這類比較運算式如何合併成更複雜的運算式有一些限制:
any
的規則:簡單不相等運算式無法與其他任何運算式搭配使用。 例如,允許此運算式:
ratings/any(r: r ne 5)
但是不允許此運算式:
ratings/any(r: r ne 5 and r gt 2)
雖然允許此運算式,但是因為條件重疊,所以並不實用:
ratings/any(r: r ne 5 or r gt 7)
涉及
eq
、lt
、le
、gt
或ge
的簡單比較運算式,可以與and
/or
合併。 例如:ratings/any(r: r gt 2 and r le 5)
ratings/any(r: r le 5 or r gt 7)
使用
and
(連接) 合併的比較運算式可以使用or
進一步合併。 這個形式在布林邏輯中稱為「析取範式」(DNF)。 例如:ratings/any(r: (r gt 2 and r le 5) or (r gt 7 and r lt 10))
all
的規則:簡單相等運算式無法與其他任何運算式搭配使用。 例如,允許此運算式:
ratings/all(r: r eq 5)
但是不允許此運算式:
ratings/all(r: r eq 5 or r le 2)
雖然允許此運算式,但是因為條件重疊,所以並不實用:
ratings/all(r: r eq 5 and r le 7)
涉及
ne
、lt
、le
、gt
或ge
的簡單比較運算式,可以與and
/or
合併。 例如:ratings/all(r: r gt 2 and r le 5)
ratings/all(r: r le 5 or r gt 7)
使用
or
(分離) 合併的比較運算式可以使用and
進一步合併。 這個形式在布林邏輯中稱為「合取範式」(CNF)。 例如:ratings/all(r: (r le 2 or gt 5) and (r lt 7 or r ge 10))
篩選複雜集合的規則
複雜集合的 Lambda 運算式,相較於基本類型集合的 Lambda 運算式,支援更有彈性的語法。 您可以在這類 Lambda 運算式內使用可在外部使用的任何篩選建構,但是只有兩個例外狀況。
首先,Lambda 運算式內不支援 search.ismatch
和 search.ismatchscoring
函式。 如需詳細資訊,請參閱了解 Azure AI 搜尋服務中的 OData 集合篩選條件。
其次,不允許參考未繫結至範圍變數 (所謂的自由變數) 的欄位。 例如,請考慮下列兩個對等的 OData 篩選運算式:
stores/any(s: s/amenities/any(a: a eq 'parking')) and details/margin gt 0.5
stores/any(s: s/amenities/any(a: a eq 'parking' and details/margin gt 0.5))
允許第一個運算式,但是拒絕第二個形式,因為 details/margin
未繫結至範圍變數 s
。
此規則也會延伸至在外部範圍中有繫結變數的運算式。 這類變數在出現範圍方面是自由的。 例如,允許第一個運算式,但是不允許第二個對等運算式,因為 s/name
在範圍變數 a
的範圍方面是自由的:
stores/any(s: s/amenities/any(a: a eq 'parking') and s/name ne 'Flagship')
stores/any(s: s/amenities/any(a: a eq 'parking' and s/name ne 'Flagship'))
這項限制不應該是實務上的問題,因為一律可以建構篩選,讓 Lambda 運算式只包含繫結變數。
收集篩選規則的速查表
下表摘要說明針對每個集合資料類型建構有效篩選的規則。
資料類型 | 使用 any 的 Lambda 運算式所允許的功能 |
使用 all 的 Lambda 運算式所允許的功能 |
---|---|---|
Collection(Edm.ComplexType) |
search.ismatch 和 search.ismatchscoring 以外的一切 |
相同 |
Collection(Edm.String) |
使用 eq 或 search.in 的比較 結合子運算式與 or |
使用 ne 或 not search.in() 的比較 結合子運算式與 and |
Collection(Edm.Boolean) |
使用 eq 或 ne 的比較 |
相同 |
Collection(Edm.GeographyPoint) |
使用 geo.distance 搭配 lt 或 le geo.intersects 結合子運算式與 or |
使用 geo.distance 搭配 gt 或 ge not geo.intersects(...) 結合子運算式與 and |
Collection(Edm.DateTimeOffset) , Collection(Edm.Double) , Collection(Edm.Int32) , Collection(Edm.Int64) |
使用 eq 、ne 、lt 、gt 、le 或 ge 的比較 使用 or 結合與其他子運算式的比較 使用 and 結合 ne 以外的其他子運算式的比較 在析取範式 (DNF) 中合併使用 and 和 or 的運算式 |
使用 eq 、ne 、lt 、gt 、le 或 ge 的比較 使用 and 結合與其他子運算式的比較 使用 or 結合 eq 以外的其他子運算式的比較 在合取範式 (CNF) 中合併使用 and 和 or 的運算式 |
如需如何為每個案例建構有效篩選的範例,請參閱如何撰寫有效的集合篩選。
如果您經常撰寫篩選,並了解第一個原則的規則可協助您記住,請參閱了解 Azure AI 搜尋服務中的 OData 集合篩選條件。