Sdílet prostřednictvím


Indexování a dotazování dat o poloze GeoJSON ve službě Azure Cosmos DB for NoSQL

PLATÍ PRO: NoSQL

Geoprostorová data ve službě Azure Cosmos DB for NoSQL umožňují ukládat informace o poloze a provádět běžné dotazy, včetně mimo jiné:

  • Zjištění, jestli je umístění v definované oblasti
  • Měření vzdálenosti mezi dvěma umístěními
  • Určení, jestli se cesta protíná s umístěním nebo oblastí

Tato příručka vás provede procesem vytváření geoprostorových dat, indexování dat a následného dotazování dat v kontejneru.

Požadavky

Vytvoření zásad kontejneru a indexování

Všechny kontejnery obsahují výchozí zásady indexování, které úspěšně indexují geoprostorová data. Pokud chcete vytvořit vlastní zásady indexování, vytvořte účet a zadejte soubor JSON s konfigurací zásad. V této části se pro nově vytvořený kontejner používá vlastní prostorový index.

  1. Otevřete terminál.

  2. Vytvořte proměnnou prostředí pro název účtu a skupiny prostředků Azure Cosmos DB for NoSQL.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  3. Vytvořte novou databázi s názvem cosmicworks using 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. Vytvořte nový soubor JSON s názvem index-policy.json a do souboru přidejte následující objekt JSON.

    {
      "indexingMode": "consistent",
      "automatic": true,
      "includedPaths": [
        {
          "path": "/*"
        }
      ],
      "excludedPaths": [
        {
          "path": "/\"_etag\"/?"
        }
      ],
      "spatialIndexes": [
        {
          "path": "/location/*",
          "types": [
            "Point",
            "Polygon"
          ]
        }
      ]
    }
    
  5. Slouží az cosmosdb sql container create k vytvoření nového kontejneru s názvem locations cesta klíče oddílu ./region

    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. Nakonec získejte koncový bod účtu pro váš účet pomocí az cosmosdb show dotazu JMESPath.

    az cosmosdb show \
        --resource-group "<resource-group-name>" \
        --name "<nosql-account-name>" \
        --query "documentEndpoint"
    
  7. Nahrajte koncový bod účtu, protože ho budete potřebovat v další části.

Vytvoření konzolové aplikace .NET SDK

Sada .NET SDK pro Azure Cosmos DB for NoSQL poskytuje třídy pro běžné objekty GeoJSON. Pomocí této sady SDK můžete zjednodušit proces přidávání geografických objektů do kontejneru.

  1. Otevřete terminál v prázdném adresáři.

  2. Pomocí příkazu se šablonou konzoly vytvořte novou aplikaci dotnet new .NET.

    dotnet new console
    
  3. Importujte Microsoft.Azure.Cosmos balíček NuGet pomocí dotnet add package příkazu.

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

    Upozorňující

    Entity Framework v současné době prostorová data ve službě Azure Cosmos DB for NoSQL neobsahuje. Pro podporu GeoJSON silného typu použijte jednu ze sad SDK služby Azure Cosmos DB for NoSQL.

  4. Importujte Azure.Identity balíček NuGet.

    dotnet add package Azure.Identity --version 1.*
    
  5. Sestavte projekt pomocí dotnet build příkazu.

    dotnet build
    
  6. Otevřete integrované vývojové prostředí (IDE) podle vašeho výběru ve stejném adresáři jako konzolová aplikace .NET.

  7. Otevřete nově vytvořený soubor Program.cs a odstraňte veškerý existující kód. Přidejte direktivy using pro Microsoft.Azure.Cosmosobory názvů , Microsoft.Azure.Cosmos.LinqaMicrosoft.Azure.Cosmos.Spatial obory názvů.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  8. Přidejte další direktivu Azure.Identity using pro obor názvů.

    using Azure.Identity;
    
  9. Vytvořte novou proměnnou s názvem credential typu DefaultAzureCredential.

    DefaultAzureCredential credential = new();
    
  10. Vytvořte řetězcovou proměnnou s názvem endpoint s koncovým bodem účtu Azure Cosmos DB for NoSQL.

    string endpoint = "<nosql-account-endpoint>";
    
  11. Vytvořte novou instanci CosmosClient třídy, která connectionString předá a zabalí ji do příkazu using.

    using CosmosClient client = new (connectionString);
    
  12. Načtěte odkaz na dříve vytvořený kontejner (cosmicworks/locations) v účtu Azure Cosmos DB for NoSQL pomocí CosmosClient.GetDatabase a pak Database.GetContainer. Uložte výsledek do proměnné s názvem container.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  13. Uložte soubor Program.cs.

Přidání geoprostorových dat

Sada .NET SDK obsahuje více typů v Microsoft.Azure.Cosmos.Spatial oboru názvů, které představují běžné objekty GeoJSON. Tyto typy zjednodušují proces přidávání nových informací o umístění do položek v kontejneru.

  1. Vytvořte nový soubor s názvem Office.cs. Do souboru přidejte direktivu Microsoft.Azure.Cosmos.Spatial using a pak vytvořte typ záznamu Office s těmito vlastnostmi:

    Typ Popis Default value
    id string Jedinečný identifikátor
    Jméno string Název kanceláře
    location Point Geografický bod GeoJSON
    kategorie string Hodnota klíče oddílu business-office
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Office(
        string id,
        string name,
        Point location,
        string category = "business-office"
    );
    

    Poznámka:

    Tento záznam obsahuje Point vlastnost představující konkrétní pozici v GeoJSON. Další informace naleznete v tématu GeoJSON Point.

  2. Vytvořte další nový soubor s názvem Region.cs. Přidejte další typ záznamu s názvem Region s těmito vlastnostmi:

    Typ Popis Default value
    id string Jedinečný identifikátor
    Jméno string Název kanceláře
    location Polygon Geografický tvar GeoJSON
    kategorie string Hodnota klíče oddílu business-region
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Region(
        string id,
        string name,
        Polygon location,
        string category = "business-region"
    );
    

    Poznámka:

    Tento záznam obsahuje Polygon vlastnost představující obrazec složený z čar nakreslených mezi několika umístěními v GeoJSON. Další informace naleznete v tématu GeoJSON Polygon.

  3. Vytvořte další nový soubor s názvem Result.cs. Přidejte typ záznamu s Result těmito dvěma vlastnostmi:

    Typ Popis
    Jméno string Název odpovídajícího výsledku
    vzdálenostKilometry decimal Vzdálenost v kilometrech
    public record Result(
        string name,
        decimal distanceKilometers
    );
    
  4. Uložte soubory Office.cs, Region.cs a Result.cs.

  5. Znovu otevřete soubor Program.cs.

  6. Vytvořte novou Polygon proměnnou s názvem 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. Vytvořte novou Region proměnnou s názvem mainCampusRegion pomocí mnohoúhelníku, jedinečného identifikátoru 1000a názvu Main Campus.

    Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
    
  8. Slouží Container.UpsertItemAsync k přidání oblasti do kontejneru. Napište informace o oblasti do konzoly.

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

    Tip

    Tato příručka místo vložení používá upsert, takže skript můžete spustit vícekrát, aniž by došlo ke konfliktu mezi jedinečnými identifikátory. Další informace o operacích upsertu najdete v tématu vytváření položek.

  9. Vytvořte novou Point proměnnou s názvem headquartersPoint. Pomocí této proměnné vytvořte novou Office proměnnou s názvem headquartersOffice pomocí bodu, jedinečného identifikátoru 0001a názvu Headquarters.

    Point headquartersPoint = new (-122.12827, 47.63980);
    Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
    
  10. Vytvořte další Point proměnnou s názvem researchPoint. Pomocí této proměnné vytvořte jinou Office proměnnou s názvem researchOffice pomocí odpovídajícího bodu, jedinečného identifikátoru 0002a názvu Research and Development.

    Point researchPoint = new (-96.84369, 46.81298);
    Office researchOffice = new ("0002", "Research and Development", researchPoint);
    
  11. Vytvořte pro TransactionalBatch upsert obou Office proměnných jako jednu transakci. Pak na konzolu napište informace o obou kancelářích.

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

    Poznámka:

    Další informace o transakcích naleznete v tématu transakční dávkové operace.

  12. Uložte soubor Program.cs.

  13. Spusťte aplikaci v terminálu pomocí dotnet runpříkazu . Všimněte si, že výstup spuštění aplikace obsahuje informace o třech nově vytvořených položkách.

    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 }
    

Dotazování geoprostorových dat pomocí dotazu NoSQL

Typy v Microsoft.Azure.Cosmos.Spatial oboru názvů lze použít jako vstupy do parametrizovaného dotazu NoSQL pro použití předdefinovaných funkcí, jako je ST_DISTANCE.

  1. Otevřete soubor Program.cs.

  2. Vytvořte novou string proměnnou s názvem nosql dotazu v této části k měření vzdálenosti mezi body.

    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

    Tento dotaz umístí geoprostorovou funkci do poddotazů , aby se zjednodušilo opakované použití již počítané hodnoty vícekrát v SELECT klauzulích a WHERE klauzulích.

  3. Vytvořte novou QueryDefinition proměnnou s názvem query pomocí nosqlString proměnné jako parametru. Pak k přidání těchto parametrů do dotazu použijte QueryDefinition.WithParameter vícekrát fluent metodu:

    Hodnota
    @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. Vytvořte nový iterátor pomocí Container.GetItemQueryIterator<>Result obecného typu a query proměnné. Potom použijte kombinaci smyčky while a foreach k iteraci všech výsledků na každé stránce výsledků. Vypíše každý výsledek do konzoly.

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

    Poznámka:

    Další informace o vytvoření výčtu výsledků dotazu najdete v tématu položky dotazu.

  5. Uložte soubor Program.cs.

  6. Spusťte aplikaci znovu v terminálu pomocí dotnet runpříkazu . Všimněte si, že výstup teď obsahuje výsledky dotazu.

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

Dotazování geoprostorových dat pomocí LINQ

Funkce LINQ to NoSQL v sadě .NET SDK podporuje zahrnutí geoprostorových typů do výrazů dotazu. Sada SDK navíc obsahuje rozšiřující metody, které se mapuje na ekvivalentní předdefinované funkce:

Metoda rozšíření Integrovaná funkce
Distance() ST_DISTANCE
Intersects() ST_INTERSECTS
IsValid() ST_ISVALID
IsValidDetailed() ST_ISVALIDDETAILED
Within() ST_WITHIN
  1. Otevřete soubor Program.cs.

  2. Region Načtěte položku z kontejneru s jedinečným identifikátorem 1000 a uložte ji do proměnné s názvem region.

    Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
    
  3. Použijte metodu Container.GetItemLinqQueryable<> k získání dotazovatelného LINQ a sestavení dotazu LINQ fluently provedením těchto tří akcí:

    1. Použijte metodu Queryable.Where<> rozšíření k filtrování pouze položek s ekvivalentem category "business-office".

    2. Znovu použijte Queryable.Where<> k filtrování pouze umístění v rámci region vlastnosti proměnné location pomocí Geometry.Within().

    3. Přeložte výraz LINQ na iterátor informačního kanálu pomocí CosmosLinqExtensions.ToFeedIterator<>.

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

    Důležité

    V tomto příkladu má vlastnost umístění kanceláře bod a vlastnost umístění oblasti má mnohoúhelník. ST_WITHIN určuje, zda je bod kanceláře v polygonu oblasti.

  4. Pomocí kombinace smyčky while a foreach iterujte všechny výsledky na každé stránce výsledků. Vypíše každý výsledek do konzoly.

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

  6. Spusťte aplikaci jednou naposledy v terminálu pomocí dotnet runpříkazu . Všimněte si, že výstup teď obsahuje výsledky druhého dotazu založeného na LINQ.

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

Vyčištění prostředků

Po dokončení této příručky odeberte databázi.

  1. Otevřete terminál a vytvořte proměnnou prostředí pro název vašeho účtu a skupiny prostředků.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  2. Slouží az cosmosdb sql database delete k odebrání databáze.

    az cosmosdb sql database delete \
        --resource-group "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --name "cosmicworks"
    

Další kroky