適用於:NoSQL
Azure Cosmos DB for NoSQL 中的地理空間資料可讓您儲存位置資訊及執行一般查詢,包括 (但不限於):
- 確認某個位置是否在定義的區域內
- 測量兩個位置之間的距離
- 判斷路徑是否與某個位置或區域相交
本指南會逐步解說建立地理空間資料、編製資料索引,然後查詢容器所含資料的程序。
必要條件
- 現有的 Azure Cosmos DB for NoSQL 帳戶。
- 如果您沒有 Azure 訂用帳戶,可以免費試用 Azure Cosmos DB for NoSQL。
- 如果您有現有的 Azure 訂用帳戶,請建立新的 Azure Cosmos DB for NoSQL 帳戶。
- 最新版的 .NET。
- 最新版的 Azure CLI。
- 如果您使用本機安裝,請使用
az login命令登入 Azure CLI。
- 如果您使用本機安裝,請使用
建立容器和編製原則索引
所有容器都包含可成功為地理空間資料編製索引的預設索引編製原則。 若要建立自訂的索引編製原則,請建立帳戶,並使用原則的設定指定 JSON 檔案。 本節會對新建立的容器使用自訂空間索引。
開啟終端機。
為您的 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>"使用
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建立名為 index-policy.json 的新 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"記錄帳戶端點,因為在下一節中將會用到此端點。
建立 .NET SDK 主控台應用程式
Azure Cosmos DB for NoSQL 的 .NET SDK 提供通用 GeoJSON 物件的類別。 使用此 SDK 簡化將地理物件新增至容器的程序。
在空的目錄中開啟終端機。
使用
dotnet new命令搭配主控台範本來建立新的 .NET 應用程式。dotnet new console使用
Microsoft.Azure.Cosmos命令匯入dotnet add packageNuGet 套件。dotnet add package Microsoft.Azure.Cosmos --version 3.*警告
Entity Framework 目前不支援 Azure Cosmos DB for NoSQL 中的空間資料。 將其中一個 Azure Cosmos DB for NoSQL 用於強型別 GeoJSON 支援。
匯入
Azure.IdentityNuGet 套件。dotnet add package Azure.Identity --version 1.*使用
dotnet build命令建立專案。dotnet build在與您的 .NET 主控台應用程式相同的目錄中,開啟您選擇的整合式開發人員環境 (IDE)。
開啟新建立的 Program.cs 檔案,並刪除任何現有的程式碼。 為 、
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();使用適用於 NoSQL 帳戶端點的 Azure Cosmos DB 建立名為
endpoint的字串變數。string endpoint = "<nosql-account-endpoint>";傳入
CosmosClient並將其包裝在connectionString中,以建立 類別的新執行個體。using CosmosClient client = new (connectionString);依序使用
cosmicworks/locations和CosmosClient.GetDatabase,在 Azure Cosmos DB for NoSQL 帳戶中擷取對先前建立的容器 (Database.GetContainer) 的參考。 將結果儲存在名為container的變數中。var container = client.GetDatabase("cosmicworks").GetContainer("locations");儲存 Program.cs 檔案。
新增地理空間資料
.NET SDK 在 Microsoft.Azure.Cosmos.Spatial 命名空間中包含了多個類型,以代表常見的 GeoJSON 物件。 這些類型可簡化將新的位置資訊新增至容器所含項目的程序。
建立名為 Office.cs 的新檔案。 在 檔案中,將 using 指示詞新增至
Microsoft.Azure.Cosmos.Spatial,然後使用下列屬性建立Office記錄類型:類型 描述 預設值 id string唯一識別碼 name string辦公室的名稱 位置 PointGeoJSON 地理點 category string分割區索引鍵值 business-officeusing Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );建立名為 Region.cs 的另一個新檔案。 使用下列屬性新增名為
Region的另一個記錄類型:類型 描述 預設值 id string唯一識別碼 name string辦公室的名稱 位置 PolygonGeoJSON 地理圖形 category string分割區索引鍵值 business-regionusing Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );注意
此記錄包含
Polygon屬性,代表在 GeoJSON 中的多個位置之間繪製的線條所組成的圖形。 如需詳細資訊,請參閱 GeoJSON 多邊形。建立名為 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 而不是 insert,因此您可以執行指令碼多次,而不會造成唯一識別碼之間的衝突。 如需 upsert 作業的詳細資訊,請參閱建立項目。
新建名為
Point的headquartersPoint變數。 使用該變數新建名為Office的headquartersOffice變數 (使用點、唯一識別碼0001和名稱Headquarters)。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以將兩個Office變數 upsert 為單一交易。 然後,將這兩個辦公室的資訊都寫入主控台。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 ";使用
QueryDefinition變數作為參數,新建名為query的nosqlString變數。 然後,使用QueryDefinition.WithParameterfluent 方法多次,將這些參數新增至查詢:值 @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 查詢地理空間資料
.NET SDK 中的 LINQ to NoSQL 功能支援在查詢運算式中包含地理空間類型。 此外,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,並藉由執行以下三個動作順暢地建置 LINQ 查詢:使用
Queryable.Where<>擴充方法,僅篩選出category等同於"business-office"的項目。再次使用
Queryable.Where<>並搭配region,僅篩選出location變數的Geometry.Within()屬性內的位置。使用
CosmosLinqExtensions.ToFeedIterator<>將 LINQ 運算式轉譯為摘要迭代器。
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"