Aracılığıyla paylaş


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

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.

  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 az cosmosdb sql database createadlı cosmicworks yeni bir veritabanı oluşturun.

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --account-name $accountName \
        --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. bölüm anahtarı yolu /regionile adlı locations yeni bir kapsayıcı oluşturmak için kullanınaz cosmosdb sql container create.

    az cosmosdb sql container create \
        --resource-group $resourceGroupName \
        --account-name $accountName \
        --database-name "cosmicworks" \
        --name "locations" \
        --partition-key-path "/category" \
        --idx @index-policy.json
    
  6. kullanarak az cosmosdb keys listhesabın birincil bağlantı dizesi alın.

    az cosmosdb keys list \
        --resource-group $resourceGroupName \
        --name $accountName \
        --type "connection-strings" \
        --query "connectionStrings[?keyKind == \`Primary\`].connectionString" \
        --output tsv
    

    İpucu

    Bir hesabın tüm olası bağlantı dizesi görmek için kullanınaz cosmosdb keys list --resource-group $resourceGroupName --name $accountName --type "connection-strings".

  7. bağlantı dizesi kaydedin. Bu kimlik bilgilerini bu kılavuzun ilerleyen bölümlerinde kullanacaksınız.

.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. konsol şablonuyla komutunu kullanarak dotnet new yeni bir .NET uygulaması oluşturun.

    dotnet new console
    
  3. komutunu kullanarak Microsoft.Azure.Cosmos 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.

  4. komutuyla dotnet build projeyi oluşturun.

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

  6. Yeni oluşturulan Program.cs dosyasını açın ve mevcut kodları silin. , Microsoft.Azure.Cosmos.LinqveMicrosoft.Azure.Cosmos.Spatial ad alanları için Microsoft.Azure.Cosmosusing yönergeleri ekleyin.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  7. Bu kılavuzun önceki bölümlerinde kaydettiğiniz bağlantı dizesi *connectionString adlı bir dize değişkeni ekleyin.

    string connectionString = "<your-account-connection-string>"
    
  8. 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);
    
  9. ve ardından Database.GetContainerkullanarak CosmosClient.GetDatabase NoSQL için Azure Cosmos DB hesabında önceden oluşturulmuş kapsayıcıya (cosmicworks/locations) bir başvuru alın. Sonucu adlı containerbir değişkende depolayın.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  10. 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.

  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 Office 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ı.

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

  3. 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
    );
    
  4. Office.cs, Region.cs ve Result.cs dosyalarını kaydedin.

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

  6. adlı mainCampusPolygondeğişkende yeni Polygon 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),
            })
        }
    );
    
  7. çokgenini, benzersiz tanımlayıcısını 1000ve adını Main Campuskullanarak adlı mainCampusRegion yeni Region bir değişken oluşturun.

    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}");
    

    İ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.

  9. adlı headquartersPointyeni Point bir değişken oluşturun. noktasını, benzersiz tanımlayıcısını 0001ve adını Headquarterskullanarak adlı headquartersOffice yeni Office 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);
    
  10. adlı researchPointbaşka bir Point değişken oluşturun. İlgili noktayı, benzersiz tanımlayıcıyı 0002ve adını Research and Developmentkullanarak adlı researchOffice başka bir Office 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);
    
  11. TransactionalBatch Her iki Office 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.

  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

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

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

  2. Bu bölümde noktalar arasındaki mesafeyi ölçmek için sorgu ile adlı nosql yeni string 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.

  3. değişkenini parametre olarak kullanarak nosqlString adlı query yeni QueryDefinition bir değişken oluşturun. Ardından bu parametreleri sorguya eklemek için fluent yöntemini birden çok kez kullanın QueryDefinition.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));
    
  4. kullanarak, genel türü ve değişkenini query kullanarak Container.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.

  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ş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
  1. Program.cs dosyasını açın.

  2. Benzersiz tanımlayıcısı Region 1000 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. kullanarak Geometry.Within()yalnızca değişkenin location özelliğindeki region konumlara filtre uygulamak için yeniden kullanınQueryable.Where<>.

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

    Ö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.

  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ı temizleme

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 $resourceGroupName \
        --account-name $accountName \
        --name "cosmicworks"
    

Sonraki adımlar