Mengindeks dan mengkueri data lokasi GeoJSON di Azure Cosmos DB untuk NoSQL

BERLAKU UNTUK: NoSQL

Data geospasial di Azure Cosmos DB for NoSQL memungkinkan Anda menyimpan informasi lokasi dan melakukan kueri umum, termasuk tetapi tidak terbatas pada:

  • Menemukan apakah lokasi berada dalam area yang ditentukan
  • Mengukur jarak antara dua lokasi
  • Menentukan apakah jalur bersinggungan dengan lokasi atau area

Panduan ini menjelaskan proses pembuatan data geospasial, mengindeks data, lalu mengkueri data dalam kontainer.

Prasyarat

Membuat kebijakan kontainer dan pengindeksan

Semua kontainer menyertakan kebijakan pengindeksan default yang akan berhasil mengindeks data geospasial. Untuk membuat kebijakan pengindeksan yang disesuaikan, buat akun dan tentukan file JSON dengan konfigurasi kebijakan. Di bagian ini, indeks spasial kustom digunakan untuk kontainer yang baru dibuat.

  1. Buka terminal.

  2. Buat variabel shell untuk nama Azure Cosmos DB Anda untuk akun NoSQL dan grup sumber daya.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  3. Buat database baru bernama cosmicworks menggunakan az cosmosdb sql database create.

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --account-name $accountName \
        --name "cosmicworks" \
        --throughput 400
    
  4. Buat file JSON baru bernama index-policy.json dan tambahkan objek JSON berikut ke file.

    {
      "indexingMode": "consistent",
      "automatic": true,
      "includedPaths": [
        {
          "path": "/*"
        }
      ],
      "excludedPaths": [
        {
          "path": "/\"_etag\"/?"
        }
      ],
      "spatialIndexes": [
        {
          "path": "/location/*",
          "types": [
            "Point",
            "Polygon"
          ]
        }
      ]
    }
    
  5. Gunakan az cosmosdb sql container create untuk membuat kontainer baru bernama locations dengan jalur kunci partisi ./region

    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. Ambil string koneksi utama untuk akun menggunakan az cosmosdb keys list.

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

    Tip

    Untuk melihat semua kemungkinan string koneksi untuk akun, gunakan az cosmosdb keys list --resource-group $resourceGroupName --name $accountName --type "connection-strings".

  7. Rekam string koneksi. Anda menggunakan kredensial ini nanti dalam panduan ini.

Membuat aplikasi konsol .NET SDK

.NET SDK untuk Azure Cosmos DB for NoSQL menyediakan kelas untuk objek GeoJSON umum. Gunakan SDK ini untuk menyederhanakan proses penambahan objek geografis ke kontainer Anda.

  1. Buka terminal di direktori kosong.

  2. Buat aplikasi .NET baru dengan menggunakan perintah dotnet new dengan templat konsol.

    dotnet new console
    
  3. Impor paket NuGet Microsoft.Azure.Cosmos menggunakan perintah dotnet add package.

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

    Peringatan

    Entity Framework saat ini tidak melakukan data spasial di Azure Cosmos DB untuk NoSQL. Gunakan salah satu Azure Cosmos DB untuk SDK NoSQL untuk dukungan GeoJSON yang sangat diketik.

  4. Buat proyek dengan perintah dotnet build.

    dotnet build
    
  5. Buka lingkungan pengembang terintegrasi (IDE) pilihan Anda di direktori yang sama dengan aplikasi konsol .NET Anda.

  6. Buka file Program.cs yang baru dibuat dan hapus kode yang ada. Tambahkan menggunakan direktif untuk Microsoft.Azure.Cosmosnamespace , Microsoft.Azure.Cosmos.Linq, danMicrosoft.Azure.Cosmos.Spatial .

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  7. Tambahkan variabel string bernama *connectionString dengan string koneksi yang Anda rekam sebelumnya dalam panduan ini.

    string connectionString = "<your-account-connection-string>"
    
  8. Buat instans baru kelas yang CosmosClient melewati connectionString dan membungkusnya dalam pernyataan penggunaan.

    using CosmosClient client = new (connectionString);
    
  9. Ambil referensi ke kontainer yang dibuat sebelumnya (cosmicworks/locations) di akun Azure Cosmos DB for NoSQL dengan menggunakan CosmosClient.GetDatabase lalu Database.GetContainer. Simpan hasilnya di variabel bernama container.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  10. Simpan file Program.cs.

Menambahkan data geospasial

.NET SDK menyertakan beberapa jenis di Microsoft.Azure.Cosmos.Spatial namespace layanan untuk mewakili objek GeoJSON umum. Jenis-jenis ini menyederhanakan proses penambahan informasi lokasi baru ke item dalam kontainer.

  1. Buat file baru bernama Office.cs. Dalam file , tambahkan menggunakan direktif ke Microsoft.Azure.Cosmos.Spatial lalu buat Officejenis catatan dengan properti ini:

    Jenis Deskripsi Nilai default
    id string Pengenal unik
    nama string Nama kantor
    lokasi Point Titik geografis GeoJSON
    kategori string Nilai kunci partisi business-office
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Office(
        string id,
        string name,
        Point location,
        string category = "business-office"
    );
    

    Catatan

    Catatan ini mencakup properti yang Point mewakili posisi tertentu di GeoJSON. Untuk informasi selengkapnya, lihat GeoJSON Point.

  2. Buat file baru lain bernama Region.cs. Tambahkan tipe catatan lain bernama Region dengan properti ini:

    Jenis Deskripsi Nilai default
    id string Pengenal unik
    nama string Nama kantor
    lokasi Polygon Bentuk geografis GeoJSON
    kategori string Nilai kunci partisi business-region
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Region(
        string id,
        string name,
        Polygon location,
        string category = "business-region"
    );
    

    Catatan

    Rekaman ini mencakup properti yang Polygon mewakili bentuk yang terdiri dari garis yang digambar di antara beberapa lokasi di GeoJSON. Untuk informasi selengkapnya, lihat Poligon GeoJSON.

  3. Buat file baru lain bernama Result.cs. Tambahkan jenis catatan bernama Result dengan dua properti ini:

    Jenis Deskripsi
    nama string Nama hasil yang cocok
    distanceKilometers decimal Jarak dalam kilometer
    public record Result(
        string name,
        decimal distanceKilometers
    );
    
  4. Simpan file Office.cs, Region.cs, dan Result.cs .

  5. Membuka file Program.cs lagi.

  6. Buat baru Polygon dalam variabel bernama 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),
            })
        }
    );
    
  7. Buat variabel baru Region bernama mainCampusRegion menggunakan poligon, pengidentifikasi 1000unik , dan nama Main Campus.

    Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
    
  8. Gunakan Container.UpsertItemAsync untuk menambahkan wilayah ke kontainer. Tulis informasi wilayah ke konsol.

    await container.UpsertItemAsync<Region>(mainCampusRegion);
    Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");
    

    Tip

    Panduan ini menggunakan upsert alih-alihmenyisipkan sehingga Anda dapat menjalankan skrip beberapa kali tanpa menyebabkan konflik antara pengidentifikasi unik. Untuk informasi selengkapnya tentang operasi upsert, lihat membuat item.

  9. Buat variabel baru Point bernama headquartersPoint. Gunakan variabel tersebut untuk membuat variabel baru Office bernama headquartersOffice menggunakan titik , pengidentifikasi 0001unik , dan nama Headquarters.

    Point headquartersPoint = new (-122.12827, 47.63980);
    Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
    
  10. Buat variabel lain Point bernama researchPoint. Gunakan variabel tersebut untuk membuat variabel lain Office bernama researchOffice menggunakan titik yang sesuai, pengidentifikasi 0002unik , dan nama Research and Development.

    Point researchPoint = new (-96.84369, 46.81298);
    Office researchOffice = new ("0002", "Research and Development", researchPoint);
    
  11. Buat TransactionalBatch untuk meningkatkan kedua Office variabel sebagai satu transaksi. Kemudian, tulis kedua informasi kantor ke konsol.

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

    Catatan

    Untuk informasi selengkapnya tentang transaksi, lihat operasi batch transaksional.

  12. Simpan file Program.cs.

  13. Jalankan aplikasi di terminal menggunakan dotnet run. Amati bahwa output eksekusi aplikasi mencakup informasi tentang tiga item yang baru dibuat.

    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 }
    

Mengkueri data geospasial menggunakan kueri NoSQL

Jenis di Microsoft.Azure.Cosmos.Spatial namespace dapat digunakan sebagai input ke kueri parameter NoSQL untuk menggunakan fungsi bawaan seperti ST_DISTANCE.

  1. Buka file Program.cs.

  2. Buat variabel baru string bernama nosql dengan kueri digunakan di bagian ini untuk mengukur jarak antar titik.

    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

    Kueri ini menempatkan fungsi geospasial dalam subkueri untuk menyederhanakan proses penggunaan kembali nilai yang sudah dihitung beberapa kali dalam SELECT klausa dan WHERE .

  3. Buat variabel baru QueryDefinition bernama query menggunakan nosqlString variabel sebagai parameter. Kemudian gunakan QueryDefinition.WithParameter metode fasih beberapa kali untuk menambahkan parameter ini ke kueri:

    Nilai
    @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. Buat iterator baru menggunakan Container.GetItemQueryIterator<>, Result jenis generik, dan query variabel . Kemudian, gunakan kombinasi perulangan sementara dan foreach untuk melakukan iterasi atas semua hasil di setiap halaman hasil. Keluarkan setiap hasil ke konsol.

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

    Catatan

    Untuk informasi selengkapnya tentang menghitung hasil kueri, lihat item kueri.

  5. Simpan file Program.cs.

  6. Jalankan aplikasi lagi di terminal menggunakan dotnet run. Amati bahwa output sekarang menyertakan hasil kueri.

    dotnet run
    
    [DISTANCE KM]   Result { name = Headquarters, distanceKilometers = 3.34 }
    [DISTANCE KM]   Result { name = Research and Development, distanceKilometers = 1907.43 }
    

Mengkueri data geospasial menggunakan LINQ

Fungsionalitas LINQ ke NoSQL di .NET SDK mendukung termasuk jenis geospasial dalam ekspresi kueri. Bahkan lebih lanjut, SDK mencakup metode ekstensi yang memetakan ke fungsi bawaan yang setara:

Metode ekstensi Fungsi bawaan
Distance() ST_DISTANCE
Intersects() ST_INTERSECTS
IsValid() ST_ISVALID
IsValidDetailed() ST_ISVALIDDETAILED
Within() ST_WITHIN
  1. Buka file Program.cs.

  2. Region Ambil item dari kontainer dengan pengidentifikasi 1000 unik dan simpan dalam variabel bernama region.

    Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
    
  3. Container.GetItemLinqQueryable<> Gunakan metode untuk mendapatkan LINQ yang dapat dikueri, dan buat kueri LINQ dengan lancar dengan melakukan ketiga tindakan ini:

    1. Queryable.Where<> Gunakan metode ekstensi untuk memfilter hanya item dengan yang category setara "business-office"dengan .

    2. Gunakan Queryable.Where<> lagi untuk memfilter hanya ke lokasi dalam region properti variabel location menggunakan Geometry.Within().

    3. Terjemahkan ekspresi LINQ ke iterator umpan menggunakan CosmosLinqExtensions.ToFeedIterator<>.

    var regionIterator = container.GetItemLinqQueryable<Office>()
        .Where(o => o.category == "business-office")
        .Where(o => o.location.Within(region.location))
        .ToFeedIterator<Office>();
    

    Penting

    Dalam contoh ini, properti lokasi kantor memiliki titik, dan properti lokasi wilayah memiliki poligon. ST_WITHIN menentukan apakah titik kantor berada dalam poligon wilayah tersebut.

  4. Gunakan kombinasi perulangan sementara danforeach untuk mengulangi semua hasil di setiap halaman hasil. Keluarkan setiap hasil ke konsol.

    while (regionIterator.HasMoreResults)
    {
        var response = await regionIterator.ReadNextAsync();
        foreach (var office in response)
        {
            Console.WriteLine($"[IN REGION]\t{office}");
        }
    }
    
  5. Simpan file Program.cs.

  6. Jalankan aplikasi untuk terakhir kalinya di terminal menggunakan dotnet run. Amati bahwa output sekarang menyertakan hasil kueri berbasis LINQ kedua.

    dotnet run
    
    [IN REGION]     Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
    

Membersihkan sumber daya

Hapus database Anda setelah Anda menyelesaikan panduan ini.

  1. Buka terminal dan buat variabel shell untuk nama akun dan grup sumber daya Anda.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  2. Gunakan az cosmosdb sql database delete untuk menghapus database.

    az cosmosdb sql database delete \
        --resource-group $resourceGroupName \
        --account-name $accountName \
        --name "cosmicworks"
    

Langkah berikutnya