GeoJSON-locatiegegevens indexeren en opvragen in Azure Cosmos DB for NoSQL
VAN TOEPASSING OP: NoSQL
Met georuimtelijke gegevens in Azure Cosmos DB for NoSQL kunt u locatiegegevens opslaan en algemene query's uitvoeren, waaronder, maar niet beperkt tot:
- Zoeken of een locatie zich binnen een gedefinieerd gebied bevindt
- De afstand tussen twee locaties meten
- Bepalen of een pad doorkruist met een locatie of gebied
In deze handleiding wordt het proces voor het maken van georuimtelijke gegevens beschreven, het indexeren van de gegevens en het uitvoeren van query's op de gegevens in een container.
Vereisten
- Een bestaand Azure Cosmos DB for NoSQL-account.
- Als u geen Azure-abonnement hebt, kunt u Gratis Azure Cosmos DB voor NoSQL proberen.
- Als u een bestaand Azure-abonnement hebt, maakt u een nieuw Azure Cosmos DB for NoSQL-account.
- Nieuwste versie van .NET.
- Nieuwste versie van Azure CLI.
- Als u een lokale installatie gebruikt, meldt u zich aan bij de Azure CLI met behulp van de
az login
opdracht.
- Als u een lokale installatie gebruikt, meldt u zich aan bij de Azure CLI met behulp van de
Container- en indexeringsbeleid maken
Alle containers bevatten een standaardindexeringsbeleid dat georuimtelijke gegevens kan indexeren. Als u een aangepast indexeringsbeleid wilt maken, maakt u een account en geeft u een JSON-bestand op met de configuratie van het beleid. In deze sectie wordt een aangepaste ruimtelijke index gebruikt voor een zojuist gemaakte container.
Open een terminal.
Maak een shellvariabele voor de naam van uw Azure Cosmos DB for NoSQL-account en resourcegroep.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"
Maak een nieuwe database met de naam
cosmicworks
.az cosmosdb sql database create
az cosmosdb sql database create \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks" \ --throughput 400
Maak een nieuw JSON-bestand met de naam index-policy.json en voeg het volgende JSON-object toe aan het bestand.
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ], "spatialIndexes": [ { "path": "/location/*", "types": [ "Point", "Polygon" ] } ] }
Hiermee
az cosmosdb sql container create
maakt u een nieuwe container met de naamlocations
met een partitiesleutelpad van/region
.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.json
Haal ten slotte het accounteindpunt voor uw account op met behulp van
az cosmosdb show
een JMESPath-query.az cosmosdb show \ --resource-group "<resource-group-name>" \ --name "<nosql-account-name>" \ --query "documentEndpoint"
Noteer het accounteindpunt zoals u dit nodig hebt in de volgende sectie.
.NET SDK-consoletoepassing maken
De .NET SDK voor Azure Cosmos DB for NoSQL biedt klassen voor algemene GeoJSON-objecten. Gebruik deze SDK om het proces van het toevoegen van geografische objecten aan uw container te stroomlijnen.
Open een terminal in een lege map.
Maak een nieuwe .NET-toepassing met behulp van de
dotnet new
opdracht met de consolesjabloon .dotnet new console
Importeer het
Microsoft.Azure.Cosmos
NuGet-pakket met behulp van dedotnet add package
opdracht.dotnet add package Microsoft.Azure.Cosmos --version 3.*
Waarschuwing
Entity Framework bevat momenteel geen ruimtelijke gegevens in Azure Cosmos DB voor NoSQL. Gebruik een van de Azure Cosmos DB for NoSQL SDK's voor sterk getypeerde GeoJSON-ondersteuning.
Importeer het
Azure.Identity
NuGet-pakket.dotnet add package Azure.Identity --version 1.*
Bouw het project met de
dotnet build
opdracht.dotnet build
Open de IDE (Integrated Developer Environment) van uw keuze in dezelfde map als uw .NET-consoletoepassing.
Open het zojuist gemaakte Program.cs-bestand en verwijder alle bestaande code. Voeg gebruiksrichtlijnen toe voor de
Microsoft.Azure.Cosmos
,Microsoft.Azure.Cosmos.Linq
enMicrosoft.Azure.Cosmos.Spatial
naamruimten.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;
Voeg nog een using-instructie toe voor de
Azure.Identity
naamruimte.using Azure.Identity;
Maak een nieuwe variabele met de naam
credential
van het typeDefaultAzureCredential
.DefaultAzureCredential credential = new();
Maak een tekenreeksvariabele met de naam
endpoint
van uw Azure Cosmos DB for NoSQL-accounteindpunt.string endpoint = "<nosql-account-endpoint>";
Maak een nieuw exemplaar van de
CosmosClient
klasse die wordtconnectionString
doorgegeven en verpakt deze in een using-instructie.using CosmosClient client = new (connectionString);
Haal een verwijzing op naar de eerder gemaakte container (
cosmicworks/locations
) in het Azure Cosmos DB for NoSQL-account met behulp vanCosmosClient.GetDatabase
en vervolgensDatabase.GetContainer
. Sla het resultaat op in een variabele met de naamcontainer
.var container = client.GetDatabase("cosmicworks").GetContainer("locations");
Sla bestand Program.cs op.
Georuimtelijke gegevens toevoegen
De .NET SDK bevat meerdere typen in de Microsoft.Azure.Cosmos.Spatial
naamruimte die algemene GeoJSON-objecten vertegenwoordigen. Met deze typen wordt het proces voor het toevoegen van nieuwe locatiegegevens aan items in een container gestroomlijnd.
Maak een nieuw bestand met de naam Office.cs. Voeg in het bestand een using-instructie toe aan
Microsoft.Azure.Cosmos.Spatial
en maak vervolgens eenOffice
recordtype met deze eigenschappen:Type Description Default value id string
Unieke id name string
Naam van het kantoor location Point
GeoJSON geografisch punt category string
Partitiesleutelwaarde business-office
using Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );
Notitie
Deze record bevat een
Point
eigenschap die een specifieke positie in GeoJSON vertegenwoordigt. Zie GeoJSON Point voor meer informatie.Maak nog een nieuw bestand met de naam Region.cs. Voeg nog een recordtype toe met de naam
Region
deze eigenschappen:Type Description Default value id string
Unieke id name string
Naam van het kantoor location Polygon
Geografische vorm van GeoJSON category string
Partitiesleutelwaarde business-region
using Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );
Notitie
Deze record bevat een
Polygon
eigenschap die een shape vertegenwoordigt die bestaat uit lijnen die zijn getekend tussen meerdere locaties in GeoJSON. Zie GeoJSON Polygon voor meer informatie.Maak nog een nieuw bestand met de naam Result.cs. Voeg een recordtype toe met de volgende
Result
twee eigenschappen:Type Description name string
Naam van het overeenkomende resultaat distanceKilometers decimal
Afstand in kilometers public record Result( string name, decimal distanceKilometers );
Sla de bestanden Office.cs, Region.cs en Result.cs op.
Open het bestand Program.cs opnieuw.
Maak een nieuwe
Polygon
in een variabele met de naammainCampusPolygon
.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), }) } );
Maak een nieuwe
Region
variabele met de naammainCampusRegion
met behulp van de veelhoek, de unieke id1000
en de naamMain Campus
.Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
Gebruik
Container.UpsertItemAsync
dit om de regio toe te voegen aan de container. Schrijf de gegevens van de regio naar de console.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");
Tip
In deze handleiding wordt upsert gebruikt in plaats van in te voegen , zodat u het script meerdere keren kunt uitvoeren zonder dat er een conflict tussen unieke id's ontstaat. Zie items maken voor meer informatie over upsert-bewerkingen.
Maak een nieuwe
Point
variabele met de naamheadquartersPoint
. Gebruik deze variabele om een nieuweOffice
variabele te maken metheadquartersOffice
behulp van het punt, de unieke id0001
en de naamHeadquarters
.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
Maak een andere
Point
variabele met de naamresearchPoint
. Gebruik deze variabele om een andereOffice
variabele te maken metresearchOffice
behulp van het bijbehorende punt, de unieke id0002
en de naamResearch and Development
.Point researchPoint = new (-96.84369, 46.81298); Office researchOffice = new ("0002", "Research and Development", researchPoint);
Maak een
TransactionalBatch
om beideOffice
variabelen als één transactie te upsert. Schrijf vervolgens de gegevens van beide kantoren naar de console.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}");
Notitie
Zie transactionele batchbewerkingen voor meer informatie over transacties.
Sla bestand Program.cs op.
Voer de toepassing uit in een terminal met behulp van
dotnet run
. U ziet dat de uitvoer van de toepassingsuitvoering informatie bevat over de drie nieuw gemaakte items.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 }
Georuimtelijke gegevens opvragen met noSQL-query
De typen in de Microsoft.Azure.Cosmos.Spatial
naamruimte kunnen worden gebruikt als invoer voor een NoSQL-geparameteriseerde query om ingebouwde functies zoals ST_DISTANCE
.
Open het Program.cs-bestand .
Maak een nieuwe
string
variabele met de naamnosql
met de query in deze sectie om de afstand tussen punten te meten.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 ";
Tip
Met deze query wordt de georuimtelijke functie binnen een subquery opgeslagen om het proces van het hergebruik van de reeds berekende waarde meerdere keren in de
SELECT
enWHERE
componenten te vereenvoudigen.Maak een nieuwe
QueryDefinition
variabele met de naamquery
met behulp van denosqlString
variabele als parameter. Gebruik vervolgens deQueryDefinition.WithParameter
fluent-methode meerdere keren om deze parameters toe te voegen aan de query:Weergegeven als @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));
Maak een nieuwe iterator met behulp van
Container.GetItemQueryIterator<>
hetResult
algemene type en dequery
variabele. Gebruik vervolgens een combinatie van een tijdje en foreach-lus om alle resultaten op elke pagina met resultaten te herhalen. Voer elk resultaat uit naar de console.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}"); } }
Notitie
Zie query-items voor meer informatie over het inventariseren van queryresultaten.
Sla bestand Program.cs op.
Voer de toepassing opnieuw uit in een terminal met behulp van
dotnet run
. U ziet dat de uitvoer nu de resultaten van de query bevat.dotnet run
[DISTANCE KM] Result { name = Headquarters, distanceKilometers = 3.34 } [DISTANCE KM] Result { name = Research and Development, distanceKilometers = 1907.43 }
Georuimtelijke gegevens opvragen met LINQ
De LINQ-naar-NoSQL-functionaliteit in de .NET SDK biedt ondersteuning voor het opnemen van georuimtelijke typen in de queryexpressies. Verder bevat de SDK uitbreidingsmethoden die zijn toegewezen aan equivalente ingebouwde functies:
Extensiemethode | Ingebouwde functie |
---|---|
Distance() |
ST_DISTANCE |
Intersects() |
ST_INTERSECTS |
IsValid() |
ST_ISVALID |
IsValidDetailed() |
ST_ISVALIDDETAILED |
Within() |
ST_WITHIN |
Open het Program.cs-bestand .
Haal het
Region
item op uit de container met een unieke id en1000
sla het op in een variabele met de naamregion
.Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
Gebruik de
Container.GetItemLinqQueryable<>
methode om een LINQ-query mogelijk te maken en de LINQ-query vloeiend te bouwen door deze drie acties uit te voeren:Gebruik de
Queryable.Where<>
extensiemethode om te filteren op alleen items met eencategory
equivalent van"business-office"
.Gebruik
Queryable.Where<>
opnieuw om te filteren op alleen locaties binnen de eigenschap vanlocation
deregion
variabele met behulp vanGeometry.Within()
.Vertaal de LINQ-expressie naar een feed-iterator met behulp van
CosmosLinqExtensions.ToFeedIterator<>
.
var regionIterator = container.GetItemLinqQueryable<Office>() .Where(o => o.category == "business-office") .Where(o => o.location.Within(region.location)) .ToFeedIterator<Office>();
Belangrijk
In dit voorbeeld heeft de locatie-eigenschap van het kantoor een punt en heeft de locatie-eigenschap van de regio een veelhoek.
ST_WITHIN
bepaalt of het punt van het kantoor binnen de veelhoek van de regio valt.Gebruik een combinatie van een tijdje en foreach-lus om alle resultaten op elke pagina met resultaten te herhalen. Voer elk resultaat uit naar de console.
while (regionIterator.HasMoreResults) { var response = await regionIterator.ReadNextAsync(); foreach (var office in response) { Console.WriteLine($"[IN REGION]\t{office}"); } }
Sla bestand Program.cs op.
Voer de toepassing een laatste keer uit in een terminal met behulp van
dotnet run
. U ziet dat de uitvoer nu de resultaten van de tweede LINQ-query bevat.dotnet run
[IN REGION] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Resources opschonen
Verwijder de database nadat u deze handleiding hebt voltooid.
Open een terminal en maak een shellvariabele voor de naam van uw account en resourcegroep.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"
Gebruik
az cosmosdb sql database delete
deze optie om de database te verwijderen.az cosmosdb sql database delete \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks"