Mengindeks dan mengkueri data lokasi GeoJSON di Azure Cosmos DB 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 suatu jalur berpotongan dengan suatu lokasi atau area

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

Prerequisites

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 "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --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 ./category

    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. Terakhir, dapatkan titik akhir akun untuk akun Anda menggunakan az cosmosdb show dan kueri JMESPath.

    az cosmosdb show \
        --resource-group "<resource-group-name>" \
        --name "<nosql-account-name>" \
        --query "documentEndpoint"
    
  7. Rekam titik akhir akun karena Anda akan membutuhkannya di bagian berikutnya.

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

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

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

    Warning

    Kerangka Kerja Entitas saat ini tidak mendukung data spasial di Azure Cosmos DB untuk NoSQL. Gunakan salah satu SDK Azure Cosmos DB untuk NoSQL guna dukungan GeoJSON dengan pengetikan ketat.

  4. Impor paket NuGet Azure.Identity.

    dotnet add package Azure.Identity --version 1.*
    
  5. Buat proyek dengan perintah dotnet build.

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

  7. Buka file Program.cs yang baru dibuat dan hapus kode yang ada. Tambahkan direktif penggunaan untuk namespace Microsoft.Azure.Cosmos, Microsoft.Azure.Cosmos.Linq, dan Microsoft.Azure.Cosmos.Spatial.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  8. Tambahkan satu lagi direktif menggunakan untuk namespace Azure.Identity.

    using Azure.Identity;
    
  9. Buat variabel baru bernama credential jenis DefaultAzureCredential.

    DefaultAzureCredential credential = new();
    
  10. Buat variabel string bernama endpoint dengan Azure Cosmos DB Anda untuk titik akhir akun NoSQL.

    string endpoint = "<nosql-account-endpoint>";
    
  11. Buat instans baru dari kelas CosmosClient dengan melewatkan endpoint dan credential serta membungkusnya dalam pernyataan menggunakan.

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

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

Menambahkan data geospasial

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

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

    Tipe Description Nilai standar
    Id string Pengidentifikasi 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"
    );
    

    Nota

    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:

    Tipe Description Nilai standar
    Id string Pengidentifikasi 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"
    );
    

    Nota

    Rekaman ini mencakup properti yang Polygon mewakili bentuk yang dibentuk oleh garis-garis yang dibuat di antara beberapa lokasi dalam format GeoJSON. Untuk informasi selengkapnya, lihat Poligon GeoJSON.

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

    Tipe Description
    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-alih menyisipkan 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 informasi kedua kantor di 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}");
    

    Nota

    Untuk informasi selengkapnya tentang transaksi, lihat pengoperasian 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 berparameter 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:

    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. Buat iterator baru menggunakan Container.GetItemQueryIterator<>, Result jenis generik, dan query variabel . Kemudian, gunakan kombinasi perulangan while 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}");
        }
    }
    

    Nota

    Untuk informasi selengkapnya tentang melakukan enumerasi 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 untuk NoSQL di SDK .NET mendukung pengikutsertaan tipe geospasial dalam ekspresi kueri. 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. Gunakan metode ekstensi Queryable.Where<> untuk memfilter hanya item dengan category yang setara dengan "business-office".

    2. Gunakan Queryable.Where<> lagi untuk menyaring ke lokasi yang hanya berada dalam properti region dari 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>();
    

    Important

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

  4. Gunakan kombinasi loop while dan foreach untuk melakukan iterasi atas 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 "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --name "cosmicworks"
    

Langkah berikutnya