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, mezi které mimo jiné patří:
- Zjištění, jestli se umístění nachází 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í
Tento průvodce 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 bezplatnou službu Azure Cosmos DB for NoSQL.
- 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žije 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
pomocíaz cosmosdb sql database create
.az cosmosdb sql database create \ --resource-group $resourceGroupName \ --account-name $accountName \ --name "cosmicworks" \ --throughput 400
Vytvořte nový soubor JSON s názvem index-policy.json a přidejte do souboru 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 klíčemlocations
oddílu/region
s cestou .az cosmosdb sql container create \ --resource-group $resourceGroupName \ --account-name $accountName \ --database-name "cosmicworks" \ --name "locations" \ --partition-key-path "/category" \ --idx @index-policy.json
Načtěte primární připojovací řetězec pro účet pomocí
az cosmosdb keys list
.az cosmosdb keys list \ --resource-group $resourceGroupName \ --name $accountName \ --type "connection-strings" \ --query "connectionStrings[?keyKind == \`Primary\`].connectionString" \ --output tsv
Tip
Pokud chcete zobrazit všechny možné připojovací řetězce pro účet, použijte
az cosmosdb keys list --resource-group $resourceGroupName --name $accountName --type "connection-strings"
.Zaznamenejte připojovací řetězec. Tyto přihlašovací údaje použijete dále v této příručce.
Vytvoření konzolové aplikace sady .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.
Vytvořte novou aplikaci .NET pomocí
dotnet new
příkazu se šablonou konzoly .dotnet new console
Importujte balíček NuGet Microsoft.Azure.Cosmos pomocí
dotnet add package
příkazu .dotnet add package Microsoft.Azure.Cosmos --version 3.*
Upozornění
Entity Framework v současné době ve službě Azure Cosmos DB for NoSQL neobsahuje prostorová data. Použijte některou ze sad Azure Cosmos DB for NoSQL SDK pro podporu GeoJSON se silnými typy.
Sestavte projekt pomocí
dotnet build
příkazu .dotnet build
Otevřete integrované vývojové prostředí (IDE) podle svého 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
Microsoft.Azure.Cosmos
using pro obory názvů ,Microsoft.Azure.Cosmos.Linq
aMicrosoft.Azure.Cosmos.Spatial
.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;
Přidejte řetězcovou proměnnou s názvem *
connectionString
s připojovacím řetězcem, který jste si poznamenali dříve v této příručce.string connectionString = "<your-account-connection-string>"
Vytvořte novou instanci
CosmosClient
třídy předávajícíconnectionString
a zabalte ji do příkazu using.using CosmosClient client = new (connectionString);
Pomocí a pak
Database.GetContainer
načtěte odkaz na dříve vytvořený kontejner (cosmicworks/locations
) v účtu Azure Cosmos DB for NoSQL.CosmosClient.GetDatabase
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í informací o novém umístění k položkám 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 Description Výchozí hodnota id string
Jedinečný identifikátor Jméno string
Název kanceláře Umístění 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 najdete 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 Description Výchozí hodnota id string
Jedinečný identifikátor Jméno string
Název kanceláře Umístění Polygon
Geografický obrazec 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 najdete v tématu GeoJSON Polygon.Vytvořte další nový soubor s názvem Result.cs. Přidejte typ záznamu s názvem
Result
s těmito dvěma vlastnostmi:Typ Description Jméno string
Název odpovídajícího výsledku vzdálenostKilometry decimal
Vzdálenost v km 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 nový
Polygon
v proměnné 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);
Použijte
Container.UpsertItemAsync
k přidání oblasti do kontejneru. Zapište informace o oblasti do konzoly.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");
Tip
Tato příručka používá upsert místo vložení , 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 upsert najdete v tématu Vytváření položek.
Vytvořte novou
Point
proměnnou s názvemheadquartersPoint
. Tuto proměnnou použijte k vytvoření novéOffice
proměnné s názvemheadquartersOffice
point, jedinečný identifikátor0001
a názevHeadquarters
.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
Vytvořte další
Point
proměnnou s názvemresearchPoint
. Tuto proměnnou použijte k vytvoření dalšíOffice
proměnné s názvem s použitímresearchOffice
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 k
TransactionalBatch
upsertu obouOffice
proměnných jako jednu transakci. Pak na konzolu zapište informace o obou pobočká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 najdete v tématu Transakční dávkové operace.
Uložte soubor Program.cs.
Spusťte aplikaci v terminálu pomocí příkazu
dotnet run
. 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ů je možné použít jako vstupy parametrizovaného dotazu NoSQL pro použití integrovaných funkcí, jako je ST_DISTANCE
.
Otevřete soubor Program.cs .
Vytvoření nové
string
proměnné s názvemnosql
s dotazem se použije 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
snosqlString
použitím proměnné jako parametru. Pak několikrát použijte metoduQueryDefinition.WithParameter
fluent a přidejte do dotazu tyto parametry: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é . Pak 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 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í příkazu
dotnet run
. 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 podporují zahrnutí geoprostorových typů do výrazů dotazu. Sada SDK navíc zahrnuje rozšiřující metody, které se mapuje na ekvivalentní integrované funkce:
Rozšiřující metoda | 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 k plynulému sestavení dotazu LINQ provedením těchto tří akcí:Pomocí rozšiřující metody vyfiltrujte
Queryable.Where<>
pouze položky, které majícategory
ekvivalent ."business-office"
Pomocí
Queryable.Where<>
příkazu znovu vyfiltrujte pouze umístění v rámciregion
vlastnosti proměnnélocation
.Geometry.Within()
Pomocí příkazu přeložte výraz LINQ na iterátor informačního kanálu
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 mnohoúhelník.
ST_WITHIN
určuje, zda se místo kanceláře nachází v polygonu oblasti.Pomocí kombinace smyčky while a foreach můžete iterovat 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 naposledy v terminálu pomocí příkazu
dotnet run
. 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 $resourceGroupName \ --account-name $accountName \ --name "cosmicworks"