NoSQL için Azure Cosmos DB'de GeoJSON konum verilerini dizine alın ve sorgula

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.

Prerequisites

Kapsayıcı ve dizinleme 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.

  1. Bir terminal açın.

  2. 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>"
    
  3. kullanarak cosmicworksadlı az cosmosdb sql database create yeni bir veritabanı oluşturun.

    az cosmosdb sql database create \
        --resource-group "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --name "cosmicworks" \
        --throughput 400
    
  4. 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"
          ]
        }
      ]
    }
    
  5. az cosmosdb sql container create kullanarak, locations adlı ve bölüm anahtar yolu /category olan yeni bir kapsayıcı oluşturun.

    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
    
  6. Son olarak, az cosmosdb show ve bir JMESPath sorgusu kullanarak hesabınızın uç noktasını alın.

    az cosmosdb show \
        --resource-group "<resource-group-name>" \
        --name "<nosql-account-name>" \
        --query "documentEndpoint"
    
  7. 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.

  1. Boş bir dizinde bir terminal açın.

  2. dotnet new şablonuyla komutunu kullanarak yeni bir .NET uygulaması oluşturun.

    dotnet new console
    
  3. Microsoft.Azure.Cosmos komutunu kullanarak dotnet add package NuGet paketini içeri aktarın.

    dotnet add package Microsoft.Azure.Cosmos --version 3.*
    

    Warning

    Entity Framework şu anda NoSQL için Azure Cosmos DB uzamsal verileri desteklememektedir. Azure Cosmos DB'nin NoSQL için hazırlanmış SDK'larından birini, güçlü tür uyumlu GeoJSON desteği sağlamak üzere kullanın.

  4. Azure.Identity NuGet paketini içeri aktarın.

    dotnet add package Azure.Identity --version 1.*
    
  5. komutuyla dotnet build projeyi oluşturun.

    dotnet build
    
  6. Seçtiğiniz tümleşik geliştirici ortamını (IDE) .NET konsol uygulamanızla aynı dizinde açın.

  7. Yeni oluşturulan Program.cs dosyasını açın ve mevcut kodları silin. , Microsoft.Azure.Cosmos, ve Microsoft.Azure.Cosmos.Linq ad alanları için Microsoft.Azure.Cosmos.Spatial.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  8. Azure.Identity ad alanı için başka bir using yönergesi ekleyin.

    using Azure.Identity;
    
  9. türünde credentialadlı DefaultAzureCredential yeni bir değişken oluşturun.

    DefaultAzureCredential credential = new();
    
  10. NoSQL hesap uç noktası için Azure Cosmos DB ile endpoint adlı bir dize değişkeni oluşturun.

    string endpoint = "<nosql-account-endpoint>";
    
  11. sınıfın CosmosClientendpoint yeni bir örneğini oluşturun ve credentialbunu using deyimine sarmalayın.

    using CosmosClient client = new (endpoint, credential);
    
  12. cosmicworks/locations ve ardından CosmosClient.GetDatabase kullanarak, NoSQL için Azure Cosmos DB hesabında önceden oluşturulmuş kapsayıcıya (Database.GetContainer) bir başvuru alın. Sonucu adlı containerbir değişkende depolayın.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  13. Program.cs dosyasını kaydedin.

Jeo-uzamsal veri ekleme

.NET SDK'sı, yaygın GeoJSON nesnelerini temsil etmek için Microsoft.Azure.Cosmos.Spatial 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.

  1. 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 bir Officekayıt türü oluşturun:

    Türü Description Varsayılan değer
    ID string Benzersiz tanımlayıcı
    name string Ofis adı
    lokasyon Point GeoJSON coğrafi noktası
    kategori 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"
    );
    

    Note

    Bu kayıt, GeoJSON'da belirli bir konumu temsil eden bir özellik içerir Point . Daha fazla bilgi için bkz . GeoJSON Noktası.

  2. Region.cs adlı başka bir yeni dosya oluşturun. Şu özelliklere sahip adlı Region başka bir kayıt türü ekleyin:

    Türü Description Varsayılan değer
    ID string Benzersiz tanımlayıcı
    name string Ofis adı
    lokasyon Polygon GeoJSON coğrafi şekli
    kategori 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"
    );
    

    Note

    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.

  3. Result.cs adlı başka bir yeni dosya oluşturun. Şu iki özelliğe sahip adlı Result bir kayıt türü ekleyin:

    Türü Description
    name string Eşleşen sonucun adı
    distanceKilometers decimal Kilometre cinsinden mesafe
    public record Result(
        string name,
        decimal distanceKilometers
    );
    
  4. Office.cs, Region.cs ve Result.cs dosyalarını kaydedin.

  5. Program.cs dosyasını yeniden açın.

  6. Yeni bir Polygon oluşturup mainCampusPolygon adlı değişkene atayın.

    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),
            })
        }
    );
    
  7. Region adını taşıyan yeni bir mainCampusRegion değişken oluşturun, çokgeni, benzersiz tanımlayıcıyı 1000 ve ismi Main Campus kullanarak.

    Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
    
  8. 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}");
    

    Tip

    Bu kılavuz, benzersiz tanımlayıcılar arasında çakışmaya neden olmadan betiği birden çok kez çalıştırabilmeniz için upsert yerine ekleme kullanır. Upsert işlemleri hakkında daha fazla bilgi için bkz . Öğe oluşturma.

  9. adlı Pointyeni headquartersPoint bir değişken oluşturun. Bu değişkeni, nokta, benzersiz tanımlayıcı Office ve ad headquartersOffice kullanarak 0001 adlı yeni bir Headquarters değişken oluşturmak için kullanın.

    Point headquartersPoint = new (-122.12827, 47.63980);
    Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
    
  10. adlı Pointbaşka bir researchPoint değişken oluşturun. Bu Office değişkeni, ilgili noktayı, benzersiz tanımlayıcı researchOffice ve adı 0002 kullanarak Research and Development adlı başka bir değişken oluşturmak için kullanın.

    Point researchPoint = new (-96.84369, 46.81298);
    Office researchOffice = new ("0002", "Research and Development", researchPoint);
    
  11. TransactionalBatch Her iki Office değişkeni de tek bir işlem olarak eklemek için bir oluşturun. Ardından, her iki ofisin bilgisini de konsola yazdırı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}");
    

    Note

    İşlemler hakkında daha fazla bilgi için bkz işlemsel toplu işlemler.

  12. Program.cs dosyasını kaydedin.

  13. kullanarak dotnet runuygulamayı 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

Microsoft.Azure.Cosmos.Spatial ad alanı içindeki türler, ST_DISTANCE gibi yerleşik işlevleri kullanmak için NoSQL parametreli sorguya giriş olarak kullanılabilir.

  1. Program.cs dosyasını açın.

  2. Noktalar arasındaki mesafeyi ölçmek için bu bölümde kullanılan sorgu ile bir string değişkeni adı nosql olarak yeni 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
    ";
    

    Tip

    Bu sorgu, alt sorgu içine yerleştirilerek, zaten hesaplanmış değerin SELECT ve WHERE klasürlerinde birden çok kez yeniden kullanılmasını basitleştirir.

  3. QueryDefinition değişkenini parametre olarak kullanarak, query adını taşıyan yeni bir nosqlString değişkeni oluşturun. Ardından bu parametreleri sorguya eklemek için fluent yöntemini birden çok kez kullanın QueryDefinition.WithParameter :

    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));
    
  4. kullanarak, genel türü ve değişkenini Container.GetItemQueryIterator<> kullanarak Resultquery 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}");
        }
    }
    

    Note

    Sorgu sonuçlarını numaralandırma hakkında daha fazla bilgi için bkz . sorgu öğeleri.

  5. Program.cs dosyasını kaydedin.

  6. kullanarak dotnet runuygulamayı 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şlevselliği, 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 fonksiyon
Distance() ST_DISTANCE
Intersects() ST_INTERSECTS
IsValid() ST_ISVALID
IsValidDetailed() ST_ISVALIDDETAILED
Within() ST_WITHIN
  1. Program.cs dosyasını açın.

  2. Benzersiz tanımlayıcısı Region1000 olan kapsayıcıdan öğeyi alın ve adlı regionbir değişkende depolayın.

    Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
    
  3. 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:

    1. Yalnızca eşdeğeri Queryable.Where<> olan category öğelere filtre uygulamak için "business-office"uzantı yöntemini kullanın.

    2. Yalnızca değişkenin Queryable.Where<> özelliğindeki region konumlarına filtre uygulamak için location kullanarak Geometry.Within() yeniden kullanın.

    3. 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>();
    

    Important

    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.

  4. 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}");
        }
    }
    
  5. Program.cs dosyasını kaydedin.

  6. kullanarak dotnet runuygulamayı 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ı temizle

Bu kılavuzu tamamladıktan sonra veritabanınızı kaldırın.

  1. 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>"
    
  2. 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"
    

Sonraki Adımlar