Delen via


GeoJSON-locatiegegevens indexeren en opvragen in Azure Cosmos DB for NoSQL

VAN TOEPASSING OP: NoSQL

Met georuimtelijke gegevens in Azure Cosmos DB for NoSQL kunt u locatiegegevens opslaan en algemene query's uitvoeren, waaronder, maar niet beperkt tot:

  • Zoeken of een locatie zich binnen een gedefinieerd gebied bevindt
  • De afstand tussen twee locaties meten
  • Bepalen of een pad doorkruist met een locatie of gebied

In deze handleiding wordt het proces voor het maken van georuimtelijke gegevens beschreven, het indexeren van de gegevens en het uitvoeren van query's op de gegevens in een container.

Vereisten

Container- en indexeringsbeleid maken

Alle containers bevatten een standaardindexeringsbeleid dat georuimtelijke gegevens kan indexeren. Als u een aangepast indexeringsbeleid wilt maken, maakt u een account en geeft u een JSON-bestand op met de configuratie van het beleid. In deze sectie wordt een aangepaste ruimtelijke index gebruikt voor een zojuist gemaakte container.

  1. Open een terminal.

  2. Maak een shellvariabele voor de naam van uw Azure Cosmos DB for NoSQL-account en resourcegroep.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  3. Maak een nieuwe database met de naam cosmicworks .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. Maak een nieuw JSON-bestand met de naam index-policy.json en voeg het volgende JSON-object toe aan het bestand.

    {
      "indexingMode": "consistent",
      "automatic": true,
      "includedPaths": [
        {
          "path": "/*"
        }
      ],
      "excludedPaths": [
        {
          "path": "/\"_etag\"/?"
        }
      ],
      "spatialIndexes": [
        {
          "path": "/location/*",
          "types": [
            "Point",
            "Polygon"
          ]
        }
      ]
    }
    
  5. Hiermee az cosmosdb sql container create maakt u een nieuwe container met de naam locations met een partitiesleutelpad van /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. Haal ten slotte het accounteindpunt voor uw account op met behulp van az cosmosdb show een JMESPath-query.

    az cosmosdb show \
        --resource-group "<resource-group-name>" \
        --name "<nosql-account-name>" \
        --query "documentEndpoint"
    
  7. Noteer het accounteindpunt zoals u dit nodig hebt in de volgende sectie.

.NET SDK-consoletoepassing maken

De .NET SDK voor Azure Cosmos DB for NoSQL biedt klassen voor algemene GeoJSON-objecten. Gebruik deze SDK om het proces van het toevoegen van geografische objecten aan uw container te stroomlijnen.

  1. Open een terminal in een lege map.

  2. Maak een nieuwe .NET-toepassing met behulp van de dotnet new opdracht met de consolesjabloon .

    dotnet new console
    
  3. Importeer het Microsoft.Azure.Cosmos NuGet-pakket met behulp van de dotnet add package opdracht.

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

    Waarschuwing

    Entity Framework bevat momenteel geen ruimtelijke gegevens in Azure Cosmos DB voor NoSQL. Gebruik een van de Azure Cosmos DB for NoSQL SDK's voor sterk getypeerde GeoJSON-ondersteuning.

  4. Importeer het Azure.Identity NuGet-pakket.

    dotnet add package Azure.Identity --version 1.*
    
  5. Bouw het project met de dotnet build opdracht.

    dotnet build
    
  6. Open de IDE (Integrated Developer Environment) van uw keuze in dezelfde map als uw .NET-consoletoepassing.

  7. Open het zojuist gemaakte Program.cs-bestand en verwijder alle bestaande code. Voeg gebruiksrichtlijnen toe voor de Microsoft.Azure.Cosmos, Microsoft.Azure.Cosmos.LinqenMicrosoft.Azure.Cosmos.Spatial naamruimten.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  8. Voeg nog een using-instructie toe voor de Azure.Identity naamruimte.

    using Azure.Identity;
    
  9. Maak een nieuwe variabele met de naam credential van het type DefaultAzureCredential.

    DefaultAzureCredential credential = new();
    
  10. Maak een tekenreeksvariabele met de naam endpoint van uw Azure Cosmos DB for NoSQL-accounteindpunt.

    string endpoint = "<nosql-account-endpoint>";
    
  11. Maak een nieuw exemplaar van de CosmosClient klasse die wordt connectionString doorgegeven en verpakt deze in een using-instructie.

    using CosmosClient client = new (connectionString);
    
  12. Haal een verwijzing op naar de eerder gemaakte container (cosmicworks/locations) in het Azure Cosmos DB for NoSQL-account met behulp van CosmosClient.GetDatabase en vervolgens Database.GetContainer. Sla het resultaat op in een variabele met de naam container.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  13. Sla bestand Program.cs op.

Georuimtelijke gegevens toevoegen

De .NET SDK bevat meerdere typen in de Microsoft.Azure.Cosmos.Spatial naamruimte die algemene GeoJSON-objecten vertegenwoordigen. Met deze typen wordt het proces voor het toevoegen van nieuwe locatiegegevens aan items in een container gestroomlijnd.

  1. Maak een nieuw bestand met de naam Office.cs. Voeg in het bestand een using-instructie toe aan Microsoft.Azure.Cosmos.Spatial en maak vervolgens een Office recordtype met deze eigenschappen:

    Type Description Default value
    id string Unieke id
    name string Naam van het kantoor
    location Point GeoJSON geografisch punt
    category string Partitiesleutelwaarde business-office
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Office(
        string id,
        string name,
        Point location,
        string category = "business-office"
    );
    

    Notitie

    Deze record bevat een Point eigenschap die een specifieke positie in GeoJSON vertegenwoordigt. Zie GeoJSON Point voor meer informatie.

  2. Maak nog een nieuw bestand met de naam Region.cs. Voeg nog een recordtype toe met de naam Region deze eigenschappen:

    Type Description Default value
    id string Unieke id
    name string Naam van het kantoor
    location Polygon Geografische vorm van GeoJSON
    category string Partitiesleutelwaarde business-region
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Region(
        string id,
        string name,
        Polygon location,
        string category = "business-region"
    );
    

    Notitie

    Deze record bevat een Polygon eigenschap die een shape vertegenwoordigt die bestaat uit lijnen die zijn getekend tussen meerdere locaties in GeoJSON. Zie GeoJSON Polygon voor meer informatie.

  3. Maak nog een nieuw bestand met de naam Result.cs. Voeg een recordtype toe met de volgende Result twee eigenschappen:

    Type Description
    name string Naam van het overeenkomende resultaat
    distanceKilometers decimal Afstand in kilometers
    public record Result(
        string name,
        decimal distanceKilometers
    );
    
  4. Sla de bestanden Office.cs, Region.cs en Result.cs op.

  5. Open het bestand Program.cs opnieuw.

  6. Maak een nieuwe Polygon in een variabele met de naam 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. Maak een nieuwe Region variabele met de naam mainCampusRegion met behulp van de veelhoek, de unieke id 1000en de naam Main Campus.

    Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
    
  8. Gebruik Container.UpsertItemAsync dit om de regio toe te voegen aan de container. Schrijf de gegevens van de regio naar de console.

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

    Tip

    In deze handleiding wordt upsert gebruikt in plaats van in te voegen , zodat u het script meerdere keren kunt uitvoeren zonder dat er een conflict tussen unieke id's ontstaat. Zie items maken voor meer informatie over upsert-bewerkingen.

  9. Maak een nieuwe Point variabele met de naam headquartersPoint. Gebruik deze variabele om een nieuwe Office variabele te maken met headquartersOffice behulp van het punt, de unieke id 0001en de naam Headquarters.

    Point headquartersPoint = new (-122.12827, 47.63980);
    Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
    
  10. Maak een andere Point variabele met de naam researchPoint. Gebruik deze variabele om een andere Office variabele te maken met researchOffice behulp van het bijbehorende punt, de unieke id 0002en de naam Research and Development.

    Point researchPoint = new (-96.84369, 46.81298);
    Office researchOffice = new ("0002", "Research and Development", researchPoint);
    
  11. Maak een TransactionalBatch om beide Office variabelen als één transactie te upsert. Schrijf vervolgens de gegevens van beide kantoren naar de console.

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

    Notitie

    Zie transactionele batchbewerkingen voor meer informatie over transacties.

  12. Sla bestand Program.cs op.

  13. Voer de toepassing uit in een terminal met behulp van dotnet run. U ziet dat de uitvoer van de toepassingsuitvoering informatie bevat over de drie nieuw gemaakte items.

    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 }
    

Georuimtelijke gegevens opvragen met noSQL-query

De typen in de Microsoft.Azure.Cosmos.Spatial naamruimte kunnen worden gebruikt als invoer voor een NoSQL-geparameteriseerde query om ingebouwde functies zoals ST_DISTANCE.

  1. Open het Program.cs-bestand .

  2. Maak een nieuwe string variabele met de naam nosql met de query in deze sectie om de afstand tussen punten te meten.

    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

    Met deze query wordt de georuimtelijke functie binnen een subquery opgeslagen om het proces van het hergebruik van de reeds berekende waarde meerdere keren in de SELECT en WHERE componenten te vereenvoudigen.

  3. Maak een nieuwe QueryDefinition variabele met de naam query met behulp van de nosqlString variabele als parameter. Gebruik vervolgens de QueryDefinition.WithParameter fluent-methode meerdere keren om deze parameters toe te voegen aan de query:

    Weergegeven als
    @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. Maak een nieuwe iterator met behulp van Container.GetItemQueryIterator<>het Result algemene type en de query variabele. Gebruik vervolgens een combinatie van een tijdje en foreach-lus om alle resultaten op elke pagina met resultaten te herhalen. Voer elk resultaat uit naar de console.

    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}");
        }
    }
    
  5. Sla bestand Program.cs op.

  6. Voer de toepassing opnieuw uit in een terminal met behulp van dotnet run. U ziet dat de uitvoer nu de resultaten van de query bevat.

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

Georuimtelijke gegevens opvragen met LINQ

De LINQ-naar-NoSQL-functionaliteit in de .NET SDK biedt ondersteuning voor het opnemen van georuimtelijke typen in de queryexpressies. Verder bevat de SDK uitbreidingsmethoden die zijn toegewezen aan equivalente ingebouwde functies:

Extensiemethode Ingebouwde functie
Distance() ST_DISTANCE
Intersects() ST_INTERSECTS
IsValid() ST_ISVALID
IsValidDetailed() ST_ISVALIDDETAILED
Within() ST_WITHIN
  1. Open het Program.cs-bestand .

  2. Haal het Region item op uit de container met een unieke id en 1000 sla het op in een variabele met de naam region.

    Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
    
  3. Gebruik de Container.GetItemLinqQueryable<> methode om een LINQ-query mogelijk te maken en de LINQ-query vloeiend te bouwen door deze drie acties uit te voeren:

    1. Gebruik de Queryable.Where<> extensiemethode om te filteren op alleen items met een category equivalent van "business-office".

    2. Gebruik Queryable.Where<> opnieuw om te filteren op alleen locaties binnen de eigenschap van location de region variabele met behulp van Geometry.Within().

    3. Vertaal de LINQ-expressie naar een feed-iterator met behulp van CosmosLinqExtensions.ToFeedIterator<>.

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

    Belangrijk

    In dit voorbeeld heeft de locatie-eigenschap van het kantoor een punt en heeft de locatie-eigenschap van de regio een veelhoek. ST_WITHIN bepaalt of het punt van het kantoor binnen de veelhoek van de regio valt.

  4. Gebruik een combinatie van een tijdje en foreach-lus om alle resultaten op elke pagina met resultaten te herhalen. Voer elk resultaat uit naar de console.

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

  6. Voer de toepassing een laatste keer uit in een terminal met behulp van dotnet run. U ziet dat de uitvoer nu de resultaten van de tweede LINQ-query bevat.

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

Resources opschonen

Verwijder de database nadat u deze handleiding hebt voltooid.

  1. Open een terminal en maak een shellvariabele voor de naam van uw account en resourcegroep.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  2. Gebruik az cosmosdb sql database delete deze optie om de database te verwijderen.

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

Volgende stappen