Geo-spatiala OData-funktioner i Azure AI Search – geo.distance
och geo.intersects
Azure AI Search stöder geo-spatiala frågor i OData-filteruttryck via geo.distance
funktionerna och geo.intersects
. Funktionen geo.distance
returnerar avståndet i kilometer mellan två punkter, en är en fält- eller intervallvariabel och en som är en konstant som skickas som en del av filtret. Funktionen geo.intersects
returnerar true
om en angiven punkt finns inom en viss polygon, där punkten är ett fält eller en intervallvariabel och polygonen anges som en konstant som skickas som en del av filtret.
Funktionen geo.distance
kan också användas i parametern $orderby för att sortera sökresultat efter avstånd från en viss punkt. Syntaxen för geo.distance
i $orderby är densamma som i $filter. När du använder geo.distance
i $orderby måste fältet som det gäller vara av typen Edm.GeographyPoint
och det måste också vara sorterbart.
Kommentar
När du använder geo.distance
i parametern $orderby får det fält som du skickar till funktionen endast innehålla en enda geo-punkt. Med andra ord måste den vara av typen Edm.GeographyPoint
och inte Collection(Edm.GeographyPoint)
. Det går inte att sortera efter samlingsfält i Azure AI Search.
Syntax
Följande EBNF (Extended Backus-Naur Form) definierar grammatiken geo.distance
för funktionerna och geo.intersects
samt de geo-spatiala värden som de fungerar på:
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)*
Ett interaktivt syntaxdiagram är också tillgängligt:
Kommentar
Se syntaxreferens för OData-uttryck för Azure AI Search för hela EBNF.
geo.distance
Funktionen geo.distance
tar två parametrar av typen Edm.GeographyPoint
och returnerar ett Edm.Double
värde som är avståndet mellan dem i kilometer. Detta skiljer sig från andra tjänster som stöder geo-spatiala OData-åtgärder, som vanligtvis returnerar avstånd i mätare.
En av parametrarna som geo.distance
måste vara en geografipunktskonstant och den andra måste vara en fältsökväg (eller en intervallvariabel om ett filter itererar över ett fält av typen Collection(Edm.GeographyPoint)
). Ordningen på dessa parametrar spelar ingen roll.
Geografipunktskonstanten är av formatet geography'POINT(<longitude> <latitude>)'
, där longitud och latitud är numeriska konstanter.
Kommentar
När du använder geo.distance
i ett filter måste du jämföra avståndet som returneras av funktionen med en konstant med hjälp av lt
, le
, gt
eller ge
. Operatorerna eq
och ne
stöds inte vid jämförelse av avstånd. Detta är till exempel en korrekt användning av geo.distance
: $filter=geo.distance(location, geography'POINT(-122.131577 47.678581)') le 5
.
geo.intersects
Funktionen geo.intersects
tar en variabel av typen Edm.GeographyPoint
och en konstant Edm.GeographyPolygon
och returnerar en Edm.Boolean
-- true
om punkten ligger inom polygonens gränser, false
annars.
Polygonen är en tvådimensionell yta som lagras som en sekvens med punkter som definierar en avgränsningsring (se exemplen nedan). Polygonen måste stängas, vilket innebär att de första och sista punktuppsättningarna måste vara desamma. Punkter i en polygon måste vara i motsols ordning.
Geo-spatiala frågor och polygoner som sträcker sig över den 180:e meridianen
För många geo-spatiala frågebibliotek som formulerar en fråga som innehåller den 180:e meridianen (nära datumlinjen) är antingen förbjudet område eller kräver en lösning, till exempel att dela upp polygonen i två, en på vardera sidan av meridianen.
I Azure AI Search fungerar geo-spatiala frågor som innehåller 180-graders longitud som förväntat om frågeformen är rektangulär och koordinaterna justeras till en rutnätslayout längs longitud och latitud (till exempel geo.intersects(location, geography'POLYGON((179 65, 179 66, -179 66, -179 65, 179 65))'
). I annat fall bör du överväga den delade polygonmetoden för icke-rektangulära eller ojusterade former.
Geo-spatiala funktioner och null
Liksom alla andra fält som inte är samlingsfält i Azure AI Search kan fält av typen Edm.GeographyPoint
innehålla null
värden. När Azure AI Search utvärderas geo.intersects
för ett fält som är null
blir resultatet alltid false
. Beteendet geo.distance
för i det här fallet beror på kontexten:
- I filter
geo.distance
resulterar ettnull
fält inull
. Det innebär att dokumentet inte matchar eftersomnull
jämfört med ett värde som inte är null utvärderas tillfalse
. - Vid sortering av resultat med hjälp av $orderby
geo.distance
resulterar ettnull
fält i det maximala möjliga avståndet. Dokument med ett sådant fält sorteras lägre än alla andra när sorteringsriktningenasc
används (standardvärdet) och högre än alla andra när riktningen ärdesc
.
Exempel
Filtrera exempel
Hitta alla hotell inom 10 kilometer från en viss referenspunkt (där platsen är ett fält av typen Edm.GeographyPoint
):
geo.distance(location, geography'POINT(-122.131577 47.678581)') le 10
Hitta alla hotell i en viss vyport som beskrivs som en polygon (där platsen är ett fält av typen Edm.GeographyPoint
). Observera att polygonen är stängd (den första och sista punkten måste vara densamma) och att punkterna måste anges i motsols ordning.
geo.intersects(location, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))')
Order-by-exempel
Sortera hotell som fallande efter rating
och sedan stigande efter avstånd från de angivna koordinaterna:
rating desc,geo.distance(location, geography'POINT(-122.131577 47.678581)') asc
Sortera hotell i fallande ordning search.score
efter och rating
, och sedan i stigande ordning efter avstånd från de angivna koordinaterna så att mellan två hotell med identiska betyg visas den närmaste först:
search.score() desc,rating desc,geo.distance(location, geography'POINT(-122.131577 47.678581)') asc