Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL
Геопространственные данные в Azure Cosmos DB для NoSQL позволяют хранить сведения о расположении и выполнять общие запросы, включая не только следующие:
- Определение нахождения местоположения в границах заданной области
- Измерение расстояния между двумя расположениями
- Определение того, пересекается ли путь с местом или областью
В этом руководстве описывается процесс создания геопространственных данных, индексирования данных и последующего запроса данных в контейнере.
Требования
- Существующая учетная запись Azure Cosmos DB для NoSQL.
- Если у вас нет подписки Azure, попробуйте использовать Azure Cosmos DB для NoSQL бесплатно.
- Если у вас есть подписка Azure, создайте новую учетную запись Azure Cosmos DB для NoSQL.
- Последняя версия .NET.
- Последняя версия Azure CLI.
- Если вы используете локальную установку, войдите в Azure CLI с помощью
az loginкоманды.
- Если вы используете локальную установку, войдите в Azure CLI с помощью
Создание политики контейнера и индексирования
Все контейнеры включают политику индексирования по умолчанию, которая успешно индексирует геопространственные данные. Чтобы создать настраиваемую политику индексирования, создайте учетную запись и укажите JSON-файл с конфигурацией политики. В этом разделе для только что созданного контейнера используется настраиваемый пространственный индекс.
Откройте окно терминала.
Создайте переменную оболочки для имени учетной записи Azure Cosmos DB для NoSQL и группы ресурсов.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"Создайте новую базу данных с именем
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Создайте файл JSON с именем index-policy.json и добавьте следующий объект JSON в файл.
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ], "spatialIndexes": [ { "path": "/location/*", "types": [ "Point", "Polygon" ] } ] }Используйте
az cosmosdb sql container createдля создания нового контейнера с именемlocationsс путем ключа раздела/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Наконец, получите конечную точку для вашей учетной записи с помощью
az cosmosdb show, используя запрос JMESPath.az cosmosdb show \ --resource-group "<resource-group-name>" \ --name "<nosql-account-name>" \ --query "documentEndpoint"Запишите конечную точку учетной записи, так как это потребуется в следующем разделе.
Создание консольного приложения пакета SDK для .NET
Пакет SDK для .NET для Azure Cosmos DB для NoSQL предоставляет классы для распространенных объектов GeoJSON. Используйте этот пакет SDK для упрощения процесса добавления географических объектов в контейнер.
Откройте терминал в пустом каталоге.
Создайте новое приложение .NET, используя команду
dotnet newс шаблоном console.dotnet new consoleMicrosoft.Azure.CosmosИмпортируйте пакет NuGet с помощьюdotnet add packageкоманды.dotnet add package Microsoft.Azure.Cosmos --version 3.*Предупреждение
Entity Framework в настоящее время не поддерживает пространственные данные в Azure Cosmos DB для NoSQL. Используйте один из SDK Azure Cosmos DB для NoSQL, чтобы обеспечить строго типизированную поддержку GeoJSON.
Azure.IdentityИмпортируйте пакет NuGet.dotnet add package Azure.Identity --version 1.*Создайте проект с помощью команды
dotnet build.dotnet buildОткройте интегрированную среду разработки (IDE) в том же каталоге, что и консольное приложение .NET.
Откройте созданный файл Program.cs и удалите существующий код. Добавьте директивы using для пространств имен
Microsoft.Azure.Cosmos,Microsoft.Azure.Cosmos.Linq, иMicrosoft.Azure.Cosmos.Spatial.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;Добавьте еще одну директиву using для пространства имен
Azure.Identity.using Azure.Identity;Создайте новую переменную с именем
credentialтипаDefaultAzureCredential.DefaultAzureCredential credential = new();Создайте строковую переменную с именем
endpoint, которая будет использоваться для конечной точки учетной записи Azure Cosmos DB с поддержкой NoSQL.string endpoint = "<nosql-account-endpoint>";Создайте новый экземпляр класса
CosmosClient, передавconnectionString, и оберните его в оператор using.using CosmosClient client = new (connectionString);Получите ссылку на ранее созданный контейнер (
cosmicworks/locations) в учетной записи Azure Cosmos DB для NoSQL с помощьюCosmosClient.GetDatabase, а затемDatabase.GetContainer. Сохраните результат в переменной под названиемcontainer.var container = client.GetDatabase("cosmicworks").GetContainer("locations");Сохраните файл Program.cs.
Добавление геопространственных данных
Пакет SDK для .NET включает несколько типов в пространстве имен Microsoft.Azure.Cosmos.Spatial для представления общих объектов GeoJSON. Эти типы упрощают процесс добавления новых сведений о расположении в элементы в контейнере.
Создайте файл с именем Office.cs. В файле добавьте директиву using для
Microsoft.Azure.Cosmos.Spatial, а затем создайтеOfficeтип записи со следующими свойствами:Тип Описание Значение по умолчанию id stringУникальный идентификатор name stringИмя офиса расположение PointГеографическая точка GeoJSON категория stringЗначение ключа раздела business-officeusing Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );Примечание.
Эта запись включает
Pointсвойство, представляющее определенную позицию в GeoJSON. Дополнительные сведения см. в разделе GeoJSON Point.Создайте другой файл с именем Region.cs. Добавьте еще один тип записи с именем
Regionи следующими свойствами:Тип Описание Значение по умолчанию id stringУникальный идентификатор name stringИмя офиса расположение PolygonГеографическая фигура GeoJSON категория stringЗначение ключа раздела business-regionusing Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );Примечание.
Эта запись включает
Polygonсвойство, представляющее фигуру, состоящую из линий, нарисованных между несколькими точками в GeoJSON. Дополнительные сведения см. в разделе GeoJSON Polygon.Создайте другой файл с именем Result.cs. Добавьте тип
Resultзаписи с этими двумя свойствами:Тип Описание name stringИмя соответствующего результата distanceKilometers decimalРасстояние в километрах public record Result( string name, decimal distanceKilometers );Сохраните файлы Office.cs, Region.cs и Result.cs .
Откройте опять файл Program.cs.
Создайте новую
Polygonпеременную с именемmainCampusPolygon.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), }) } );Создайте новую переменную
Regionс именемmainCampusRegionс использованием многоугольника, уникального идентификатора1000, и имениMain Campus.Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);Используйте
Container.UpsertItemAsyncдля добавления региона в контейнер. Напишите сведения о регионе в консоль.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");Совет
В этом руководстве используется upsert вместо вставки , чтобы можно было выполнять скрипт несколько раз, не вызывая конфликт между уникальными идентификаторами. Дополнительные сведения об операциях upsert см. в статье о создании элементов.
Создайте новую
Pointпеременную с именемheadquartersPoint. Используйте ту переменную для создания новой переменнойOffice, используя точку, уникальный идентификаторheadquartersOfficeи имя0001.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);Создайте другую
Pointпеременную с именемresearchPoint. Используйте ту переменную, чтобы создать другуюOfficeпеременнуюresearchOfficeс помощью соответствующей точки, уникального идентификатора0002и имениResearch and Development.Point researchPoint = new (-96.84369, 46.81298); Office researchOffice = new ("0002", "Research and Development", researchPoint);Создайте
TransactionalBatch, чтобы выполнить upsert обеихOfficeпеременных в рамках одной транзакции. Затем напишите сведения о обоих офисах в консоль.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}");Примечание.
Дополнительные сведения о транзакциях см. в разделе транзакционные пакетные операции.
Сохраните файл Program.cs.
Запустите приложение в терминале с помощью
dotnet run. Обратите внимание, что выходные данные запуска приложения содержат сведения о трех только что созданных элементах.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 }
Запрос геопространственных данных с помощью запроса NoSQL
Типы в Microsoft.Azure.Cosmos.Spatial пространстве имен можно использовать в качестве входных данных для параметризованного запроса NoSQL для использования встроенных функций, таких как ST_DISTANCE.
Откройте файл Program.cs.
Создайте новую переменную
string, названнуюnosql, которая будет использоваться в этом разделе для измерения расстояния между точками.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 ";Совет
Этот запрос помещает геопространственную функцию в вложенный запрос, чтобы упростить процесс повторного использования уже вычисленного значения несколько раз в
SELECTиWHEREпредложениях.Создайте новую
QueryDefinitionпеременную с именемqueryс помощью переменнойnosqlStringв качестве параметра. Затем несколько раз используйтеQueryDefinition.WithParameterметод fluent, чтобы добавить эти параметры в запрос:Значение @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));Создайте новый итератор, используя
Container.GetItemQueryIterator<>, универсальный типResultи переменнуюquery. Затем используйте сочетание цикла while и цикла foreach, для перебора всех результатов на каждой странице результатов. Выводит каждый результат в консоль.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}"); } }Примечание.
Дополнительные сведения о перечислении результатов запроса см. в разделе "Элементы запроса".
Сохраните файл Program.cs.
Снова запустите приложение в терминале с помощью
dotnet run. Обратите внимание, что выходные данные теперь включают результаты запроса.dotnet run[DISTANCE KM] Result { name = Headquarters, distanceKilometers = 3.34 } [DISTANCE KM] Result { name = Research and Development, distanceKilometers = 1907.43 }
Запрос геопространственных данных с помощью LINQ
Функции LINQ to NoSQL в пакете SDK для .NET поддерживают включение геопространственных типов в выражения запроса. Кроме того, пакет SDK включает методы расширения, которые сопоставляют с эквивалентными встроенными функциями:
| Метод расширения | Встроенная функция |
|---|---|
Distance() |
ST_DISTANCE |
Intersects() |
ST_INTERSECTS |
IsValid() |
ST_ISVALID |
IsValidDetailed() |
ST_ISVALIDDETAILED |
Within() |
ST_WITHIN |
Откройте файл Program.cs.
RegionИзвлеките элемент из контейнера с уникальным идентификатором1000и сохраните его в переменной с именемregion.Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));Используйте метод
Container.GetItemLinqQueryable<>, чтобы получить объект LINQ queryable, и стройте запрос LINQ последовательно, выполняя следующие три действия:Queryable.Where<>Используйте метод расширения, чтобы отфильтровать только элементы с эквивалентомcategory"business-office".Используйте
Queryable.Where<>еще раз, чтобы отфильтровать только расположения в свойствеregionпеременнойlocationс помощьюGeometry.Within().Переведите выражение LINQ в итератор потока с помощью
CosmosLinqExtensions.ToFeedIterator<>.
var regionIterator = container.GetItemLinqQueryable<Office>() .Where(o => o.category == "business-office") .Where(o => o.location.Within(region.location)) .ToFeedIterator<Office>();Внимание
В этом примере местоположение офиса представлено точкой, а местоположение региона представлено многоугольником.
ST_WITHINопределяет, находится ли точка офиса в многоугольнике региона.Используйте сочетание цикла while и цикла foreach, чтобы перебирать все результаты на каждой странице. Выводит каждый результат в консоль.
while (regionIterator.HasMoreResults) { var response = await regionIterator.ReadNextAsync(); foreach (var office in response) { Console.WriteLine($"[IN REGION]\t{office}"); } }Сохраните файл Program.cs.
Запустите приложение в последний раз в терминале с помощью
dotnet run. Обратите внимание, что выходные данные теперь включают результаты второго запроса на основе LINQ.dotnet run[IN REGION] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Очистка ресурсов
Удалите базу данных после завершения работы с этим руководством.
Откройте терминал и создайте переменную оболочки для имени учетной записи и группы ресурсов.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"Используется
az cosmosdb sql database deleteдля удаления базы данных.az cosmosdb sql database delete \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks"