Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os dados geoespaciais no Azure Cosmos DB for NoSQL permitem armazenar informações de localização e executar consultas comuns, incluindo, mas não se limitando a:
- Descobrir se um local está dentro de uma área definida
- Medir a distância entre dois locais
- Determinar se um caminho se cruza com um local ou uma área
Esse guia orienta você ao longo do processo de criar dados geoespaciais, indexar os dados e, em seguida, consultar os dados em um contêiner.
Pré-requisitos
- Uma conta existente do Azure Cosmos DB for NoSQL.
- Se não tiver uma assinatura do Azure, Experimente o Azure Cosmos DB for NoSQL gratuitamente.
- Se tiver uma assinatura existente do Azure, crie uma conta nova do Azure Cosmos DB for NoSQL.
- Versão mais recente do .NET.
- Versão mais recente da CLI do Azure.
- Se estiver usando uma instalação local, entre com a CLI do Azure usando o comando
az login.
- Se estiver usando uma instalação local, entre com a CLI do Azure usando o comando
Criar um contêiner e uma política de indexação
Todos os contêineres incluem uma política de indexação padrão que irá indexar os dados geoespaciais com sucesso. Para criar uma política de indexação personalizada, crie uma conta e especifique um arquivo JSON com a configuração da política. Nesta seção, um índice espacial personalizado é usado para um contêiner recém-criado.
Abra um terminal.
Crie uma variável de shell para o nome da conta e do grupo de recursos do seu 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>"Crie um novo banco de dados chamado
cosmicworksusandoaz cosmosdb sql database create.az cosmosdb sql database create \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks" \ --throughput 400Crie um novo arquivo JSON chamado index-policy.json e adicione ao arquivo o objeto JSON a seguir.
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ], "spatialIndexes": [ { "path": "/location/*", "types": [ "Point", "Polygon" ] } ] }Use um
az cosmosdb sql container createpara criar um novo contêiner chamadolocationscom um caminho de chave de partição de/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.jsonPara terminar, obtenha o ponto de extremidade de conta para a sua conta usando
az cosmosdb showe uma consulta JMESPath.az cosmosdb show \ --resource-group "<resource-group-name>" \ --name "<nosql-account-name>" \ --query "documentEndpoint"Anote o ponto de extremidade da conta porque você vai precisar dele na próxima seção.
Criar um SDK de aplicativo de console do .NET
O SDK do .NET para o Azure Cosmos DB for NoSQL fornece classes para objetos GeoJSON comuns. Use esse SDK para simplificar o processo de adicionar objetos geográficos ao seu contêiner.
Abra um terminal em um diretório vazio.
Crie um novo aplicativo .NET usando o comando
dotnet newcom o modelo de console .dotnet new consoleImporte o pacote NuGet
Microsoft.Azure.Cosmosusando o comandodotnet add package.dotnet add package Microsoft.Azure.Cosmos --version 3.*Aviso
Atualmente, o Entity Framework não dá suporte a dados espaciais no Azure Cosmos DB for NoSQL. Use um dos SDKs do Azure Cosmos DB for NoSQL para obter um suporte fortemente tipado ao GeoJSON.
Importe o pacote NuGet
Azure.Identity.dotnet add package Azure.Identity --version 1.*Compile o projeto com o
dotnet buildcomando.dotnet buildAbra o ambiente de desenvolvedor integrado (IDE) de sua escolha no mesmo diretório que o seu aplicativo de console do .NET.
Abra o arquivo Program.cs recém-criado e exclua qualquer código existente. Adicione diretivas de uso para os namespaces
Microsoft.Azure.Cosmos,Microsoft.Azure.Cosmos.LinqeMicrosoft.Azure.Cosmos.Spatial.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;Adicione outra diretiva de uso para o namespace
Azure.Identity.using Azure.Identity;Crie uma nova variável do tipo
credentialchamadaDefaultAzureCredential.DefaultAzureCredential credential = new();Crie uma variável de cadeia de caracteres chamada
endpointcom o ponto de extremidade da sua conta do Azure Cosmos DB for NoSQL.string endpoint = "<nosql-account-endpoint>";Crie uma nova instância da classe
CosmosClienttransmitindo-a paraconnectionStringe encapsulando-a em uma instrução using.using CosmosClient client = new (connectionString);Recupere uma referência ao contêiner criado anteriormente (
cosmicworks/locations) na conta do Azure Cosmos DB for NoSQL usandoCosmosClient.GetDatabasee, em seguida,Database.GetContainer. Armazene o resultado em uma variável chamadacontainer.var container = client.GetDatabase("cosmicworks").GetContainer("locations");Salve o arquivo Program.cs.
Adicionar dados geoespaciais
O SDK do .NET inclui vários tipos no namespace Microsoft.Azure.Cosmos.Spatial para representar objetos GeoJSON comuns. Esses tipos simplificam o processo de adicionar novas informações de localização aos itens em um contêiner.
Crie um novo arquivo chamado Office.cs. No arquivo, adicione uma diretiva using a
Microsoft.Azure.Cosmos.Spatiale crie umOfficetipo de registro com essas propriedades:Tipo Description Valor padrão id stringIdentificador exclusivo name stringNome do escritório localização PointPonto geográfico GeoJSON categoria stringValor da chave de partição business-officeusing Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );Observação
Esse registro inclui uma propriedade
Pointque representa uma posição específica no GeoJSON. Para obter mais informações, confira Ponto GeoJSON.Crie outro arquivo novo chamado Category.cs. Adicione outro tipo de registro chamado
Regioncom essas propriedades:Tipo Description Valor padrão id stringIdentificador exclusivo name stringNome do escritório localização PolygonForma geográfica GeoJSON categoria stringValor da chave de partição business-regionusing Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );Observação
Esse registro inclui uma propriedade
Polygonque representa uma forma composta de linhas desenhadas entre diversos locais no GeoJSON. Para obter mais informações, confira Polígono GeoJSON.Crie outro arquivo novo chamado Result.cs. Adicione um tipo de registro chamado
Resultcom essas duas propriedades:Tipo Description name stringNome do resultado equiparado distanceKilometers decimalDistância em quilômetros public record Result( string name, decimal distanceKilometers );Salve os arquivos Office.cs, Region.cs e Result.cs.
Abra o arquivo Program.cs outra vez.
Crie um novo
Polygonem uma variável chamadamainCampusPolygon.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), }) } );Crie uma nova variável
RegionchamadamainCampusRegionusando o polígono, o identificador único1000e o nomeMain Campus.Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);Use
Container.UpsertItemAsyncpara adicionar a região ao contêiner. Escreva as informações da região no console.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");Dica
Este guia usa upsert em vez de inserir para que você possa executar o script várias vezes sem causar um conflito entre os identificadores únicos. Para obter mais informações sobre operações upsert, consulte como criar itens.
Crie uma nova variável
PointchamadaheadquartersPoint. Use essa variável para criar uma nova variávelOfficechamadaheadquartersOfficeusando o ponto, o identificador único0001e o nomeHeadquarters.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);Crie outra
Pointvariável chamadaresearchPoint. Use essa variável para criar uma outra variávelOfficechamadaresearchOfficeusando o respectivo ponto, o identificador único0002e o nomeResearch and Development.Point researchPoint = new (-96.84369, 46.81298); Office researchOffice = new ("0002", "Research and Development", researchPoint);Crie um
TransactionalBatchpara fazer upsert de ambas as variáveisOfficecomo uma única transação. Em seguida, grave as informações dos dois escritórios no 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}");Observação
Para obter mais informações sobre transações, confira operações em lotes transacionais.
Salve o arquivo Program.cs.
Execute o aplicativo em um terminal usando
dotnet run. Observe que a saída da execução do aplicativo inclui informações sobre os três itens recém-criados.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 }
Consultar dados geoespaciais usando a consulta NoSQL
Os tipos no namespace Microsoft.Azure.Cosmos.Spatial podem ser usados como entradas de dados para uma consulta parametrizada NoSQL para usar funções integradas como ST_DISTANCE.
Abra o arquivo Program.cs.
Criar uma nova variável
stringchamadanosqlcuja consulta é usada nesta seção para medir a distância entre pontos.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 ";Dica
Essa consulta coloca a função geoespacial dentro de uma subconsulta para simplificar o processo de reutilização do valor já calculado várias vezes nas cláusulas
SELECTeWHERE.Crie uma nova variável
QueryDefinitionchamadaqueryusando a variávelnosqlStringcomo um parâmetro. Em seguida, use o método fluenteQueryDefinition.WithParametervárias vezes para adicionar esses parâmetros à consulta:Value @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));Crie um novo iterador usando
Container.GetItemQueryIterator<>, o tipo genéricoResulte a variávelquery. Em seguida, use uma combinação de um loop while e foreach para iterar todos os resultados em cada página de resultados. Exiba cada resultado no 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}"); } }Observação
Para obter mais informações sobre como enumerar os resultados da consulta, confira itens de consulta.
Salve o arquivo Program.cs.
Execute o aplicativo novamente em um terminal usando
dotnet run. Observe que a saída agora inclui os resultados da consulta.dotnet run[DISTANCE KM] Result { name = Headquarters, distanceKilometers = 3.34 } [DISTANCE KM] Result { name = Research and Development, distanceKilometers = 1907.43 }
Consultar dados geoespaciais usando LINQ
A funcionalidade LINQ to NoSQL no SDK do .NET dá suporte à inclusão de tipos geoespaciais nas expressões de consulta. Mais ainda, o SDK inclui métodos de extensão que são mapeados para funções integradas equivalentes:
| Método de extensão | Função integrada |
|---|---|
Distance() |
ST_DISTANCE |
Intersects() |
ST_INTERSECTS |
IsValid() |
ST_ISVALID |
IsValidDetailed() |
ST_ISVALIDDETAILED |
Within() |
ST_WITHIN |
Abra o arquivo Program.cs.
Recupere o item
Regiondo contêiner com um identificador único de1000e o armazene em uma variável chamadaregion.Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));Use o método
Container.GetItemLinqQueryable<>para obter um LINQ consultável e crie a consulta LINQ fluentemente executando essas três ações:Use o método de extensão
Queryable.Where<>para filtrar apenas para itens com umacategoryequivalente a"business-office".Use
Queryable.Where<>novamente para filtrar locais somente dentro da propriedaderegionda variávellocationusandoGeometry.Within().Traduza a expressão LINQ em um iterador de feed usando
CosmosLinqExtensions.ToFeedIterator<>.
var regionIterator = container.GetItemLinqQueryable<Office>() .Where(o => o.category == "business-office") .Where(o => o.location.Within(region.location)) .ToFeedIterator<Office>();Importante
Nesse exemplo, a propriedade de localização do escritório tem um ponto e a propriedade de localização da região tem um polígono.
ST_WITHINestá determinando se o ponto do escritório está dentro do polígono da região.Use uma combinação de um loop while e foreach para iterar todos os resultados em cada página de resultados. Exiba cada resultado no console.
while (regionIterator.HasMoreResults) { var response = await regionIterator.ReadNextAsync(); foreach (var office in response) { Console.WriteLine($"[IN REGION]\t{office}"); } }Salve o arquivo Program.cs.
Execute o aplicativo uma última vez em um terminal usando
dotnet run. Observe que a saída agora inclui os resultados da segunda consulta baseada em LINQ.dotnet run[IN REGION] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Limpar os recursos
Remova seu banco de dados após concluir este guia.
Abra um terminal e crie uma variável de shell para o nome da sua conta e grupo de recursos.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"Use
az cosmosdb sql database deletepara remover o banco de dados.az cosmosdb sql database delete \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks"