NoSQL için Azure Cosmos DB'de GeoJSON konum verilerini dizine alın ve sorgula
UYGULANANLAR: NoSQL
NoSQL için Azure Cosmos DB'deki jeo-uzamsal veriler, konum bilgilerini depolamanıza ve bunlarla sınırlı olmamak üzere yaygın sorgular gerçekleştirmenize olanak tanır:
- Bir konumun tanımlı bir alan içinde olup olmadığını bulma
- İki konum arasındaki mesafeyi ölçme
- Bir yolun bir konum veya alanla kesişip kesişmediğini belirleme
Bu kılavuzda jeo-uzamsal veri oluşturma, verilerin dizinini oluşturma ve ardından kapsayıcıdaki verileri sorgulama işlemi açıklanmaktadır.
Önkoşullar
- Mevcut bir NoSQL için Azure Cosmos DB hesabı.
- Azure aboneliğiniz yoksa NoSQL için Azure Cosmos DB'yi ücretsiz deneyin.
- Mevcut bir Azure aboneliğiniz varsa Yeni bir NoSQL için Azure Cosmos DB hesabı oluşturun.
- .NET'in en son sürümü.
- Azure CLI'nın en son sürümü.
- Yerel yükleme kullanıyorsanız komutunu kullanarak
az login
Azure CLI'da oturum açın.
- Yerel yükleme kullanıyorsanız komutunu kullanarak
Kapsayıcı ve dizin oluşturma ilkesi oluşturma
Tüm kapsayıcılar, jeo-uzamsal verileri başarıyla dizine alacak bir varsayılan dizin oluşturma ilkesi içerir. Özelleştirilmiş dizin oluşturma ilkesi oluşturmak için bir hesap oluşturun ve ilkenin yapılandırmasına sahip bir JSON dosyası belirtin. Bu bölümde, yeni oluşturulan bir kapsayıcı için özel bir uzamsal dizin kullanılır.
Bir terminal açın.
NoSQL için Azure Cosmos DB hesabınızın ve kaynak grubunuzun adı için bir kabuk değişkeni oluşturun.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"
kullanarak
az cosmosdb sql database create
adlıcosmicworks
yeni bir veritabanı oluşturun.az cosmosdb sql database create \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks" \ --throughput 400
index-policy.json adlı yeni bir JSON dosyası oluşturun ve dosyaya aşağıdaki JSON nesnesini ekleyin.
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ], "spatialIndexes": [ { "path": "/location/*", "types": [ "Point", "Polygon" ] } ] }
bölüm anahtarı yolu
/region
ile adlılocations
yeni bir kapsayıcı oluşturmak için kullanınaz cosmosdb sql container create
.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
Son olarak, ve bir JMESPath sorgusu kullanarak
az cosmosdb show
hesabınızın hesap uç noktasını alın.az cosmosdb show \ --resource-group "<resource-group-name>" \ --name "<nosql-account-name>" \ --query "documentEndpoint"
Sonraki bölümde buna ihtiyacınız olacağı için hesap uç noktasını kaydedin.
.NET SDK konsol uygulaması oluşturma
NoSQL için Azure Cosmos DB için .NET SDK'sı, yaygın GeoJSON nesneleri için sınıflar sağlar. Kapsayıcınıza coğrafi nesneler ekleme işlemini kolaylaştırmak için bu SDK'yi kullanın.
Boş bir dizinde bir terminal açın.
konsol şablonuyla komutunu kullanarak
dotnet new
yeni bir .NET uygulaması oluşturun.dotnet new console
Microsoft.Azure.Cosmos
komutunu kullanarak NuGet paketini içeri aktarındotnet add package
.dotnet add package Microsoft.Azure.Cosmos --version 3.*
Uyarı
Entity Framework şu anda NoSQL için Azure Cosmos DB'de uzamsal veriler içermez. Güçlü türdeki GeoJSON desteği için NoSQL SDK'ları için Azure Cosmos DB'lerden birini kullanın.
NuGet paketini içeri aktarın
Azure.Identity
.dotnet add package Azure.Identity --version 1.*
komutuyla
dotnet build
projeyi oluşturun.dotnet build
Seçtiğiniz tümleşik geliştirici ortamını (IDE) .NET konsol uygulamanızla aynı dizinde açın.
Yeni oluşturulan Program.cs dosyasını açın ve mevcut kodları silin. ,
Microsoft.Azure.Cosmos.Linq
veMicrosoft.Azure.Cosmos.Spatial
ad alanları içinMicrosoft.Azure.Cosmos
using yönergeleri ekleyin.using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Spatial;
Ad alanı için başka bir using yönergesi
Azure.Identity
ekleyin.using Azure.Identity;
türünde
DefaultAzureCredential
adlıcredential
yeni bir değişken oluşturun.DefaultAzureCredential credential = new();
NoSQL için Azure Cosmos DB hesap uç noktanızla adlı
endpoint
bir dize değişkeni oluşturun.string endpoint = "<nosql-account-endpoint>";
sınıfının yeni bir örneğini
CosmosClient
connectionString
oluşturun ve bunu bir using deyiminde sarmalayın.using CosmosClient client = new (connectionString);
ve ardından
Database.GetContainer
kullanarakCosmosClient.GetDatabase
NoSQL için Azure Cosmos DB hesabında önceden oluşturulmuş kapsayıcıya (cosmicworks/locations
) bir başvuru alın. Sonucu adlıcontainer
bir değişkende depolayın.var container = client.GetDatabase("cosmicworks").GetContainer("locations");
Program.cs dosyasını kaydedin.
Jeo-uzamsal veri ekleme
.NET SDK'sı Microsoft.Azure.Cosmos.Spatial
, yaygın GeoJSON nesnelerini temsil etmek için ad alanında birden çok tür içerir. Bu türler, kapsayıcıdaki öğelere yeni konum bilgileri ekleme işlemini kolaylaştırır.
Office.cs adlı yeni bir dosya oluşturun. dosyasına bir using yönergesi
Microsoft.Azure.Cosmos.Spatial
ekleyin ve ardından şu özelliklere sahip birOffice
kayıt türü oluşturun:Type Açıklama Default value id string
Benzersiz tanımlayıcı ad string
Ofis adı konum Point
GeoJSON coğrafi noktası category string
Bölüm anahtarı değeri business-office
using Microsoft.Azure.Cosmos.Spatial; public record Office( string id, string name, Point location, string category = "business-office" );
Not
Bu kayıt, GeoJSON'da belirli bir konumu temsil eden bir özellik içerir
Point
. Daha fazla bilgi için bkz . GeoJSON Noktası.Region.cs adlı başka bir yeni dosya oluşturun. Şu özelliklere sahip adlı
Region
başka bir kayıt türü ekleyin:Type Açıklama Default value id string
Benzersiz tanımlayıcı ad string
Ofis adı konum Polygon
GeoJSON coğrafi şekli category string
Bölüm anahtarı değeri business-region
using Microsoft.Azure.Cosmos.Spatial; public record Region( string id, string name, Polygon location, string category = "business-region" );
Not
Bu kayıt, GeoJSON'da birden çok konum arasında çizilen çizgilerden oluşan şekli temsil eden bir özellik içerir
Polygon
. Daha fazla bilgi için bkz . GeoJSON Polygon.Result.cs adlı başka bir yeni dosya oluşturun. Şu iki özelliğe sahip adlı
Result
bir kayıt türü ekleyin:Type Açıklama ad string
Eşleşen sonucun adı distanceKilometers decimal
Kilometre cinsinden mesafe public record Result( string name, decimal distanceKilometers );
Office.cs, Region.cs ve Result.cs dosyalarını kaydedin.
Program.cs dosyasını yeniden açın.
adlı
mainCampusPolygon
değişkende yeniPolygon
bir oluşturun.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), }) } );
çokgenini, benzersiz tanımlayıcısını
1000
ve adınıMain Campus
kullanarak adlımainCampusRegion
yeniRegion
bir değişken oluşturun.Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
Bölgeyi kapsayıcıya eklemek için kullanın
Container.UpsertItemAsync
. Bölgenin bilgilerini konsola yazın.await container.UpsertItemAsync<Region>(mainCampusRegion); Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");
İpucu
Bu kılavuz, benzersiz tanımlayıcılar arasında çakışmaya neden olmadan betiği birden çok kez çalıştırabilmeniz için ekleme yerine upsert kullanır. Upsert işlemleri hakkında daha fazla bilgi için bkz . Öğe oluşturma.
adlı
headquartersPoint
yeniPoint
bir değişken oluşturun. noktasını, benzersiz tanımlayıcısını0001
ve adınıHeadquarters
kullanarak adlıheadquartersOffice
yeniOffice
bir değişken oluşturmak için bu değişkeni kullanın.Point headquartersPoint = new (-122.12827, 47.63980); Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
adlı
researchPoint
başka birPoint
değişken oluşturun. İlgili noktayı, benzersiz tanımlayıcıyı0002
ve adınıResearch and Development
kullanarak adlıresearchOffice
başka birOffice
değişken oluşturmak için bu değişkeni kullanın.Point researchPoint = new (-96.84369, 46.81298); Office researchOffice = new ("0002", "Research and Development", researchPoint);
TransactionalBatch
Her ikiOffice
değişkeni de tek bir işlem olarak eklemek için bir oluşturun. Ardından, her iki office bilgisini de konsola yazın.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}");
Not
İşlemler hakkında daha fazla bilgi için bkz . işlem toplu işlemleri.
Program.cs dosyasını kaydedin.
kullanarak
dotnet run
uygulamayı bir terminalde çalıştırın. Uygulama çalıştırmasının çıktısının yeni oluşturulan üç öğe hakkında bilgi içerdiğini gözlemleyin.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 sorgusu kullanarak jeo-uzamsal verileri sorgulama
Ad alanı içindeki Microsoft.Azure.Cosmos.Spatial
türler, gibi ST_DISTANCE
yerleşik işlevleri kullanmak için NoSQL parametreli sorguya giriş olarak kullanılabilir.
Program.cs dosyasını açın.
Bu bölümde noktalar arasındaki mesafeyi ölçmek için sorgu ile adlı
nosql
yenistring
bir değişken oluşturun.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 ";
İpucu
Bu sorgu, ve yan tümcelerinde zaten hesaplanmış değeri birden çok kez yeniden kullanma işlemini basitleştirmek için jeo-uzamsal işlevi bir alt sorguya
SELECT
WHERE
yerleştirir.değişkenini parametre olarak kullanarak
nosqlString
adlıquery
yeniQueryDefinition
bir değişken oluşturun. Ardından bu parametreleri sorguya eklemek için fluent yöntemini birden çok kez kullanınQueryDefinition.WithParameter
:Değer @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));
kullanarak, genel türü ve değişkenini
query
kullanarakContainer.GetItemQueryIterator<>
Result
yeni bir yineleyici oluşturun. Ardından, her sonuç sayfasındaki tüm sonuçları yinelemek için bir süre ve foreach döngüsünün birleşimini kullanın. Her sonucu konsola çıktı olarak ekleyin.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}"); } }
Not
Sorgu sonuçlarını numaralandırma hakkında daha fazla bilgi için bkz . sorgu öğeleri.
Program.cs dosyasını kaydedin.
kullanarak
dotnet run
uygulamayı terminalde yeniden çalıştırın. Çıkışın artık sorgunun sonuçlarını içerdiğini gözlemleyin.dotnet run
[DISTANCE KM] Result { name = Headquarters, distanceKilometers = 3.34 } [DISTANCE KM] Result { name = Research and Development, distanceKilometers = 1907.43 }
LINQ kullanarak jeo-uzamsal verileri sorgulama
.NET SDK'sında LINQ to NoSQL işlevi, sorgu ifadelerine jeo-uzamsal türlerin dahil olmasını destekler. Ayrıca SDK, eşdeğer yerleşik işlevlerle eşlenen uzantı yöntemleri içerir:
Uzantı yöntemi | Yerleşik işlev |
---|---|
Distance() |
ST_DISTANCE |
Intersects() |
ST_INTERSECTS |
IsValid() |
ST_ISVALID |
IsValidDetailed() |
ST_ISVALIDDETAILED |
Within() |
ST_WITHIN |
Program.cs dosyasını açın.
Benzersiz tanımlayıcısı
Region
1000
olan kapsayıcıdan öğeyi alın ve adlıregion
bir değişkende depolayın.Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
Container.GetItemLinqQueryable<>
Sorgulanabilir bir LINQ almak için yöntemini kullanın ve şu üç eylemi gerçekleştirerek LINQ sorgusunu akıcı bir şekilde oluşturun:Yalnızca eşdeğeri
Queryable.Where<>
olancategory
öğelere filtre uygulamak için"business-office"
uzantı yöntemini kullanın.kullanarak
Geometry.Within()
yalnızca değişkeninlocation
özelliğindekiregion
konumlara filtre uygulamak için yeniden kullanınQueryable.Where<>
.kullanarak
CosmosLinqExtensions.ToFeedIterator<>
LINQ ifadesini bir akış yineleyicisine çevirin.
var regionIterator = container.GetItemLinqQueryable<Office>() .Where(o => o.category == "business-office") .Where(o => o.location.Within(region.location)) .ToFeedIterator<Office>();
Önemli
Bu örnekte, ofisin konum özelliği bir noktaya ve bölgenin konum özelliği çokgene sahiptir.
ST_WITHIN
ofisin noktasının bölgenin çokgeni içinde olup olmadığını belirler.Her sonuç sayfasındaki tüm sonuçları yinelemek için bir süre ve foreach döngüsünün birleşimini kullanın. Her sonucu konsola çıktı olarak ekleyin.
while (regionIterator.HasMoreResults) { var response = await regionIterator.ReadNextAsync(); foreach (var office in response) { Console.WriteLine($"[IN REGION]\t{office}"); } }
Program.cs dosyasını kaydedin.
kullanarak
dotnet run
uygulamayı bir terminalde son kez çalıştırın. Çıkışın artık ikinci LINQ tabanlı sorgunun sonuçlarını içerdiğini gözlemleyin.dotnet run
[IN REGION] Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
Kaynakları temizleme
Bu kılavuzu tamamladıktan sonra veritabanınızı kaldırın.
Bir terminal açın ve hesabınızın ve kaynak grubunuzun adı için bir kabuk değişkeni oluşturun.
# Variable for resource group name resourceGroupName="<name-of-your-resource-group>" # Variable for account name accountName="<name-of-your-account>"
Veritabanını kaldırmak için kullanın
az cosmosdb sql database delete
.az cosmosdb sql database delete \ --resource-group "<resource-group-name>" \ --account-name "<nosql-account-name>" \ --name "cosmicworks"