GeoJSON-helyadatok indexelése és lekérdezése az Azure Cosmos DB for NoSQL-ben

A KÖVETKEZŐKRE VONATKOZIK: NoSQL

Az Azure Cosmos DB for NoSQL térinformatikai adatai lehetővé teszik a helyadatok tárolását és a gyakori lekérdezések végrehajtását, többek között az alábbiakat:

  • Annak megállapítása, hogy egy hely egy meghatározott területen belül van-e
  • Két hely távolságának mérése
  • Annak meghatározása, hogy egy elérési út hellyel vagy területtel metszi-e egymást

Ez az útmutató végigvezeti a térinformatikai adatok létrehozásának, az adatok indexelésének, majd az adatok tárolóban való lekérdezésének folyamatán.

Előfeltételek

Tároló- és indexelési szabályzat létrehozása

Minden tároló tartalmaz egy alapértelmezett indexelési szabályzatot, amely sikeresen indexeli a térinformatikai adatokat. Testreszabott indexelési szabályzat létrehozásához hozzon létre egy fiókot, és adjon meg egy JSON-fájlt a szabályzat konfigurációjával. Ebben a szakaszban egy egyéni térbeli indexet használunk egy újonnan létrehozott tárolóhoz.

  1. Nyisson meg egy terminált.

  2. Hozzon létre egy rendszerhéjváltozót az Azure Cosmos DB for NoSQL-fiók és erőforráscsoport nevéhez.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  3. Hozzon létre egy nevű cosmicworks új adatbázist a használatával az cosmosdb sql database create.

    az cosmosdb sql database create \
        --resource-group $resourceGroupName \
        --account-name $accountName \
        --name "cosmicworks" \
        --throughput 400
    
  4. Hozzon létre egy új JSON-fájlt index-policy.json néven, és adja hozzá a következő JSON-objektumot a fájlhoz.

    {
      "indexingMode": "consistent",
      "automatic": true,
      "includedPaths": [
        {
          "path": "/*"
        }
      ],
      "excludedPaths": [
        {
          "path": "/\"_etag\"/?"
        }
      ],
      "spatialIndexes": [
        {
          "path": "/location/*",
          "types": [
            "Point",
            "Polygon"
          ]
        }
      ]
    }
    
  5. A használatával az cosmosdb sql container create hozzon létre egy nevű locations új tárolót a partíciókulcs elérési útjával /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. Kérje le a fiók elsődleges kapcsolati sztring a használatávalaz cosmosdb keys list.

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

    Tipp

    A fiók összes lehetséges kapcsolati sztringjének megtekintéséhez használja a következőt az cosmosdb keys list --resource-group $resourceGroupName --name $accountName --type "connection-strings": .

  7. Jegyezze fel a kapcsolati sztring. Ezt a hitelesítő adatot az útmutató későbbi részében fogja használni.

.NET SDK-konzolalkalmazás létrehozása

Az Azure Cosmos DB for NoSQL -hez készült .NET SDK osztályokat biztosít a gyakori GeoJSON-objektumokhoz. Ezzel az SDK-val egyszerűsítheti a földrajzi objektumok tárolóhoz való hozzáadásának folyamatát.

  1. Nyisson meg egy terminált egy üres könyvtárban.

  2. Hozzon létre egy új .NET-alkalmazást a dotnet new parancs és a konzolsablon használatával.

    dotnet new console
    
  3. Importálja a Microsoft.Azure.Cosmos NuGet-csomagot a dotnet add package paranccsal.

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

    Figyelmeztetés

    Az Entity Framework jelenleg nem végez térbeli adatokat az Azure Cosmos DB for NoSQL-ben. Használja a NoSQL-hez készült Azure Cosmos DB SDK-k egyikét az erős típusú GeoJSON-támogatáshoz.

  4. Hozza létre a projektet a dotnet build paranccsal.

    dotnet build
    
  5. Nyissa meg a választott integrált fejlesztői környezetet (IDE) ugyanabban a könyvtárban, mint a .NET-konzolalkalmazást.

  6. Nyissa meg az újonnan létrehozott Program.cs fájlt, és törölje a meglévő kódot. Add using directives for the Microsoft.Azure.Cosmos, Microsoft.Azure.Cosmos.Linq, andMicrosoft.Azure.Cosmos.Spatial namespaces.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  7. Adjon hozzá egy *connectionString nevű sztringváltozót az útmutató korábbi részében rögzített kapcsolati sztring.

    string connectionString = "<your-account-connection-string>"
    
  8. Hozzon létre egy új példányt az osztálynak, amely connectionString átadja és CosmosClient becsomagolja egy using utasításba.

    using CosmosClient client = new (connectionString);
    
  9. A és a használatával CosmosClient.GetDatabaseDatabase.GetContainerkérje le a korábban létrehozott tárolóra (cosmicworks/locations) mutató hivatkozást az Azure Cosmos DB for NoSQL-fiókban. Tárolja az eredményt egy nevű containerváltozóban.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  10. Mentse a Program.cs fájlt.

Térinformatikai adatok hozzáadása

A .NET SDK több típust is tartalmaz a névtérben a Microsoft.Azure.Cosmos.Spatial gyakori GeoJSON-objektumok megjelenítéséhez. Ezek a típusok leegyszerűsítik az új helyadatok tárolóelemekhez való hozzáadásának folyamatát.

  1. Hozzon létre egy új fájlt Office.cs néven. A fájlban adjon hozzá egy using direktívát a fájlhozMicrosoft.Azure.Cosmos.Spatial, majd hozzon létre egy rekordtípustOffice az alábbi tulajdonságokkal:

    Típus Description Alapértelmezett érték
    id string Egyedi azonosító
    név string Az iroda neve
    Helyen Point GeoJSON földrajzi pont
    Kategória string Partíciókulcs értéke business-office
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Office(
        string id,
        string name,
        Point location,
        string category = "business-office"
    );
    

    Megjegyzés

    Ez a rekord tartalmaz egy tulajdonságot Point , amely egy adott pozíciót jelöl a GeoJSON-ban. További információ: GeoJSON-pont.

  2. Hozzon létre egy másik, Region.cs nevű új fájlt. Adjon hozzá egy másik nevű Region rekordtípust a következő tulajdonságokkal:

    Típus Description Alapértelmezett érték
    id string Egyedi azonosító
    név string Az iroda neve
    Helyen Polygon GeoJSON földrajzi alakzat
    Kategória string Partíciókulcs értéke business-region
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Region(
        string id,
        string name,
        Polygon location,
        string category = "business-region"
    );
    

    Megjegyzés

    Ez a rekord tartalmaz egy tulajdonságot Polygon , amely egy alakzatot jelöl, amely a GeoJSON több helye között rajzolt vonalakból áll. További információ: GeoJSON-sokszög.

  3. Hozzon létre egy másik új fájlt Result.cs néven. Adjon hozzá egy nevű Result rekordtípust a következő két tulajdonsággal:

    Típus Description
    név string Az egyeztetett eredmény neve
    distanceKilometers decimal Távolság kilométerben
    public record Result(
        string name,
        decimal distanceKilometers
    );
    
  4. Mentse az Office.cs, Region.cs és Result.cs fájlokat.

  5. Nyissa meg újra a Program.cs fájlt.

  6. Hozzon létre egy újat Polygon egy nevű mainCampusPolygonváltozóban.

    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. Hozzon létre egy nevű mainCampusRegion új Region változót a sokszög, az egyedi azonosító 1000és a név Main Campushasználatával.

    Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
    
  8. A használatával Container.UpsertItemAsync adja hozzá a régiót a tárolóhoz. Írja be a régió adatait a konzolra.

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

    Tipp

    Ez az útmutató beszúrás helyett upsert fájlt használ, így a szkriptet többször is futtathatja anélkül, hogy ütközést okozna az egyedi azonosítók között. Az upsert műveletekkel kapcsolatos további információkért lásd az elemek létrehozását ismertető cikket.

  9. Hozzon létre egy nevű új Point változót headquartersPoint. Ezzel a változóval hozzon létre egy új Office nevű headquartersOffice változót a pont, az egyedi azonosító 0001és a név Headquartershasználatával.

    Point headquartersPoint = new (-122.12827, 47.63980);
    Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
    
  10. Hozzon létre egy másik Point nevű változót researchPoint. Ezzel a változóval hozzon létre egy másik Office nevű változót researchOffice a megfelelő pont, az egyedi azonosító 0002és a név Research and Developmenthasználatával.

    Point researchPoint = new (-96.84369, 46.81298);
    Office researchOffice = new ("0002", "Research and Development", researchPoint);
    
  11. Hozzon létre egy to TransactionalBatch upsert mindkét Office változót egyetlen tranzakcióként. Ezután írja be mindkét iroda adatait a konzolra.

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

    Megjegyzés

    A tranzakciókról további információt a tranzakciós kötegműveletek című témakörben talál.

  12. Mentse a Program.cs fájlt.

  13. Futtassa az alkalmazást egy terminálban a paranccsal dotnet run. Figyelje meg, hogy az alkalmazásfuttatás kimenete tartalmazza a három újonnan létrehozott elemet.

    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 }
    

Térinformatikai adatok lekérdezése NoSQL-lekérdezéssel

A névtérben lévő Microsoft.Azure.Cosmos.Spatial típusok egy NoSQL paraméteres lekérdezés bemeneteként használhatók az olyan beépített függvények használatához, mint a ST_DISTANCE.

  1. Nyissa meg a Program.cs fájlt.

  2. Hozzon létre egy új string változót a lekérdezéssel együtt nosql , amely ebben a szakaszban a pontok közötti távolság mérésére szolgál.

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

    Tipp

    Ez a lekérdezés a térinformatikai függvényt egy alkérdezésen belül helyezi el, hogy leegyszerűsítse a már kiszámított érték és záradékok többszöri SELECTWHERE újrafelhasználásának folyamatát.

  3. Hozzon létre egy nevű query új QueryDefinition változót a nosqlString változó paraméterként való használatával. Ezután a QueryDefinition.WithParameter fluent metódus többszöri használatával adja hozzá ezeket a paramétereket a lekérdezéshez:

    Érték
    @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. Hozzon létre egy új iterátort a használatával, az Result általános típussal és a query változóvalContainer.GetItemQueryIterator<>. Ezután egy idő és egy foreach hurok kombinációjával iteráljon az eredmények minden oldalán. Az egyes eredmények kimenete a konzolra.

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

    Megjegyzés

    A lekérdezési eredmények számbavételéről további információt a lekérdezéselemek című témakörben talál.

  5. Mentse a Program.cs fájlt.

  6. Futtassa újra az alkalmazást egy terminálban a paranccsal dotnet run. Figyelje meg, hogy a kimenet most már tartalmazza a lekérdezés eredményeit.

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

Térinformatikai adatok lekérdezése a LINQ használatával

A .NET SDK LINQ–NoSQL funkciója támogatja a térinformatikai típusokat a lekérdezési kifejezésekben. Az SDK emellett olyan bővítménymetó módszereket is tartalmaz, amelyek egyenértékű beépített függvényekhez képeznek le:

Bővítménymetódus Beépített függvény
Distance() ST_DISTANCE
Intersects() ST_INTERSECTS
IsValid() ST_ISVALID
IsValidDetailed() ST_ISVALIDDETAILED
Within() ST_WITHIN
  1. Nyissa meg a Program.cs fájlt.

  2. Kérje le az Region elemet a tárolóból egy egyedi azonosítóval 1000 , és tárolja egy nevű regionváltozóban.

    Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
    
  3. Container.GetItemLinqQueryable<> A metódussal lekérdezhető LINQ-lekérdezést kaphat, és a LINQ-lekérdezést az alábbi három művelet végrehajtásával hozhatja létre folyékonyan:

    1. A bővítménymetódussal csak azokkal Queryable.Where<> az elemekkel szűrhet, amelyek egyenértékűek a következővel category"business-office": .

    2. Ismét használva Queryable.Where<> csak a változó tulajdonságán location belüli helyekre szűrhet a region használatávalGeometry.Within().

    3. Fordítsa le a LINQ kifejezést egy hírcsatorna-iterátorra a használatával CosmosLinqExtensions.ToFeedIterator<>.

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

    Fontos

    Ebben a példában az iroda helytulajdonságának van egy pontja, a régió helytulajdonságának pedig sokszöge. ST_WITHIN meghatározza, hogy az iroda pontja a régió sokszögén belül van-e.

  4. Egy idő és egy foreach hurok kombinációjával iteráljon az eredmények minden oldalán. Az egyes eredmények kimenete a konzolra.

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

  6. Futtassa utoljára az alkalmazást egy terminálban a paranccsal dotnet run. Figyelje meg, hogy a kimenet most már tartalmazza a második LINQ-alapú lekérdezés eredményeit.

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

Az erőforrások eltávolítása

Az útmutató elvégzése után távolítsa el az adatbázist.

  1. Nyisson meg egy terminált, és hozzon létre egy rendszerhéjváltozót a fiók és az erőforráscsoport nevéhez.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  2. Az adatbázis eltávolítására használható az cosmosdb sql database delete .

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

Következő lépések