Solução de problemas de filtros de coleção OData no IA do Azure Search
Para filtrar em campos de coleção no IA do Azure Search, você pode usar os operadores any
e all
juntamente com expressões lambda. Uma expressão lambda é um subfiltro que é aplicado a cada elemento de uma coleção.
Nem todo recurso de expressões de filtro está disponível dentro de uma expressão lambda. Quais recursos estão disponíveis diferem dependendo do tipo de dados do campo de coleção que você deseja filtrar. Isso pode resultar em um erro se você tentar usar um recurso em uma expressão lambda que não tenha suporte nesse contexto. Se você estiver encontrando esses erros ao tentar escrever um filtro complexo nos campos de coleção, este artigo o ajudará a solucionar o problema.
Erros comuns de filtros de coleção
A tabela a seguir lista os erros que você pode encontrar ao tentar executar um filtro de coleção. Esses erros ocorrem quando você usa um recurso de expressões de filtro que não tem suporte dentro de uma expressão lambda. Cada erro fornece algumas diretrizes sobre como você pode reescrever seu filtro para evitar o erro. A tabela também inclui um link para a seção relevante deste artigo que fornece mais informações sobre como evitar esse erro.
Mensagem de erro | Situação | Detalhes |
---|---|---|
A função ismatch não tem parâmetros associados ao 's' da variável de intervalo. Só há suporte para referências de campo associadas dentro de expressões lambda ('qualquer' ou 'todos'). No entanto, você pode alterar o filtro para que a função ismatch esteja fora da expressão lambda e tentar novamente. |
Usando search.ismatch ou search.ismatchscoring dentro de uma expressão lambda |
Regras para filtrar coleções complexas |
Expressão lambda inválida. Foi encontrado um teste para igualdade ou desigualdade em que o oposto era esperado em uma expressão lambda que itera em um campo do tipo Coleção (Edm.String). Para 'any', use expressões do formato 'x eq y' ou 'search.in(...)'. Para 'all', use expressões do formulário 'x ne y', 'not (x eq y)' ou 'not search.in(...)'. | Filtragem em um campo do tipo Collection(Edm.String) |
Regras para filtrar coleções de cadeias de caracteres |
Expressão lambda inválida. Encontrada uma forma sem suporte de expressão booliana complexa. Para 'any', use expressões que são 'ORs of ANDs', também conhecidas como Formulário Normal Disjuntivo. Por exemplo: (a and b) or (c and d) , em que a, b, c e d são subexpressões de comparação ou de igualdade. Para 'all', use expressões que são 'ANDs de ORs', também conhecidas como Formulário Normal Conjuntivo. Por exemplo: (a or b) and (c or d) , em que a, b, c e d são subexpressões de comparação ou de desigualdade. Exemplos de expressões de comparação: 'x gt 5', 'x le 2'. Exemplo de uma expressão de igualdade: 'x eq 5'. Exemplo de uma expressão de desigualdade: 'x ne 5'. |
Filtragem em campos do tipo Collection(Edm.DateTimeOffset) , Collection(Edm.Double) , Collection(Edm.Int32) ou Collection(Edm.Int64) |
Regras para filtragem de coleções comparáveis |
Expressão lambda inválida. Foi encontrado um uso sem suporte de geo.distance() or geo.intersects() em uma expressão lambda que itera sobre um campo do tipo Coleção (Edm.GeographyPoint). Para 'any', verifique se você compara geo.distance() usando os operadores 'lt' ou 'le' e verifique se qualquer uso de geo.intersects() não está negado. Para 'todos', certifique-se de comparar geo.distance() usando os operadores 'gt' ou 'ge' e certifique-se de que qualquer uso de geo.intersects() seja negado. | Filtragem em um campo do tipo Collection(Edm.GeographyPoint) |
Regras para filtragem de coleções GeographyPoint |
Expressão lambda inválida. Expressões boolianas complexas não têm suporte em expressões lambda que iteram em campos do tipo Collection(Edm.GeographyPoint). Para "any", junte subexpressões com "or". Não há suporte para "and". Para "all", junte subexpressões com "and"; Não há suporte para "or". | Filtragem em campos do tipo Collection(Edm.String) ou Collection(Edm.GeographyPoint) |
Regras para filtrar coleções de cadeias de caracteres Regras para filtragem de coleções GeographyPoint |
Expressão lambda inválida. Encontrado um operador de comparação (um de 'lt', 'le', 'gt' ou 'ge'). Somente operadores de igualdade são permitidos em expressões lambda que iteram sobre campos do tipo Coleção (Edm.String). Para 'any', se expressões do formulário 'x eq y'. Para 'all', use expressões da forma 'x ne y' ou 'not (x eq y)'. | Filtragem em um campo do tipo Collection(Edm.String) |
Regras para filtrar coleções de cadeias de caracteres |
Como escrever filtros de coleção válidos
As regras para gravar filtros de coleção válidos são diferentes para cada tipo de dados. As seções a seguir descrevem as regras mostrando exemplos de quais recursos de filtro têm suporte e quais não têm:
- Regras para filtrar coleções de cadeias de caracteres
- Regras para filtragem de coleções boolianas
- Regras para filtragem de coleções GeographyPoint
- Regras para filtragem de coleções comparáveis
- Regras para filtrar coleções complexas
Regras para filtrar coleções de cadeias de caracteres
Em expressões lambda para coleções de cadeia de caracteres. somente os operadores de comparação que podem ser usados são eq
e ne
.
Observação
O IA do Azure Search não dá suporte aos operadores lt
/le
//gt
ge
para cadeias de caracteres, dentro ou fora de uma expressão lambda.
O corpo de um any
só pode testar a igualdade enquanto o corpo de um all
só pode testar desigualdade.
Também é possível combinar várias expressões por meio do or
corpo de um any
, e por meio do and
corpo de um all
. Como a função search.in
é equivalente à combinação de verificações de igualdade com or
, ela também é permitida no corpo de um any
. Por outro lado, not search.in
é permitido no corpo de um all
.
Por exemplo, estas expressões são permitidas:
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'))
Enquanto essas expressões não são permitidas:
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'))
Regras para filtragem de coleções boolianas
O tipo Edm.Boolean
oferece suporte apenas eq
e operadores ne
. Assim, não faz muito sentido permitir a combinação dessas cláusulas que verificam a mesma variável de intervalo com and
/or
, pois isso sempre levaria a tautologias ou contraditórias.
Aqui estão alguns exemplos de filtros em coleções boolianas que são permitidos:
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))
Ao contrário das coleções de cadeias de caracteres, as coleções boolianas não têm limites sobre qual operador pode ser usado em qual tipo de expressão lambda. Ambos eq
e ne
podem ser usados no corpo de any
ou all
.
Expressões como as seguintes não são permitidas para coleções boolianas:
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)
Regras para filtragem de coleções GeographyPoint
Os valores do tipo Edm.GeographyPoint
em uma coleção não podem ser comparados diretamente entre si. Em vez disso, eles devem ser usados como parâmetros para as funções geo.distance
e geo.intersects
. A funçãogeo.distance
, por sua vez, deve ser comparada a um valor de distância usando um dos operadores de comparação lt
, le
, gt
ou ge
. Essas regras também se aplicam aos campos de não coleção Edm.GeographyPoint.
Como as coleções de cadeias de caracteres, as coleçõesEdm.GeographyPoint
têm algumas regras para como as funções geoespaciais podem ser usadas e combinadas nos diferentes tipos de expressões lambda:
- Quais operadores de comparação que você pode usar com a função
geo.distance
depende do tipo de expressão lambda. Paraany
, você pode usar apenaslt
oule
. Paraall
, você pode usar apenasgt
ouge
. Você pode negar as expressões que envolvemgeo.distance
, mas precisará alterar o operador de comparação (geo.distance(...) lt x
torna-senot (geo.distance(...) ge x)
egeo.distance(...) le x
torna-senot (geo.distance(...) gt x)
). - No corpo de um
all
, a funçãogeo.intersects
deve ser negada. Por outro lado, no corpo de umany
, a funçãogeo.intersects
não deve ser negada. - No corpo de um
any
, as expressões geoespaciais podem ser combinadas usandoor
. No corpo de umall
, essas expressões podem ser combinadas usandoand
.
As limitações acima existem por motivos semelhantes como a limitação de igualdade/desigualdade em coleções de cadeias de caracteres. Consulte Noções básicas sobre filtros de coleção OData no IA do Azure Search para ver mais detalhadamente esses motivos.
Aqui estão alguns exemplos de filtros em coleções Edm.GeographyPoint
que são permitidos:
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))'))
Expressões como a seguinte não são permitidas para coleções 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))'))
Regras para filtragem de coleções comparáveis
Esta seção se aplica a todos os seguintes tipos de dados:
Collection(Edm.DateTimeOffset)
Collection(Edm.Double)
Collection(Edm.Int32)
Collection(Edm.Int64)
Tipos como Edm.Int32
e Edm.DateTimeOffset
dão suporte a todos os seis operadores de comparação: eq
, ne
, lt
, le
, gt
e ge
. Expressões lambda sobre coleções desses tipos podem conter expressões simples usando qualquer um desses operadores. Isso se aplica a ambos any
e all
. Por exemplo, estes filtros são permitidos:
ratings/any(r: r ne 5)
dates/any(d: d gt 2017-08-24T00:00:00Z)
not margins/all(m: m eq 3.5)
No entanto, há limitações sobre como essas expressões de comparação podem ser combinadas em expressões mais complexas dentro de uma expressão lambda:
- Regras para
any
:Expressões de desigualdade simples não podem ser combinadas de forma útil com nenhuma outra expressão. Por exemplo, essa expressão é permitida:
ratings/any(r: r ne 5)
Mas essa expressão não é:
ratings/any(r: r ne 5 and r gt 2)
e embora essa expressão seja permitida, ela não é útil porque as condições se sobrepõem:
ratings/any(r: r ne 5 or r gt 7)
Expressões de comparação simples envolvendo
eq
,lt
,le
,gt
ouge
podem ser combinadas comand
/or
. Por exemplo:ratings/any(r: r gt 2 and r le 5)
ratings/any(r: r le 5 or r gt 7)
Expressões de comparação combinadas com
and
(conjunções) podem ser combinadas usandoor
. Esse formulário é conhecido em lógica booliana como "Formulário Normal Disjuntivo" (DNF). Por exemplo:ratings/any(r: (r gt 2 and r le 5) or (r gt 7 and r lt 10))
- Regras para
all
:Expressões de igualdade simples não podem ser combinadas de forma útil com nenhuma outra expressão. Por exemplo, essa expressão é permitida:
ratings/all(r: r eq 5)
Mas essa expressão não é:
ratings/all(r: r eq 5 or r le 2)
e embora essa expressão seja permitida, ela não é útil porque as condições se sobrepõem:
ratings/all(r: r eq 5 and r le 7)
Expressões de comparação simples envolvendo
ne
,lt
,le
,gt
ouge
podem ser combinadas comand
/or
. Por exemplo:ratings/all(r: r gt 2 and r le 5)
ratings/all(r: r le 5 or r gt 7)
Expressões de comparação combinadas com
or
(disjunções) podem ser combinadas usandoand
. Esse formulário é conhecido em lógica booliana como "Formulário Normal Conjuntivo" (CNF). Por exemplo:ratings/all(r: (r le 2 or gt 5) and (r lt 7 or r ge 10))
Regras para filtrar coleções complexas
Expressões lambda sobre coleções complexas dão suporte a uma sintaxe muito mais flexível do que expressões lambda em coleções de tipos primitivos. Você pode usar qualquer constructo de filtro dentro de uma expressão lambda que você pode usar fora de uma, com apenas duas exceções.
Primeiro, as funções search.ismatch
e search.ismatchscoring
não têm suporte dentro de expressões lambda. Para obter mais informações, consulte Noções básicas sobre filtros de coleção OData no IA do Azure Search.
Segundo, a referência de campos que não estão associados à variável de intervalo (chamadas de variáveis livres) não é permitida. Por exemplo, considere as duas expressões de filtro OData equivalentes a seguir:
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))
A primeira expressão será permitida, enquanto o segundo formulário será rejeitado porque details/margin
não está associado à variável de intervalo s
.
Essa regra também se estende a expressões que têm variáveis associadas em um escopo externo. Essas variáveis são gratuitas em relação ao escopo no qual aparecem. Por exemplo, a primeira expressão é permitida, enquanto a segunda expressão equivalente não é permitida porque s/name
é gratuita em relação ao escopo da variável de intervalo 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'))
Essa limitação não deve ser um problema na prática, pois sempre é possível construir filtros, de modo que as expressões lambda contenham apenas variáveis associadas.
Roteiro para regras de filtro de coleção
A tabela a seguir resume as regras para construir filtros válidos para cada tipo de dados de coleção.
Tipo de dados | Recursos permitidos em expressões lambda com any |
Recursos permitidos em expressões lambda com all |
---|---|---|
Collection(Edm.ComplexType) |
Tudo exceto search.ismatch e search.ismatchscoring |
Idêntico |
Collection(Edm.String) |
Comparações com eq ou search.in Combinando subexpressões com or |
Comparações com ne ou not search.in() Combinando subexpressões com and |
Collection(Edm.Boolean) |
Comparações com eq ou ne |
Idêntico |
Collection(Edm.GeographyPoint) |
Usando geo.distance com lt ou le geo.intersects Combinando subexpressões com or |
Usando geo.distance com gt ou ge not geo.intersects(...) Combinando subexpressões com and |
Collection(Edm.DateTimeOffset) , Collection(Edm.Double) , Collection(Edm.Int32) , Collection(Edm.Int64) |
Comparações usando eq , ne , lt , gt , le ou ge Combinando comparações com outras subexpressões usando or Combinar comparações, exceto ne com outras subexpressões usando and Expressões usando combinações de and e or na forma normal disjuntiva (DNF) |
Comparações usando eq , ne , lt , gt , le ou ge Combinando comparações com outras subexpressões usando and Combinar comparações, exceto eq com outras subexpressões usando or Expressões usando combinações de and e or no formato normal de conjuntiva (CNF) |
Para obter exemplos de como construir filtros válidos para cada caso, consulte Como escrever filtros de coleção válidos.
Se você escrever filtros com frequência e entender as regras dos primeiros princípios o ajudará mais do que apenas memorizá-los, consulte Noções básicas sobre filtros de coleção OData no IA do Azure Search.