Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
GÄLLER FÖR: NoSQL
Med geospatiala data i Azure Cosmos DB for NoSQL kan du lagra platsinformation och utföra vanliga frågor, inklusive men inte begränsat till:
- Söka efter om en plats finns inom ett definierat område
- Mäta avståndet mellan två platser
- Avgöra om en sökväg korsar en plats eller ett område
Den här guiden går igenom processen med att skapa geospatiala data, indexera data och sedan köra frågor mot data i en container.
Förutsättningar
- Ett befintligt Azure Cosmos DB för NoSQL-konto.
- Om du inte har en Azure-prenumeration kan du prova Azure Cosmos DB utan kostnad för NoSQL.
- Om du har en befintlig Azure-prenumeration skapar du ett nytt Azure Cosmos DB för NoSQL-konto.
- Senaste versionen av .NET.
- Senaste versionen av Azure CLI.
- Om du använder en lokal installation loggar du in på Azure CLI med hjälp
az loginav kommandot .
- Om du använder en lokal installation loggar du in på Azure CLI med hjälp
Skapa en container och en indexeringsprincip
Alla containrar innehåller en standardindexeringsprincip som ska indexera geospatiala data. Skapa en anpassad indexeringsprincip genom att skapa ett konto och ange en JSON-fil med principens konfiguration. I det här avsnittet används ett anpassat rumsligt index för en nyligen skapad container.
Öppna en terminal.
Skapa en gränssnittsvariabel för namnet på ditt Azure Cosmos DB för NoSQL-konto och resursgrupp.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"Skapa en ny databas med namnet
cosmicworksmed .az cosmosdb sql database createaz cosmosdb sql database create \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks" \ --throughput 400Skapa en ny JSON-fil med namnet index-policy.json och lägg till följande JSON-objekt i filen.
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ], "spatialIndexes": [ { "path": "/location/*", "types": [ "Point", "Polygon" ] } ] }Använd
az cosmosdb sql container createför att skapa en ny container med namnetlocationsmed en partitionsnyckelsökväg/regionför .az cosmosdb sql container create \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --database-name "cosmicworks" \ --name "locations" \ --partition-key-path "/category" \ --idx @index-policy.jsonHämta slutligen kontoslutpunkten för ditt konto med hjälp av
az cosmosdb showoch en JMESPath-fråga.az cosmosdb show \ --resource-group "<resource-group-name>" \ --name "<nosql-account-name>" \ --query "documentEndpoint"Registrera kontoslutpunkten som du behöver i nästa avsnitt.
Skapa .NET SDK-konsolprogram
.NET SDK för Azure Cosmos DB for NoSQL tillhandahåller klasser för vanliga GeoJSON-objekt. Använd denna SDK för att effektivisera processen med att lägga till geografiska objekt i containern.
Öppna en terminal i en tom katalog.
Skapa ett nytt .NET-program med hjälp
dotnet newav kommandot med konsolmallen.dotnet new consoleMicrosoft.Azure.CosmosImportera NuGet-paketet med kommandotdotnet add package.dotnet add package Microsoft.Azure.Cosmos --version 3.*Varning
Entity Framework lagrar för närvarande inte rumsliga data i Azure Cosmos DB för NoSQL. Använd en av Azure Cosmos DB for NoSQL SDK:erna för starkt skrivet GeoJSON-stöd.
Importera NuGet-paketet
Azure.Identity.dotnet add package Azure.Identity --version 1.*Skapa projektet med
dotnet buildkommandot .dotnet buildÖppna valfri integrerad utvecklarmiljö (IDE) i samma katalog som ditt .NET-konsolprogram.
Öppna den nyligen skapade Program.cs-filen och ta bort eventuell befintlig kod. Lägg till med hjälp av direktiv för
Microsoft.Azure.Cosmosnamnrymderna ,Microsoft.Azure.Cosmos.LinqochMicrosoft.Azure.Cosmos.Spatial.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;Lägg till ett annat användningsdirektiv för
Azure.Identitynamnområdet.using Azure.Identity;Skapa en ny variabel med namnet
credentialav typenDefaultAzureCredential.DefaultAzureCredential credential = new();Skapa en strängvariabel med namnet
endpointmed azure Cosmos DB för NoSQL-kontoslutpunkten.string endpoint = "<nosql-account-endpoint>";Skapa en ny instans av
CosmosClient-klassen, och skicka inconnectionStringsom parameter, och omslut instansen i en using-instruktion.using CosmosClient client = new (connectionString);Hämta en referens till den tidigare skapade container (
cosmicworks/locations) i Azure Cosmos DB för NoSQL-kontot med hjälp avCosmosClient.GetDatabaseoch sedanDatabase.GetContainer. Lagra resultatet i en variabel med namnetcontainer.var container = client.GetDatabase("cosmicworks").GetContainer("locations");Spara Program.cs-filen.
Lägga till geospatiala data
.NET SDK innehåller flera typer i Microsoft.Azure.Cosmos.Spatial namnområdet för att representera vanliga GeoJSON-objekt. Dessa typer effektiviserar processen med att lägga till ny platsinformation till objekt i en container.
Skapa en ny fil med namnet Office.cs. I filen lägger du till ett användningsdirektiv i
Microsoft.Azure.Cosmos.Spatialoch skapar sedan enOfficeposttyp med följande egenskaper:Typ Beskrivning Standardvärde id stringUnik identifierare Namn stringNamnet på kontoret Plats PointGeografisk punkt för GeoJSON kategori stringPartitionsnyckelvärde business-officeusing Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );Kommentar
Den här posten innehåller en
Pointegenskap som representerar en specifik position i GeoJSON. Mer information finns i GeoJSON Point.Skapa en annan ny fil med namnet Region.cs. Lägg till en annan posttyp med namnet
Regionmed följande egenskaper:Typ Beskrivning Standardvärde id stringUnik identifierare Namn stringNamnet på kontoret Plats PolygonGeoJSON-geografisk form kategori stringPartitionsnyckelvärde business-regionusing Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );Kommentar
Den här posten innehåller en
Polygonegenskap som representerar en form som består av linjer som ritats mellan flera platser i GeoJSON. Mer information finns i GeoJSON Polygon.Skapa en annan ny fil med namnet Result.cs. Lägg till en posttyp med namnet
Resultmed följande två egenskaper:Typ Beskrivning Namn stringNamnet på det matchade resultatet distanceKilometers decimalAvstånd i kilometer public record Result( string name, decimal distanceKilometers );Spara filerna Office.cs, Region.cs och Result.cs.
Öppna filen Program.cs igen.
Skapa en ny
Polygoni en variabel med namnetmainCampusPolygon.Polygon mainCampusPolygon = new ( new [] { new LinearRing(new [] { new Position(-122.13237, 47.64606), new Position(-122.13222, 47.63376), new Position(-122.11841, 47.64175), new Position(-122.12061, 47.64589), new Position(-122.13237, 47.64606), }) } );Skapa en ny
Regionvariabel med namnetmainCampusRegionmed hjälp av polygonen, den unika identifieraren1000och namnetMain Campus.Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);Använd
Container.UpsertItemAsyncför att lägga till regionen i containern. Skriv regionens information till konsolen.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");Tips
Den här guiden använder upsert i stället för infoga så att du kan köra skriptet flera gånger utan att orsaka en konflikt mellan unika identifierare. Mer information om upsert-åtgärder finns i skapa objekt.
Skapa en ny
Pointvariabel med namnetheadquartersPoint. Använd variabeln för att skapa en nyOfficevariabel med namnetheadquartersOfficemed hjälp av punkten, den unika identifieraren0001och namnetHeadquarters.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);Skapa en annan
Pointvariabel med namnetresearchPoint. Använd variabeln för att skapa en annanOfficevariabel med namnetresearchOfficemed hjälp av motsvarande punkt, den unika identifieraren0002och namnetResearch and Development.Point researchPoint = new (-96.84369, 46.81298); Office researchOffice = new ("0002", "Research and Development", researchPoint);Skapa en
TransactionalBatchför att uppdatera eller infoga bådaOfficevariablerna som en enda transaktion. Skriv sedan information om båda kontoren till konsolen.TransactionalBatch officeBatch = container.CreateTransactionalBatch(new PartitionKey("business-office")); officeBatch.UpsertItem<Office>(headquartersOffice); officeBatch.UpsertItem<Office>(researchOffice); await officeBatch.ExecuteAsync(); Console.WriteLine($"[UPSERT ITEM]\t{headquartersOffice}"); Console.WriteLine($"[UPSERT ITEM]\t{researchOffice}");Kommentar
Mer information om transaktioner finns i transaktionsbatchoperationer.
Spara Program.cs-filen.
Kör programmet i en terminal med .
dotnet runObservera att utdata från programkörningen innehåller information om de tre nyligen skapade objekten.dotnet run[UPSERT ITEM] Region { id = 1000, name = Main Campus, location = Microsoft.Azure.Cosmos.Spatial.Polygon, category = business-region } [UPSERT ITEM] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office } [UPSERT ITEM] Office { id = 0002, name = Research and Development, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Fråga geospatiala data med hjälp av NoSQL-fråga
Typerna Microsoft.Azure.Cosmos.Spatial i namnområdet kan användas som indata till en NoSQL-parameteriserad fråga för att använda inbyggda funktioner som ST_DISTANCE.
Öppna filen Program.cs .
Skapa en ny
stringvariabel med namnetnosqlmed frågan som används i det här avsnittet för att mäta avståndet mellan punkter.string nosqlString = @" SELECT o.name, NumberBin(distanceMeters / 1000, 0.01) AS distanceKilometers FROM offices o JOIN (SELECT VALUE ROUND(ST_DISTANCE(o.location, @compareLocation))) AS distanceMeters WHERE o.category = @partitionKey AND distanceMeters > @maxDistance ";Tips
Den här frågan placerar den geospatiala funktionen i en underfråga för att förenkla processen att återanvända det redan beräknade värdet flera gånger i
SELECT- ochWHERE-satserna.Skapa en ny
QueryDefinitionvariabel med namnetquerymed variabelnnosqlStringsom parameter. AnvändQueryDefinition.WithParametersedan fluent-metoden flera gånger för att lägga till dessa parametrar i frågan:Värde @maxDistance 2000@partitionKey "business-office"@compareLocation new Point(-122.11758, 47.66901)var query = new QueryDefinition(nosqlString) .WithParameter("@maxDistance", 2000) .WithParameter("@partitionKey", "business-office") .WithParameter("@compareLocation", new Point(-122.11758, 47.66901));Skapa en ny iterator med hjälp av
Container.GetItemQueryIterator<>, denResultgeneriska typen och variabelnquery. Använd sedan en kombination av en while - och foreach-loop för att iterera över alla resultat på varje sida med resultat. Mata ut varje resultat till konsolen.var distanceIterator = container.GetItemQueryIterator<Result>(query); while (distanceIterator.HasMoreResults) { var response = await distanceIterator.ReadNextAsync(); foreach (var result in response) { Console.WriteLine($"[DISTANCE KM]\t{result}"); } }Kommentar
Mer information om hur du räknar upp frågeresultat finns i frågeobjekt.
Spara Program.cs-filen.
Kör programmet igen i en terminal med hjälp av
dotnet run. Observera att utdata nu innehåller resultatet av frågan.dotnet run[DISTANCE KM] Result { name = Headquarters, distanceKilometers = 3.34 } [DISTANCE KM] Result { name = Research and Development, distanceKilometers = 1907.43 }
Fråga geospatiala data med LINQ
Funktionen LINQ till NoSQL i .NET SDK stödjer inbegripandet av geospatiala typer i frågeuttrycken. SDK innehåller även tilläggsmetoder som mappar till motsvarande inbyggda funktioner:
| Tilläggsmetod | Inbyggd funktion |
|---|---|
Distance() |
ST_DISTANCE |
Intersects() |
ST_INTERSECTS |
IsValid() |
ST_ISVALID |
IsValidDetailed() |
ST_ISVALIDDETAILED |
Within() |
ST_WITHIN |
Öppna filen Program.cs .
RegionHämta objektet från containern med en unik identifierare för1000och lagra det i en variabel med namnetregion.Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));Använd
Container.GetItemLinqQueryable<>metoden för att få en LINQ-frågebar och skapa LINQ-frågan smidigt genom att utföra följande tre åtgärder:Använd
Queryable.Where<>-tilläggsmetoden för att filtrera så att endast objekt med encategorysom är likvärdig med"business-office"ingår.Använd
Queryable.Where<>igen om du bara vill filtrera till platser iregionvariabelnslocationegenskap med hjälp avGeometry.Within().Översätt LINQ-uttrycket till en feed-iterator med hjälp av
CosmosLinqExtensions.ToFeedIterator<>.
var regionIterator = container.GetItemLinqQueryable<Office>() .Where(o => o.category == "business-office") .Where(o => o.location.Within(region.location)) .ToFeedIterator<Office>();Viktigt!
I det här exemplet har kontorets platsegenskap en punkt och regionens platsegenskap har en polygon.
ST_WITHINavgör om platsen på kontoret ligger inom regionens polygon.Använd en kombination av en while-loop och foreach-loop för att iterera över alla resultat på varje resulterande sida. Mata ut varje resultat till konsolen.
while (regionIterator.HasMoreResults) { var response = await regionIterator.ReadNextAsync(); foreach (var office in response) { Console.WriteLine($"[IN REGION]\t{office}"); } }Spara Program.cs-filen.
Kör programmet en sista gång i en terminal med .
dotnet runObservera att utdata nu innehåller resultatet av den andra LINQ-baserade frågan.dotnet run[IN REGION] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Rensa resurser
Ta bort databasen när du har slutfört den här guiden.
Öppna en terminal och skapa en gränssnittsvariabel för namnet på ditt konto och din resursgrupp.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"Använd
az cosmosdb sql database deleteför att ta bort databasen.az cosmosdb sql database delete \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks"