Funções geoespaciais OData no Azure AI Search – geo.distance
e geo.intersects
O Azure AI Search dá suporte a consultas geoespaciais em Expressões de filtro OData por meio das funções geo.distance
e geo.intersects
. A função geo.distance
retorna a distância em quilômetros entre dois pontos, um deles sendo um campo ou variável de intervalo e o outro uma constante passada como parte do filtro. A função geo.intersects
retorna true
se um determinado ponto está dentro de um polígono determinado, em que o ponto é um campo ou variável de intervalo e o polígono é especificado como uma constante passada como parte do filtro.
A função geo.distance
também pode ser usada no parâmetro $OrderBy para classificar os resultados da pesquisa por distância de um determinado ponto. A sintaxe para geo.distance
em $orderby é a mesma que em $filter. Ao usar geo.distance
em $orderby, o campo ao qual a operação se aplica deve ser do tipo Edm.GeographyPoint
e também deve ser classificável.
Observação
Ao usar geo.distance
no parâmetro $OrderBy, o campo que você passa para a função deve conter apenas um único ponto geográfico. Em outras palavras, ele deve ser do tipo Edm.GeographyPoint
e não Collection(Edm.GeographyPoint)
. Não é possível classificar em campos de coleção no Azure AI Search.
Sintaxe
O EBNF a seguir (Formulário Backus-Naur estendido) define a gramática das funções geo.distance
e geo.intersects
, bem como os valores geoespaciais nos quais operam:
geo_distance_call ::=
'geo.distance(' variable ',' geo_point ')'
| 'geo.distance(' geo_point ',' variable ')'
geo_point ::= "geography'POINT(" lon_lat ")'"
lon_lat ::= float_literal ' ' float_literal
geo_intersects_call ::=
'geo.intersects(' variable ',' geo_polygon ')'
/* You need at least four points to form a polygon, where the first and
last points are the same. */
geo_polygon ::=
"geography'POLYGON((" lon_lat ',' lon_lat ',' lon_lat ',' lon_lat_list "))'"
lon_lat_list ::= lon_lat(',' lon_lat)*
Um diagrama de sintaxe interativa também está disponível:
Observação
Confira Referência de sintaxe de expressão OData para Azure AI Search para ver a EBNF completa.
geo.distance
A função geo.distance
usa dois parâmetros do tipo Edm.GeographyPoint
e retorna um valor Edm.Double
que é a distância entre eles em quilômetros. Isso difere de outros serviços compatíveis com as operações geoespaciais do OData, que normalmente retornam as distâncias em metros.
Um dos parâmetros para geo.distance
deve ser uma constante de ponto de geografia e o outro deve ser um caminho de campo (ou uma variável de intervalo no caso de uma iteração de filtro sobre um campo de tipo Collection(Edm.GeographyPoint)
). A ordem desses parâmetros não importa.
A constante de ponto de geografia é do formulário geography'POINT(<longitude> <latitude>)'
, em que a longitude e a latitude são constantes numéricas.
Observação
Ao usar geo.distance
em um filtro, você deve comparar a distância retornada pela função com uma constante usando lt
, le
, gt
ou ge
. Os operadores eq
e ne
não são compatíveis ao comparar as distâncias. Por exemplo, este é um uso correto de geo.distance
: $filter=geo.distance(location, geography'POINT(-122.131577 47.678581)') le 5
.
geo.intersects
A função geo.intersects
usa uma variável do tipo Edm.GeographyPoint
e uma constante Edm.GeographyPolygon
e retorna um Edm.Boolean
-- true
se o ponto estiver dentro dos limites do polígono, caso contrário, false
.
O polígono é uma superfície bidimensional armazenada como uma sequência de pontos que definem um anel delimitador (veja o exemplo a seguir) (veja os exemplos abaixo). O polígono precisa estar fechado, o que significa que os conjuntos de primeiro e último pontos devem ser os mesmos. Os pontos em um polígono devem estar no sentido anti-horário.
Consultas geoespaciais e polígonos abrangendo o meridiano 180º
Para muitas bibliotecas de consulta geoespaciais, a formulação de uma consulta que inclua o meridiano 180º (próximo à hora do meridiano) está fora dos limites ou requer uma solução alternativa, como dividir o polígono em dois, um em cada lado do meridiano.
No Azure AI Search, as consultas geoespaciais que incluem longitude de 180 graus funcionam conforme o esperado se a forma de consulta for retangular e suas coordenadas se alinham a um layout de grade na longitude e na latitude (por exemplo, geo.intersects(location, geography'POLYGON((179 65, 179 66, -179 66, -179 65, 179 65))'
). Caso contrário, para formas não retangulares ou desalinhadas, considere a abordagem de polígono dividido.
Funções espaciais geográficas e null
Como todos os outros campos que não são de coleção no Azure AI Search, os campos do tipo Edm.GeographyPoint
podem conter valores de null
. Quando o Azure AI Search avalia geo.intersects
para um campo que é null
, o resultado sempre será false
. O comportamento de geo.distance
nesse caso depende do contexto:
- Nos filtros,
geo.distance
de um camponull
resulta emnull
. Isso significa que o documento não corresponderá, poisnull
comparado a qualquer valor não nulo é avaliado comofalse
. - Ao classificar os resultados usando $OrderBy,
geo.distance
de um camponull
resulta na distância máxima possível. Os documentos com tal campo classificarão menos do que todos os outros quando a direção de classificaçãoasc
for usada (o padrão) e mais alta do que todas as outras quando a direção fordesc
.
Exemplos
Exemplos de filtro
Localizar todos os hotéis em um raio de 10 km de determinado ponto de referência (em que o local é um campo do tipo Edm.GeographyPoint
):
geo.distance(location, geography'POINT(-122.131577 47.678581)') le 10
Localizar todos os hotéis dentro de determinado visor descrito como um polígono (em que o local é um campo do tipo Edm.GeographyPoint
). Observe que o polígono está fechado (o primeiro e o último pontos devem ser o mesmo) e os pontos devem estar listados no sentido anti-horário.
geo.intersects(location, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))')
Exemplos de Order-by
Organizar hotéis em ordem decrescente por rating
e, em seguida, em ordem crescente por distância das coordenadas fornecidas:
rating desc,geo.distance(location, geography'POINT(-122.131577 47.678581)') asc
Organizar em ordem decrescente por search.score
e por rating
e, em seguida, em ordem crescente por distância das coordenadas fornecidas, de modo que entre dois hotéis com classificações idênticas, o mais próximo seja listado primeiro:
search.score() desc,rating desc,geo.distance(location, geography'POINT(-122.131577 47.678581)') asc