Indexování a dotazování dat o poloze GeoJSON ve službě Azure Cosmos DB for NoSQL
PLATÍ PRO: NoSQL
Geoprostorová data ve službě Azure Cosmos DB for NoSQL umožňují ukládat informace o poloze a provádět běžné dotazy, včetně mimo jiné:
- Zjištění, jestli je umístění v definované oblasti
- Měření vzdálenosti mezi dvěma umístěními
- Určení, jestli se cesta protíná s umístěním nebo oblastí
Tato příručka vás provede procesem vytváření geoprostorových dat, indexování dat a následného dotazování dat v kontejneru.
Požadavky
- Existující účet Azure Cosmos DB for NoSQL.
- Pokud nemáte předplatné Azure, vyzkoušejte službu Azure Cosmos DB pro NoSQL zdarma.
- Pokud máte existující předplatné Azure, vytvořte nový účet Azure Cosmos DB for NoSQL.
- Nejnovější verze .NET
- Nejnovější verze Azure CLI
- Pokud používáte místní instalaci, přihlaste se k Azure CLI pomocí
az login
příkazu.
- Pokud používáte místní instalaci, přihlaste se k Azure CLI pomocí
Vytvoření zásad kontejneru a indexování
Všechny kontejnery obsahují výchozí zásady indexování, které úspěšně indexují geoprostorová data. Pokud chcete vytvořit vlastní zásady indexování, vytvořte účet a zadejte soubor JSON s konfigurací zásad. V této části se pro nově vytvořený kontejner používá vlastní prostorový index.
Otevřete terminál.
Vytvořte proměnnou prostředí pro název účtu a skupiny prostředků Azure Cosmos DB for NoSQL.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"
Vytvořte novou databázi s názvem
cosmicworks
usingaz cosmosdb sql database create
.az cosmosdb sql database create \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks" \ --throughput 400
Vytvořte nový soubor JSON s názvem index-policy.json a do souboru přidejte následující objekt JSON.
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ], "spatialIndexes": [ { "path": "/location/*", "types": [ "Point", "Polygon" ] } ] }
Slouží
az cosmosdb sql container create
k vytvoření nového kontejneru s názvemlocations
cesta klíče oddílu ./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
Nakonec získejte koncový bod účtu pro váš účet pomocí
az cosmosdb show
dotazu JMESPath.az cosmosdb show \ --resource-group "<resource-group-name>" \ --name "<nosql-account-name>" \ --query "documentEndpoint"
Nahrajte koncový bod účtu, protože ho budete potřebovat v další části.
Vytvoření konzolové aplikace .NET SDK
Sada .NET SDK pro Azure Cosmos DB for NoSQL poskytuje třídy pro běžné objekty GeoJSON. Pomocí této sady SDK můžete zjednodušit proces přidávání geografických objektů do kontejneru.
Otevřete terminál v prázdném adresáři.
Pomocí příkazu se šablonou konzoly vytvořte novou aplikaci
dotnet new
.NET.dotnet new console
Importujte
Microsoft.Azure.Cosmos
balíček NuGet pomocídotnet add package
příkazu.dotnet add package Microsoft.Azure.Cosmos --version 3.*
Upozorňující
Entity Framework v současné době prostorová data ve službě Azure Cosmos DB for NoSQL neobsahuje. Pro podporu GeoJSON silného typu použijte jednu ze sad SDK služby Azure Cosmos DB for NoSQL.
Importujte
Azure.Identity
balíček NuGet.dotnet add package Azure.Identity --version 1.*
Sestavte projekt pomocí
dotnet build
příkazu.dotnet build
Otevřete integrované vývojové prostředí (IDE) podle vašeho výběru ve stejném adresáři jako konzolová aplikace .NET.
Otevřete nově vytvořený soubor Program.cs a odstraňte veškerý existující kód. Přidejte direktivy using pro
Microsoft.Azure.Cosmos
obory názvů ,Microsoft.Azure.Cosmos.Linq
aMicrosoft.Azure.Cosmos.Spatial
obory názvů.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;
Přidejte další direktivu
Azure.Identity
using pro obor názvů.using Azure.Identity;
Vytvořte novou proměnnou s názvem
credential
typuDefaultAzureCredential
.DefaultAzureCredential credential = new();
Vytvořte řetězcovou proměnnou s názvem
endpoint
s koncovým bodem účtu Azure Cosmos DB for NoSQL.string endpoint = "<nosql-account-endpoint>";
Vytvořte novou instanci
CosmosClient
třídy, kteráconnectionString
předá a zabalí ji do příkazu using.using CosmosClient client = new (connectionString);
Načtěte odkaz na dříve vytvořený kontejner (
cosmicworks/locations
) v účtu Azure Cosmos DB for NoSQL pomocíCosmosClient.GetDatabase
a pakDatabase.GetContainer
. Uložte výsledek do proměnné s názvemcontainer
.var container = client.GetDatabase("cosmicworks").GetContainer("locations");
Uložte soubor Program.cs.
Přidání geoprostorových dat
Sada .NET SDK obsahuje více typů v Microsoft.Azure.Cosmos.Spatial
oboru názvů, které představují běžné objekty GeoJSON. Tyto typy zjednodušují proces přidávání nových informací o umístění do položek v kontejneru.
Vytvořte nový soubor s názvem Office.cs. Do souboru přidejte direktivu
Microsoft.Azure.Cosmos.Spatial
using a pak vytvořte typ záznamuOffice
s těmito vlastnostmi:Typ Popis Default value id string
Jedinečný identifikátor Jméno string
Název kanceláře location Point
Geografický bod GeoJSON kategorie string
Hodnota klíče oddílu business-office
using Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );
Poznámka:
Tento záznam obsahuje
Point
vlastnost představující konkrétní pozici v GeoJSON. Další informace naleznete v tématu GeoJSON Point.Vytvořte další nový soubor s názvem Region.cs. Přidejte další typ záznamu s názvem
Region
s těmito vlastnostmi:Typ Popis Default value id string
Jedinečný identifikátor Jméno string
Název kanceláře location Polygon
Geografický tvar GeoJSON kategorie string
Hodnota klíče oddílu business-region
using Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );
Poznámka:
Tento záznam obsahuje
Polygon
vlastnost představující obrazec složený z čar nakreslených mezi několika umístěními v GeoJSON. Další informace naleznete v tématu GeoJSON Polygon.Vytvořte další nový soubor s názvem Result.cs. Přidejte typ záznamu s
Result
těmito dvěma vlastnostmi:Typ Popis Jméno string
Název odpovídajícího výsledku vzdálenostKilometry decimal
Vzdálenost v kilometrech public record Result( string name, decimal distanceKilometers );
Uložte soubory Office.cs, Region.cs a Result.cs.
Znovu otevřete soubor Program.cs.
Vytvořte novou
Polygon
proměnnou s názvemmainCampusPolygon
.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), }) } );
Vytvořte novou
Region
proměnnou s názvemmainCampusRegion
pomocí mnohoúhelníku, jedinečného identifikátoru1000
a názvuMain Campus
.Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
Slouží
Container.UpsertItemAsync
k přidání oblasti do kontejneru. Napište informace o oblasti do konzoly.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");
Tip
Tato příručka místo vložení používá upsert, takže skript můžete spustit vícekrát, aniž by došlo ke konfliktu mezi jedinečnými identifikátory. Další informace o operacích upsertu najdete v tématu vytváření položek.
Vytvořte novou
Point
proměnnou s názvemheadquartersPoint
. Pomocí této proměnné vytvořte novouOffice
proměnnou s názvemheadquartersOffice
pomocí bodu, jedinečného identifikátoru0001
a názvuHeadquarters
.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
Vytvořte další
Point
proměnnou s názvemresearchPoint
. Pomocí této proměnné vytvořte jinouOffice
proměnnou s názvemresearchOffice
pomocí odpovídajícího bodu, jedinečného identifikátoru0002
a názvuResearch and Development
.Point researchPoint = new (-96.84369, 46.81298); Office researchOffice = new ("0002", "Research and Development", researchPoint);
Vytvořte pro
TransactionalBatch
upsert obouOffice
proměnných jako jednu transakci. Pak na konzolu napište informace o obou kancelářích.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}");
Poznámka:
Další informace o transakcích naleznete v tématu transakční dávkové operace.
Uložte soubor Program.cs.
Spusťte aplikaci v terminálu pomocí
dotnet run
příkazu . Všimněte si, že výstup spuštění aplikace obsahuje informace o třech nově vytvořených položkách.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 }
Dotazování geoprostorových dat pomocí dotazu NoSQL
Typy v Microsoft.Azure.Cosmos.Spatial
oboru názvů lze použít jako vstupy do parametrizovaného dotazu NoSQL pro použití předdefinovaných funkcí, jako je ST_DISTANCE
.
Otevřete soubor Program.cs.
Vytvořte novou
string
proměnnou s názvemnosql
dotazu v této části k měření vzdálenosti mezi body.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 ";
Vytvořte novou
QueryDefinition
proměnnou s názvemquery
pomocínosqlString
proměnné jako parametru. Pak k přidání těchto parametrů do dotazu použijteQueryDefinition.WithParameter
vícekrát fluent metodu:Hodnota @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));
Vytvořte nový iterátor pomocí
Container.GetItemQueryIterator<>
Result
obecného typu aquery
proměnné. Potom použijte kombinaci smyčky while a foreach k iteraci všech výsledků na každé stránce výsledků. Vypíše každý výsledek do konzoly.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}"); } }
Poznámka:
Další informace o vytvoření výčtu výsledků dotazu najdete v tématu položky dotazu.
Uložte soubor Program.cs.
Spusťte aplikaci znovu v terminálu pomocí
dotnet run
příkazu . Všimněte si, že výstup teď obsahuje výsledky dotazu.dotnet run
[DISTANCE KM] Result { name = Headquarters, distanceKilometers = 3.34 } [DISTANCE KM] Result { name = Research and Development, distanceKilometers = 1907.43 }
Dotazování geoprostorových dat pomocí LINQ
Funkce LINQ to NoSQL v sadě .NET SDK podporuje zahrnutí geoprostorových typů do výrazů dotazu. Sada SDK navíc obsahuje rozšiřující metody, které se mapuje na ekvivalentní předdefinované funkce:
Metoda rozšíření | Integrovaná funkce |
---|---|
Distance() |
ST_DISTANCE |
Intersects() |
ST_INTERSECTS |
IsValid() |
ST_ISVALID |
IsValidDetailed() |
ST_ISVALIDDETAILED |
Within() |
ST_WITHIN |
Otevřete soubor Program.cs.
Region
Načtěte položku z kontejneru s jedinečným identifikátorem1000
a uložte ji do proměnné s názvemregion
.Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
Použijte metodu
Container.GetItemLinqQueryable<>
k získání dotazovatelného LINQ a sestavení dotazu LINQ fluently provedením těchto tří akcí:Použijte metodu
Queryable.Where<>
rozšíření k filtrování pouze položek s ekvivalentemcategory
"business-office"
.Znovu použijte
Queryable.Where<>
k filtrování pouze umístění v rámciregion
vlastnosti proměnnélocation
pomocíGeometry.Within()
.Přeložte výraz LINQ na iterátor informačního kanálu pomocí
CosmosLinqExtensions.ToFeedIterator<>
.
var regionIterator = container.GetItemLinqQueryable<Office>() .Where(o => o.category == "business-office") .Where(o => o.location.Within(region.location)) .ToFeedIterator<Office>();
Důležité
V tomto příkladu má vlastnost umístění kanceláře bod a vlastnost umístění oblasti má mnohoúhelník.
ST_WITHIN
určuje, zda je bod kanceláře v polygonu oblasti.Pomocí kombinace smyčky while a foreach iterujte všechny výsledky na každé stránce výsledků. Vypíše každý výsledek do konzoly.
while (regionIterator.HasMoreResults) { var response = await regionIterator.ReadNextAsync(); foreach (var office in response) { Console.WriteLine($"[IN REGION]\t{office}"); } }
Uložte soubor Program.cs.
Spusťte aplikaci jednou naposledy v terminálu pomocí
dotnet run
příkazu . Všimněte si, že výstup teď obsahuje výsledky druhého dotazu založeného na LINQ.dotnet run
[IN REGION] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Vyčištění prostředků
Po dokončení této příručky odeberte databázi.
Otevřete terminál a vytvořte proměnnou prostředí pro název vašeho účtu a skupiny prostředků.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"
Slouží
az cosmosdb sql database delete
k odebrání databáze.az cosmosdb sql database delete \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks"