Compartilhar via


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

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//gtge 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. Para any, você pode usar apenas lt ou le. Para all, você pode usar apenas gt ou ge. Você pode negar as expressões que envolvem geo.distance, mas precisará alterar o operador de comparação (geo.distance(...) lt x torna-se not (geo.distance(...) ge x) e geo.distance(...) le x torna-se not (geo.distance(...) gt x)).
  • No corpo de um all, a função geo.intersects deve ser negada. Por outro lado, no corpo de um any, a função geo.intersects não deve ser negada.
  • No corpo de um any, as expressões geoespaciais podem ser combinadas usando or. No corpo de um all, essas expressões podem ser combinadas usando and.

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 ou ge podem ser combinadas com and / 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 usando or. 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 ou ge podem ser combinadas com and / 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 usando and. 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:

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

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:

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

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.

Próximas etapas