Solução de problemas de filtros de coleção OData na Pesquisa de IA do Azure
Para filtrar campos de coleção no Azure AI Search, você pode usar os any
operadores e all
junto com expressões lambda. Uma expressão lambda é um subfiltro que é aplicado a cada elemento de uma coleção.
Nem todos os recursos de expressões de filtro estão disponíveis dentro de uma expressão lambda. Os recursos disponíveis diferem dependendo do tipo de dados do campo de coleta que você deseja filtrar. Isso pode resultar em um erro se você tentar usar um recurso em uma expressão lambda que não é suportada nesse contexto. Se você estiver encontrando esses erros ao tentar escrever um filtro complexo sobre campos de coleção, este artigo irá ajudá-lo a solucionar o problema.
Erros comuns do filtro de coleta
A tabela a seguir lista os erros que você pode encontrar ao tentar executar um filtro de coleção. Esses erros acontecem quando você usa um recurso de expressões de filtro que não é suportado dentro de uma expressão lambda. Cada erro fornece algumas orientações 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 ligados à variável de intervalo 's'. Apenas referências de campos acoplados são suportadas dentro de expressões lambda ('qualquer' ou 'todos'). No entanto, você pode alterar o filtro para que a ismatch função 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. Encontrado um teste para igualdade ou desigualdade onde o oposto era esperado em uma expressão lambda que itera sobre um campo do tipo Collection(Edm.String). Para «qualquer», utilizar expressões sob a forma «x eq y» ou «search.in(...)». Para «todos», utilizar expressões sob a forma «x ne y», «not (x eq y)» ou «not search.in(...)». | Filtragem num campo do tipo Collection(Edm.String) |
Regras para filtrar coleções de cadeias de caracteres |
Expressão lambda inválida. Encontrou uma forma sem suporte de expressão booleana complexa. Para 'qualquer', use expressões que são 'ORs de E', também conhecida como Forma Normal Disjuntiva. Por exemplo: (a and b) or (c and d) onde a, b, c e d são subexpressões de comparação ou igualdade. Para 'todos', use expressões que são 'Es de RUPs', também conhecida como Forma Normal Conjuntiva. Por exemplo: (a or b) and (c or d) onde a, b, c e d são subexpressões de comparação ou 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 filtrar coleções comparáveis |
Expressão lambda inválida. Encontrado um uso não suportado de geo.distance() ou geo.intersects() em uma expressão lambda que itera sobre um campo do tipo Collection(Edm.GeographyPoint). Para 'qualquer', certifique-se de comparar geo.distance() usando os operadores 'lt' ou 'le' e certifique-se de que qualquer uso de geo.intersects() não seja 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 num campo do tipo Collection(Edm.GeographyPoint) |
Regras para filtrar coleções GeographyPoint |
Expressão lambda inválida. Não há suporte para expressões booleanas complexas em expressões lambda que iteram em campos do tipo Collection(Edm.GeographyPoint). Para 'qualquer', junte subexpressões com 'ou'; 'e' não é suportado. Para 'todos', junte subexpressões com 'e'; 'ou' não é suportado. | Filtragem em campos do tipo Collection(Edm.String) ou Collection(Edm.GeographyPoint) |
Regras para filtrar coleções de cadeias de caracteres Regras para filtrar 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 Collection(Edm.String). Para «qualquer», se expressões da forma «x eq y». Para «todos», utilizar expressões da forma «x ne y» ou «not (x eq y)». | Filtragem num 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 escrever 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 são suportados e quais não são:
- Regras para filtrar coleções de cadeias de caracteres
- Regras para filtrar coleções booleanas
- Regras para filtrar coleções GeographyPoint
- Regras para filtrar coleções comparáveis
- Regras para filtrar coleções complexas
Regras para filtrar coleções de cadeias de caracteres
Dentro de expressões lambda para coleções de cadeias de caracteres, os únicos operadores de comparação que podem ser usados são eq
e ne
.
Nota
O Azure AI Search não oferece suporte aos lt
gt
ge
/le
//operadores para cadeias de caracteres, seja 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 a desigualdade.
Também é possível combinar múltiplas expressões via or
no corpo de um any
, e via and
no corpo de um all
. Uma vez que a search.in
função é equivalente a combinar verificações de igualdade com or
, também é permitida no corpo de um any
. Por outro lado, not search.in
é permitido no corpo de um all
arquivo .
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'))
Embora estas expressões não sejam 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 filtrar coleções booleanas
O tipo Edm.Boolean
suporta apenas os eq
operadores e ne
. Como tal, não faz muito sentido permitir a combinação de tais cláusulas que verificam a mesma variável and
/or
de intervalo, uma vez que isso levaria sempre a tautologias ou contradições.
Aqui estão alguns exemplos de filtros em coleções booleanas 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 cadeia de caracteres, as coleções booleanas 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 booleanas:
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 filtrar 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 geo.distance
funções e geo.intersects
. A geo.distance
função, por sua vez, deve ser comparada a um valor de distância usando um dos operadores lt
de comparação , , le
gt
, ou ge
. Essas regras também se aplicam a campos Edm.GeographyPoint não colecionados.
Como as coleções de cadeias de caracteres, Edm.GeographyPoint
as coleções têm algumas regras para como as funções geoespaciais podem ser usadas e combinadas nos diferentes tipos de expressões lambda:
- Os operadores de comparação que você pode usar com a
geo.distance
função dependem do tipo de expressão lambda. Paraany
, você pode usar apenaslt
oule
. Paraall
, você pode usar apenasgt
ouge
. Você pode negar expressões envolvendogeo.distance
, mas você tem que mudar 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
, ageo.intersects
função deve ser negada. Por outro lado, no corpo de umany
, ageo.intersects
função não deve ser negada. - No corpo de um
any
, as expressões geoespaciais podem ser combinadas usandoor
. No corpo de umall
, tais expressões podem ser combinadas usandoand
.
As limitações acima existem por razões semelhantes à limitação de igualdade/desigualdade em coleções de cordas. Consulte Noções básicas sobre filtros de coleção OData na Pesquisa de IA do Azure para obter uma visão mais profunda desses motivos.
Aqui estão alguns exemplos de filtros em Edm.GeographyPoint
coleções 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 as seguintes não são permitidas para Edm.GeographyPoint
coleções:
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 filtrar coleções comparáveis
Esta secção aplica-se 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
suportam todos os seis operadores de comparação: eq
, ne
, lt
, le
, gt
e ge
. Expressões do Lambda sobre coleções desses tipos podem conter expressões simples usando qualquer um desses operadores. Isto aplica-se a ambos e any
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 tais expressões de comparação podem ser combinadas em expressões mais complexas dentro de uma expressão lambda:
- Regras para
any
:Expressões simples de desigualdade não podem ser utilmente combinadas com quaisquer outras expressões. Por exemplo, esta expressão é permitida:
ratings/any(r: r ne 5)
mas esta expressão não é:
ratings/any(r: r ne 5 and r gt 2)
e embora esta expressão seja permitida, 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 , , , , ou
ge
podem ser combinadas com/or
and
.gt
le
lt
eq
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
. Esta forma é conhecida na lógica booleana como "Forma Normal Disjuntiva" (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 simples de igualdade não podem ser combinadas utilmente com outras expressões. Por exemplo, esta expressão é permitida:
ratings/all(r: r eq 5)
mas esta expressão não é:
ratings/all(r: r eq 5 or r le 2)
e embora esta expressão seja permitida, 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 , , , , ou
ge
podem ser combinadas com/or
and
.gt
le
lt
ne
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
. Esta forma é conhecida na lógica booleana como "Forma Normal Conjuntiva" (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 suportam uma sintaxe muito mais flexível do que expressões lambda sobre coleções de tipos primitivos. Você pode usar qualquer construção 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 são suportadas dentro de expressões lambda. Para obter mais informações, consulte Noções básicas sobre filtros de coleção OData no Azure AI Search.
Em segundo lugar, não é permitida a referência a campos que não estão vinculados à variável range (as chamadas variáveis livres). 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 é permitida, enquanto a segunda forma é rejeitada porque details/margin
não está vinculada à variável s
range .
Essa regra também se estende a expressões que têm variáveis vinculadas em um escopo externo. Tais variáveis são livres no que diz respeito ao âmbito em que aparecem. Por exemplo, a primeira expressão é permitida, enquanto a segunda expressão equivalente não é permitida porque s/name
é livre em relação ao escopo da variável a
range :
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, já que é sempre possível construir filtros de modo que as expressões lambda contenham apenas variáveis vinculadas.
Cheat sheet para regras de filtro de coleta
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 |
Mesma |
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 |
Mesma |
Collection(Edm.GeographyPoint) |
Utilizar geo.distance com lt ou le geo.intersects Combinando subexpressões com or |
Utilizar 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 Combinação de 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 Combinação de comparações, exceto eq com outras subexpressões usando or Expressões usando combinações de and e or na Forma Normal 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ê escreve filtros com frequência, e entender as regras a partir dos primeiros princípios ajudaria mais do que apenas memorizá-las, consulte Noções básicas sobre filtros de coleção OData no Azure AI Search.