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:

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, gteller 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 nullblir resultatet alltid false. Beteendet geo.distance för i det här fallet beror på kontexten:

  • I filter geo.distance resulterar ett null fält i null. Det innebär att dokumentet inte matchar eftersom null jämfört med ett värde som inte är null utvärderas till false.
  • Vid sortering av resultat med hjälp av $orderby geo.distanceresulterar ett null fält i det maximala möjliga avståndet. Dokument med ett sådant fält sorteras lägre än alla andra när sorteringsriktningen asc används (standardvärdet) och högre än alla andra när riktningen är desc.

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

Nästa steg