排查 Azure 认知搜索中的 OData 集合筛选器问题Troubleshooting OData collection filters in Azure Cognitive Search

若要根据 Azure 认知搜索中的集合字段进行筛选,可以结合 Lambda 表达式使用 anyall 运算符To filter on collection fields in Azure Cognitive Search, you can use the any and all operators together with lambda expressions. Lambda 表达式是应用到每个集合元素的子筛选器。A lambda expression is a sub-filter that is applied to each element of a collection.

并非每个筛选表达式功能都可在 Lambda 表达式中使用。Not every feature of filter expressions is available inside a lambda expression. 可用的功能因要筛选的集合字段的数据类型而异。Which features are available differs depending on the data type of the collection field that you want to filter. 如果你尝试在 Lambda 表达式中使用该上下文不支持的某个功能,可能会导致错误。This can result in an error if you try to use a feature in a lambda expression that isn't supported in that context. 如果你在尝试基于集合字段编写复杂的筛选器时遇到此类错误,本文可帮助你排查问题。If you're encountering such errors while trying to write a complex filter over collection fields, this article will help you troubleshoot the problem.

常见的集合筛选器错误Common collection filter errors

下表列出了在尝试执行集合筛选器时可能会遇到的错误。The following table lists errors that you might encounter when trying to execute a collection filter. 使用 Lambda 表达式中不支持的筛选表达式功能时,将发生这些错误。These errors happen when you use a feature of filter expressions that isn't supported inside a lambda expression. 每个错误提供了有关如何重写筛选器以避免该错误的一些指导。Each error gives some guidance on how you can rewrite your filter to avoid the error. 表格中还包含了本文相关部分的链接,其中提供了有关如何避免该错误的详细信息。The table also includes a link to the relevant section of this article that provides more information on how to avoid that error.

错误消息Error message 场景Situation 有关详细信息,请参阅For more information, see
函数 'ismatch' 没有任何参数绑定到范围变量的 's'。The function 'ismatch' has no parameters bound to the range variable 's'. Lambda 表达式中仅支持绑定的字段引用('any' 或 'all')。Only bound field references are supported inside lambda expressions ('any' or 'all'). 请更改筛选器,使 'ismatch' 函数位于 Lambda 表达式的外部,然后重试。Please change your filter so that the 'ismatch' function is outside the lambda expression and try again. 在 Lambda 表达式中使用 search.ismatchsearch.ismatchscoringUsing search.ismatch or search.ismatchscoring inside a lambda expression 有关筛选复杂集合的规则Rules for filtering complex collections
Lambda 表达式无效。Invalid lambda expression. 找到了一个相等性或不相等性测试,但循环访问 Collection(Edm.String) 类型的的字段的 Lambda 表达式预期需要相反的测试。Found a test for equality or inequality where the opposite was expected in a lambda expression that iterates over a field of type Collection(Edm.String). 对于 'any',请使用 'x eq y' 或 'search.in(...)' 格式的表达式。For 'any', please use expressions of the form 'x eq y' or 'search.in(...)'. 对于 'all',请使用 'x ne y'、'not (x eq y)' 或 'not search.in(...)' 格式的表达式。For 'all', please use expressions of the form 'x ne y', 'not (x eq y)', or 'not search.in(...)'. 根据 Collection(Edm.String) 类型的字段进行筛选Filtering on a field of type Collection(Edm.String) 有关筛选字符串集合的规则Rules for filtering string collections
Lambda 表达式无效。Invalid lambda expression. 找到了不受支持格式的复杂布尔表达式。Found an unsupported form of complex Boolean expression. 对于 'any',请使用“AND 的 OR”格式(也称为析取范式)的表达式。For 'any', please use expressions that are 'ORs of ANDs', also known as Disjunctive Normal Form. 例如:'(a and b) or (c and d)',其中 a、b、c 和 d 是比较或相等性子表达式。For example: '(a and b) or (c and d)' where a, b, c, and d are comparison or equality sub-expressions. 对于 'all',请使用“OR 的 AND”格式(也称为合取范式)的表达式。For 'all', please use expressions that are 'ANDs of ORs', also known as Conjunctive Normal Form. 例如:'(a or b) and (c or d)',其中 a、b、c 和 d 是比较或不相等性子表达式。For example: '(a or b) and (c or d)' where a, b, c, and d are comparison or inequality sub-expressions. 比较表达式的示例:'x gt 5'、'x le 2'。Examples of comparison expressions: 'x gt 5', 'x le 2'. 相等性表达式的示例:'x eq 5'。Example of an equality expression: 'x eq 5'. 不相等性表达式的示例:'x ne 5'。Example of an inequality expression: 'x ne 5'. 根据 Collection(Edm.DateTimeOffset)Collection(Edm.Double)Collection(Edm.Int32)Collection(Edm.Int64) 类型的字段进行筛选Filtering on fields of type Collection(Edm.DateTimeOffset), Collection(Edm.Double), Collection(Edm.Int32), or Collection(Edm.Int64) 有关筛选可比较集合的规则Rules for filtering comparable collections
Lambda 表达式无效。Invalid lambda expression. 在循环访问 Collection(Edm.GeographyPoint) 类型的字段的 Lambda 表达式中找到 geo.distance() 或 geo.intersects() 的不受支持用法。Found an unsupported use of geo.distance() or geo.intersects() in a lambda expression that iterates over a field of type Collection(Edm.GeographyPoint). 对于 'any',请确保使用 'lt' 或 'le' 运算符比较 geo.distance(),并确保不要对 geo.intersects() 的任何用法进行求反。For 'any', make sure you compare geo.distance() using the 'lt' or 'le' operators and make sure that any usage of geo.intersects() is not negated. 对于 'all',请确保使用 'gt' 或 'ge' 运算符比较 geo.distance(),并确保对 geo.intersects() 的任何用法进行求反。For 'all', make sure you compare geo.distance() using the 'gt' or 'ge' operators and make sure that any usage of geo.intersects() is negated. 根据 Collection(Edm.GeographyPoint) 类型的字段进行筛选Filtering on a field of type Collection(Edm.GeographyPoint) 有关筛选 GeographyPoint 集合的规则Rules for filtering GeographyPoint collections
Lambda 表达式无效。Invalid lambda expression. 循环访问 Collection(Edm.GeographyPoint) 类型的字段的 Lambda 表达式中不支持复杂布尔表达式。Complex Boolean expressions are not supported in lambda expressions that iterate over fields of type Collection(Edm.GeographyPoint). 对于 'any',请使用 'or' 联接子表达式;不支持 'and'。For 'any', please join sub-expressions with 'or'; 'and' is not supported. 对于 'all',请使用 'and' 联接子表达式;不支持 'or'。For 'all', please join sub-expressions with 'and'; 'or' is not supported. 根据 Collection(Edm.String)Collection(Edm.GeographyPoint) 类型的字段进行筛选Filtering on fields of type Collection(Edm.String) or Collection(Edm.GeographyPoint) 有关筛选字符串集合的规则Rules for filtering string collections

有关筛选 GeographyPoint 集合的规则Rules for filtering GeographyPoint collections
Lambda 表达式无效。Invalid lambda expression. 找到比较运算符(一个 'lt'、'le'、'gt' 或 'ge')。Found a comparison operator (one of 'lt', 'le', 'gt', or 'ge'). 循环访问 Collection(Edm.String) 类型的字段的 Lambda 表达式中只允许相等性运算符。Only equality operators are allowed in lambda expressions that iterate over fields of type Collection(Edm.String). 对于 'any',请使用 'x eq y' 格式的表达式。For 'any', please use expressions of the form 'x eq y'. 对于 'all',请使用 'x ne y' 或 'not (x eq y)' 格式的表达式。For 'all', please use expressions of the form 'x ne y' or 'not (x eq y)'. 根据 Collection(Edm.String) 类型的字段进行筛选Filtering on a field of type Collection(Edm.String) 有关筛选字符串集合的规则Rules for filtering string collections

如何编写有效的集合筛选器How to write valid collection filters

有关编写有效集合筛选器的规则对于每种数据类型各不相同。The rules for writing valid collection filters are different for each data type. 以下部分通过示例介绍了这些规则,其中指出了支持和不支持的筛选器功能:The following sections describe the rules by showing examples of which filter features are supported and which aren't:

有关筛选字符串集合的规则Rules for filtering string collections

在字符串集合的 Lambda 表达式中,只能使用 eqne 比较运算符。Inside lambda expressions for string collections, the only comparison operators that can be used are eq and ne.

备注

Azure 认知搜索不支持对字符串使用 lt/le/gt/ge 运算符,无论字符串是在 Lambda 表达式的内部还是外部。Azure Cognitive Search does not support the lt/le/gt/ge operators for strings, whether inside or outside a lambda expression.

只能在 any 的正文中测试相等性,只能在 all 的正文中测试不相等性。The body of an any can only test for equality while the body of an all can only test for inequality.

还可以通过 any 正文中的 or,以及通过 all 正文中的 and,来合并多个表达式。It's also possible to combine multiple expressions via or in the body of an any, and via and in the body of an all. 由于 search.in 函数等效于将相等性检查与 or 相结合,因此,any 的正文中也允许该函数。Since the search.in function is equivalent to combining equality checks with or, it's also allowed in the body of an any. 相比之下,all 的正文中允许 not search.inConversely, not search.in is allowed in the body of an all.

例如,允许以下表达式:For example, these expressions are allowed:

  • 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'))

不允许以下表达式:while these expressions aren't allowed:

  • 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'))

有关筛选布尔集合的规则Rules for filtering Boolean collections

类型 Edm.Boolean 仅支持 eqne 运算符。The type Edm.Boolean supports only the eq and ne operators. 因此,允许合并此类子句来检查包含 and/or 的相同范围变量的做法没有太大意义,因为这始终会导致同义反复或矛盾。As such, it doesn’t make much sense to allow combining such clauses that check the same range variable with and/or since that would always lead to tautologies or contradictions.

下面是允许的根据布尔集合进行筛选的一些示例:Here are some examples of filters on Boolean collections that are allowed:

  • 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 表达式中使用哪个运算符不设限制。Unlike string collections, Boolean collections have no limits on which operator can be used in which type of lambda expression. anyall 的正文中可以使用 eqneBoth eq and ne can be used in the body of any or all.

布尔集合不允许如下所示的表达式:Expressions such as the following aren't allowed for Boolean collections:

  • 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 集合的规则Rules for filtering GeographyPoint collections

集合中 Edm.GeographyPoint 类型的值不能直接相互比较。Values of type Edm.GeographyPoint in a collection can’t be compared directly to each other. 必须将它们用作 geo.distancegeo.intersects 函数的参数。Instead, they must be used as parameters to the geo.distance and geo.intersects functions. 然后,必须使用 ltlegtge 比较运算符将 geo.distance 函数与距离值进行比较。The geo.distance function in turn must be compared to a distance value using one of the comparison operators lt, le, gt, or ge. 这些规则也适用于非集合 Edm.GeographyPoint 字段。These rules also apply to non-collection Edm.GeographyPoint fields.

与字符串集合一样,Edm.GeographyPoint 集合在如何在不同类型的 Lambda 表达式中使用与合并地理空间函数方面也实施了一些规则:Like string collections, Edm.GeographyPoint collections have some rules for how the geo-spatial functions can be used and combined in the different types of lambda expressions:

  • 可在 geo.distance 函数中使用哪些比较运算符取决于 Lambda 表达式的类型。Which comparison operators you can use with the geo.distance function depends on the type of lambda expression. 对于 any,只能使用 ltleFor any, you can use only lt or le. 对于 all,只能使用 gtgeFor all, you can use only gt or ge. 可将涉及 geo.distance 的表达式求反,但必须更改比较运算符(geo.distance(...) lt x 更改为 not (geo.distance(...) ge x)geo.distance(...) le x 更改为 not (geo.distance(...) gt x))。You can negate expressions involving geo.distance, but you'll have to change the comparison operator (geo.distance(...) lt x becomes not (geo.distance(...) ge x) and geo.distance(...) le x becomes not (geo.distance(...) gt x)).
  • all 的正文中,必须将 geo.intersects 函数求反。In the body of an all, the geo.intersects function must be negated. 相反,在 any 的正文中,不得将 geo.intersects 函数求反。Conversely, in the body of an any, the geo.intersects function must not be negated.
  • any 的正文中,可以使用 or 来合并地理空间表达式。In the body of an any, geo-spatial expressions can be combined using or. all 的正文中,可以使用 and 来合并此类表达式。In the body of an all, such expressions can be combined using and.

之所以存在上述限制,是因为字符串集合存在类似的相等性/不相等性限制。The above limitations exist for similar reasons as the equality/inequality limitation on string collections. 若要深入了解这些原因,请参阅了解 Azure 认知搜索中的 OData 集合筛选器See Understanding OData collection filters in Azure Cognitive Search for a deeper look at these reasons.

下面是允许的根据 Edm.GeographyPoint 集合进行筛选的一些示例:Here are some examples of filters on Edm.GeographyPoint collections that are allowed:

  • 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 集合不允许如下所示的表达式:Expressions such as the following are not allowed for Edm.GeographyPoint collections:

  • 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))'))

有关筛选可比较集合的规则Rules for filtering comparable collections

本部分适用于以下所有数据类型:This section applies to all the following data types:

  • Collection(Edm.DateTimeOffset)
  • Collection(Edm.Double)
  • Collection(Edm.Int32)
  • Collection(Edm.Int64)

Edm.Int32Edm.DateTimeOffset 等类型支持所有六个比较运算符:eqneltlegtgeTypes such as Edm.Int32 and Edm.DateTimeOffset support all six of the comparison operators: eq, ne, lt, le, gt, and ge. 这些类型的集合上的 Lambda 表达式可以包含使用上述任一运算符的简单表达式。Lambda expressions over collections of these types can contain simple expressions using any of these operators. 这适用于 anyallThis applies to both any and all. 例如,允许以下筛选器:For example, these filters are allowed:

  • 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 表达式中将此类比较表达式合并成更复杂的表达式方面存在一些限制:However, there are limitations on how such comparison expressions can be combined into more complex expressions inside a lambda expression:

  • 适用于 any 的规则:Rules for any:
    • 简单的不相等性表达式不能有效地与任何其他表达式合并。Simple inequality expressions can't be usefully combined with any other expressions. 例如,允许以下表达式:For example, this expression is allowed:

      • ratings/any(r: r ne 5)

      但不允许以下表达式:but this expression isn't:

      • ratings/any(r: r ne 5 and r gt 2)

      尽管允许此表达式,但由于条件重叠,此表达式没有作用:and while this expression is allowed, it isn't useful because the conditions overlap:

      • ratings/any(r: r ne 5 or r gt 7)
    • 涉及 eqltlegtge 的简单比较表达式可与 and/or 合并。Simple comparison expressions involving eq, lt, le, gt, or ge can be combined with and/or. 例如:For example:

      • ratings/any(r: r gt 2 and r le 5)
      • ratings/any(r: r le 5 or r gt 7)
    • 使用 and(合取)合并的比较表达式可以通过 or 进一步合并。Comparison expressions combined with and (conjunctions) can be further combined using or. 此格式在布尔逻辑中称为“析取范式”(DNF)。This form is known in Boolean logic as "Disjunctive Normal Form" (DNF). 例如:For example:

      • ratings/any(r: (r gt 2 and r le 5) or (r gt 7 and r lt 10))
  • 适用于 all 的规则:Rules for all:
    • 简单的相等性表达式不能有效地与任何其他表达式合并。Simple equality expressions can't be usefully combined with any other expressions. 例如,允许以下表达式:For example, this expression is allowed:

      • ratings/all(r: r eq 5)

      但不允许以下表达式:but this expression isn't:

      • ratings/all(r: r eq 5 or r le 2)

      尽管允许此表达式,但由于条件重叠,此表达式没有作用:and while this expression is allowed, it isn't useful because the conditions overlap:

      • ratings/all(r: r eq 5 and r le 7)
    • 涉及 neltlegtge 的简单比较表达式可与 and/or 合并。Simple comparison expressions involving ne, lt, le, gt, or ge can be combined with and/or. 例如:For example:

      • ratings/all(r: r gt 2 and r le 5)
      • ratings/all(r: r le 5 or r gt 7)
    • 使用 or(析取)合并的比较表达式可以通过 and 进一步合并。Comparison expressions combined with or (disjunctions) can be further combined using and. 此格式在布尔逻辑中称为“合取范式”(CNF)。This form is known in Boolean logic as "Conjunctive Normal Form" (CNF). 例如:For example:

      • ratings/all(r: (r le 2 or gt 5) and (r lt 7 or r ge 10))

有关筛选复杂集合的规则Rules for filtering complex collections

基于复杂集合的 Lambda 表达式支持的语法比基于基元类型的集合的 Lambda 表达式更灵活。Lambda expressions over complex collections support a much more flexible syntax than lambda expressions over collections of primitive types. 可在外部使用的任何筛选器构造也可以在此类 Lambda 表达式内部使用,只存在两种例外情况。You can use any filter construct inside such a lambda expression that you can use outside one, with only two exceptions.

第一,Lambda 表达式中不支持 search.ismatchsearch.ismatchscoring 函数。First, the functions search.ismatch and search.ismatchscoring aren't supported inside lambda expressions. 有关详细信息,请参阅了解 Azure 认知搜索中的 OData 集合筛选器For more information, see Understanding OData collection filters in Azure Cognitive Search.

第二,不允许引用未绑定到范围变量(所谓的“自由变量”)的字段。 Second, referencing fields that aren't bound to the range variable (so-called free variables) isn't allowed. 例如,考虑以下两个等效的 OData 筛选表达式:For example, consider the following two equivalent OData filter expressions:

  1. stores/any(s: s/amenities/any(a: a eq 'parking')) and details/margin gt 0.5
  2. stores/any(s: s/amenities/any(a: a eq 'parking' and details/margin gt 0.5))

将允许第一个表达式,而第二种格式将被拒绝,因为 details/margin 未绑定到范围变量 sThe first expression will be allowed, while the second form will be rejected because details/margin isn't bound to the range variable s.

此规则还会延伸到在外部范围中绑定了变量的表达式。This rule also extends to expressions that have variables bound in an outer scope. 此类变量的显示范围是自由的。Such variables are free with respect to the scope in which they appear. 例如,允许第一个表达式,但不允许第二个等效的表达式,因为 s/name 相对于范围变量 a 的范围是自由的:For example, the first expression is allowed, while the second equivalent expression isn't allowed because s/name is free with respect to the scope of the range variable a:

  1. stores/any(s: s/amenities/any(a: a eq 'parking') and s/name ne 'Flagship')
  2. stores/any(s: s/amenities/any(a: a eq 'parking' and s/name ne 'Flagship'))

在实践中,此限制应该不是一个问题,因为始终可以构造筛选器,使 Lambda 表达式只包含绑定的变量。This limitation shouldn't be a problem in practice since it's always possible to construct filters such that lambda expressions contain only bound variables.

集合筛选器规则速查表Cheat sheet for collection filter rules

下表汇总了有关为每个集合数据类型构建有效筛选器的规则。The following table summarizes the rules for constructing valid filters for each collection data type.

数据类型Data type any 的 lambda 表达式中允许的功能Features allowed in lambda expressions with any all 的 lambda 表达式中允许的功能Features allowed in lambda expressions with all
Collection(Edm.ComplexType) search.ismatchsearch.ismatchscoring 外的所有内容Everything except search.ismatch and search.ismatchscoring 相同Same
Collection(Edm.String) 使用 eqsearch.in 进行比较Comparisons with eq or search.in

使用 or 组合子表达式Combining sub-expressions with or
使用 nenot search.in() 进行比较Comparisons with ne or not search.in()

使用 and 组合子表达式Combining sub-expressions with and
Collection(Edm.Boolean) 使用 eqne 进行比较Comparisons with eq or ne 相同Same
Collection(Edm.GeographyPoint) geo.distanceltle 配合使用Using geo.distance with lt or le

geo.intersects

使用 or 组合子表达式Combining sub-expressions with or
geo.distancegtge 配合使用Using geo.distance with gt or ge

not geo.intersects(...)

使用 and 组合子表达式Combining sub-expressions with and
Collection(Edm.DateTimeOffset)Collection(Edm.Double)Collection(Edm.Int32)Collection(Edm.Int64)Collection(Edm.DateTimeOffset), Collection(Edm.Double), Collection(Edm.Int32), Collection(Edm.Int64) 使用 eqneltgtlege 进行比较Comparisons using eq, ne, lt, gt, le, or ge

使用 or 将比较与其他子表达式组合Combining comparisons with other sub-expressions using or

使用 and 将除 ne 以外的比较与其他子表达式组合Combining comparisons except ne with other sub-expressions using and

在析取范式 (DNF) 中使用 andor 组合的表达式Expressions using combinations of and and or in Disjunctive Normal Form (DNF)
使用 eqneltgtlege 进行比较Comparisons using eq, ne, lt, gt, le, or ge

使用 and 将比较与其他子表达式组合Combining comparisons with other sub-expressions using and

使用 or 将除 eq 以外的比较与其他子表达式组合Combining comparisons except eq with other sub-expressions using or

在合取范式 (CNF) 中使用 andor 组合的表达式Expressions using combinations of and and or in Conjunctive Normal Form (CNF)

有关如何为每个用例的构建有效筛选器的示例,请参阅如何编写有效的集合筛选器For examples of how to construct valid filters for each case, see How to write valid collection filters.

如果你经常编写筛选器,并且知道从首要原理上理解规则能够带来更大的帮助,而不仅仅是有助于记住这些规则,那么,请参阅了解 Azure 认知搜索中的 OData 集合筛选器If you write filters often, and understanding the rules from first principles would help you more than just memorizing them, see Understanding OData collection filters in Azure Cognitive Search.

后续步骤Next steps