Dette dokument er en guide til hvordan anvendere kan bruge Datafordelerens entitetsbaserede GraphQL-tjenester.
Dokumentet er opdelt i tre dele:
- Første del af dokumentet beskriver hvad entitetsbaserede GraphQL-tjenester er og hvordan de bruges.
- Anden del af dokumentet beskriver hvordan autentifikation og autorisation håndteres.
- Tredje del af dokumentet forklarer forskelle mellem GraphQL og de nuværende REST-tjenester på Datafordeleren, samt hvordan anvendere kan komme i gang med at anvende GraphQL-tjenester.
Dokumentet er tiltænkt følgende læsere: - Eksisterende anvendere af Datafordeleren der bruger den Nuværende Datafordelers REST-tjenester, som ønsker at komme i gang med at bruge de entitetsbasereede GraphQL-tjenester i stedet.
- Nye anvendere, der vil i gang med at bruge GraphQL-tjenesterne på Datafordeleren.
Begreber
I dette dokument bruges begreberne i Tabel 1. Bemærk at begreberne også er yderligere forklaret i løbet af dokumentet med eksempler.
...
Begreb
...
Beskrivelse
...
Nuværende Datafordeler
...
REST-tjenester:
...
REST-tjenester er en metode til at få data fra Datafordeleren. Man kan som anvender hente data ved at bruge en URL. REST-tjenester er beskrevet her https://confluence.sdfi.dk/pages/viewpage.action?pageId=17138461.
...
Moderniserede Datafordeler
...
GraphQL:
...
GraphQL beskrives i denne vejledning.
...
Entitet:
...
En entitet er en fysisk repræsentation af et registerobjekt som findes i Grunddatamodellen. De total- og deltadownload, der kan hentes fra Datafordeleren, indeholder hver især data bestående af en enkelt entitet.
...
GraphQL-skemaer:
...
GraphQL-skemaer er .graphql-filer der genereres på baggrund af registrenes datamodeller og er yderligere beriget med metadata fra hvert register. Skemaerne beskriver hvordan data er struktureret og hvordan data kan hentes.
...
Paging:
...
Paging er når resultater inddeles i sider således at resultater returneres én side ad gangen.
Tabel 1: Begrebsliste.
GraphQL er en funktionalitet på Datafordeleren til udstilling af data. Dette dokument beskriver hvordan anvendere kan benytte GraphQL-tjenesterne til at hente tabulære data fra registrene på Datafordeleren.
Hvad er GraphQL?
GraphQL er et moderne API-sprog, der gør det muligt for anvendere at hente data på en effektiv og fleksibel måde. I modsætning til Datafordelerens nuværende REST-tjenester, hvor man ofte får for meget data, giver GraphQL mulighed for at hente præcis de oplysninger, anvenderen skal bruge. GraphQL-tjenesterne er derfor velegnede når anvendere ønsker at hente mindre datamængder og ikke nødvendigvis ønsker at postprocessere data efterfølgende.
Med GraphQL kan anvendere definere hvilke datafelter de ønsker returneret. Dette betyder, at de kun modtager de oplysninger, de har brug for, hvilket kan forbedre ydeevnen og reducere mængden af data, der overføres.
Anvendere kan bruge GraphQL-tjenesterne ved at sende en forespørgsel, der beskriver de data de ønsker, til Datafordeleren, hvorefter serveren kun svarer med de specifikke data, der blev anmodet om. Dette kan blandt andet gøres gennem en desktop applikation eller gennem browseren ved brug af en browser-extension.
Yderligere information om GraphQL kan findes på graphql.org.
Måden man bruger GraphQL-tjenesterne på, er ved at sende en såkaldt query til et af Datafordelerens GraphQL-endepunkter. En query er anvendernes måde at definere hvilke data de ønsker at hente. Et eksempel på en query kan ses i Figur 1 nedenfor.
query {
BBR_Bygning( # Entitet
where: { # Standardfiltre
kommunekode: { eq: "0550" }
virkningsaktoer: { startsWith: "Konvertering" }
}
virkningstid: "2024-11-12T14:41:33Z" # Bitemporalt filter
first: 10 # Paging
) {
pageInfo { # Paginginformation
startCursor
endCursor
hasNextPage
hasPreviousPage
}
nodes {
id_lokalId
kommunekode
virkningsaktoer
}
}
}
Figur 1: Eksempel på en GraphQL-query
GraphQL-queries fungerer således:
- Entitet (beskrevet i afsnit 2.2): Hver query skal specificere hvilken entitet den omhandler. Eksemplet ovenfor viser en query for entiteten BBR_Bygning fra BBR og specifikt kun for 3 kolonner (angivet i "nodes"): id_lokalId, kommunekode og virkningsaktoer.
- Endepunkt (beskrevet i afsnit 2.3): En query sendes til et GraphQL-endepunkt som et GET- eller POST-request.
- Standardfiltre (beskrevet i afsnit 2.4): En query kan indeholde standardfiltre der filtrerer data. Query'en ovenfor indeholder to standardfiltre: et lighedsfilter (eq: "0550") på kommunekode-kolonnen og et tekstfilter (startsWith: "Konvertering") på virkningsaktoer-kolonnen.
- Geometriske filtre (beskrevet i afsnit 2.5): En query kan også indeholde geometriske filtre, der filtrerer data på baggrund af geometri-felter.
- Bitemporale filtre (beskrevet i afsnit 2.6): En query kan også indeholde bitemporale filtre. Query'en oven for indeholder et bitemporalt point-in-time-filter (virkningstid: "2024-11-12T14:41:33Z") på virkningstidspunktet.
- Paging (beskrevet i afsnit Fejl! Henvisningskilde ikke fundet.): En query kan også definere hvordan data pagineres. Query'en oven for returnerer de første 10 rækker (first: 10) givet filtreringen samt paginginformation for resultatsættet (angivet i "pageInfo").
Om entitetsbaserede GraphQL-tjenester
GraphQL-tjenester tilbydes som entitetsbaserede GraphQL-tjenester og baserer sig på de datamodeller som registrene har på Datafordeleren.
En entitet svarer til en tabel defineret i registrenes datamodel fra Grunddatamodellen: https://datafordeler.dk/grunddatamodel/ En entitet kan eksempelvis være en "Adresse" fra DAR, en "Bygning" fra BBR eller et "Jordstykke" fra MAT. Det at GraphQL-tjenesterne er entitetsbaserede betyder at et kald til en af tjenesterne returnerer data for en enkelt type af entitet. De entitetsbaserede GraphQL-tjenester leverer udelukkende tabulære data og ikke rasterdata (billeddata). Tabulære data forstås som strukturerede data der kan opbevares i tabeller, som fx adresser men ikke billedtyper som skærmkort.
Brug af API'et beskrives nærmere i afsnittet 2.11.
Figur 2: Opsummering af GraphQL-funktionalitet
En opsummering hvad GraphQL-tjenesterne består af, kan ses i ovenstående figur. Figuren viser 3 registre:
- Register A, som har 5 entiteter. Registerets entiteter refererer til hinanden indbyrdes indenfor registeret og har også en enkelt reference til en entitet i register C udenfor registeret.
- Register B, som har 6 entiteter. Registerets entiteter refererer til hinanden indbyrdes indenfor registeret og har også en enkelt reference til en entitet i register A udenfor registeret.
- Register C, som har 6 entiteter. Registerets entiteter refererer til hinanden indbyrdes indenfor registeret.
I modsætning til registrenes datamodeller har de entitetsbaserede GraphQL-tjenester på nuværende tidspunkt ingen relationer men kaldes enkeltvis per entitet.
GraphQL-endepunkter
GraphQL-tjenesterne udstilles gennem URL'er, der følger nedenstående form:
https://graphql.datafordeler.dk/<register>/<version>
<register> er forkortelsen for det register anvenderen forsøger at hente og <version> er versionen for det pågældende register. Versionering er yderligere beskrevet i afsnit 2.9.
Alle registre, hvis entiteter udstilles via GraphQL-tjenesterne, er vist i Tabel 2 nedenfor.
...
Register
...
Forkortelse
...
Bygnings- og Boligregistret
...
BBR
...
Danmarks Administrative Geografiske Inddeling
...
DAGI
...
Danmarks Adresseregister
...
DAR
...
Danmarks Fikspunktregister
...
FIKSPUNKT
...
DHM Højdekurver
...
DHMHoejdekurver
...
DHM Oprindelse
...
DHMOprindelse
...
...
...
...
...
...
...
...
...
Tabel 3: Oversigt over registre med adgangsbegrænsede data.
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Boolean
...
...
...
Tabel 4: Understøttede datatyper og operatorer
Geometrisk filtrering
...
Point POINT (3 5) Line LINESTRING (6 4, 8 2, 7 1) Polygon POLYGON (1 1, 3 3, 4 2, 4 0, 1 1) |
...
Datatyper
...
Understøttede operatorer
...
PostGis Link
...
Geometri
...
contains(koordinatsystem, geometri)
...
https://postgis.net/docs/ST_Contains.html
...
covers(koordinatsystem, geometri)
...
https://postgis.net/docs/ST_Covers.html
...
...
...
...
...
...
...
...
...
...
...
...
...
Geometrisk operator | Omvendte operator |
contains | within |
covers | coveredBy |
coveredBy | covers |
crosses | Ingen. crosses er symmetrisk |
intersects | Ingen. intersects er symmetrisk |
within | contains |
overlaps | Ingen. overlaps er symmetrisk |
touches | Ingen. touches er symmetrisk |
Tabel 6: Geometriske operatorer og deres omvendte operatorer.
Syntaksen for at bruge geometriske filtre, og hvilke felter der kan filtreres geometrisk, er specificeret af GraphQL-skemaet for den pågældende tjeneste, som man ønsker at bruge. Når man angiver WKT-strengen for den geometri, der skal filtreres på, skal man også angive, hvilket koordinatsystem (CRS) deres WKT tilhører, som illustreret i eksemplet i Figur 4.
Da geospatiale data kan have forskellige formater afhængigt af, hvilket register det drejer sig om, udfører Datafordeleren udelukkende validering på om det angivne koordinatsystem (CRS) er det samme koordinatsystem som registrets data og at den angivne WKT er valid og repræsenterer en topologisk valid geometri som specificeret i OGC SFS-specifikationen.
Bitemporal filtrering
Der er to typer queries, som man kan udføre på bitemporale data:
- Interval-queries, hvor man ønsker data, der er bitemporalt gyldige i en bestemt tidsperiode.
- Point-in-time-queries, hvor man ønsker bitemporalt gyldige data pr. deres angivne tidspunkt.
...
Bitemporal filtrering for CVR
Alle registre der understøtter bitemporal filtrering, understøtter filtrering på både virkningstidspunkt og registreringstidspunkt bortset fra CVR. CVR er det eneste register, hvor anvendere ikke kan specificere et registreringspunkt i deres query. For CVR sættes registreringstidspunktet derimod altid til tidspunktet for forespørgslen, dvs. "registreringstid = NOW()". Det er muligt at filtrere på virkningstidspunktet på sædvanlig vis.
Paging
GraphQL-tjenesterne understøtter paging af resultater. At resultaterne pagineres vil sige at resultaterne inddeles i "sider" og returneres én ad gangen. Anvendere vil således få én side returneret ad gangen og kan efterfølgende lave et nyt kald for at få næste side for på den måde at gennemgå hele datasættet.
Pagingen er cursor-baseret, hvilket vil sige at der returneres en reference, en såkaldt cursor, til første og sidste resultat (for edges ved hvert enkelt resultat) i det returnerede datasæt ved hvert kald. Denne cursor kan derefter bruges til at hente flere sider ved at anmode om mere data fra cursorens værdi. I praksis kan anvendere bruge cursor-værdien i en efterfølgende query, til at hente den næste side af data, startende fra den position, der er angivet ved den pågældende cursor. Paging er implementeret således at flere identiske anmodninger ved hjælp af den samme cursor vil returnere de samme data, forudsat at registrene ikke opdaterer de underliggende data i mellemtiden.
Paging er udelukkende implementeret som fremadgående paging. Det vil sige, at anvenderne kan hente den næste side af resultater fra en given cursor. Bagudgående paging understøttes ikke.
Paging i queries: PageInfo, nodes og edges
Paging består af tre datastrukturer: PageInfo samt nodes eller edges.
PageInfo indeholder metadata om den nuværende paging og består af følgende felter:
...
...
...
...
...
...
...
...
...
...
...
Eksempler på paging-queries
Følgende query kan bruges til at hente de første 5 datapunkter fra første side af BBR_Bygning-entiteten:
query {
BBR_Bygning(first: 5, after: null) {
pageInfo {
endCursor
hasNextPage
} nodes {
id_lokalId
}
}
}
Figur 5: Eksempel på en GraphQL-query med first=5.
Tjenesten returnerer følgende resultat:
{
"data": {
"BBR_Bygning": {
"pageInfo": {
"endCursor": "1rsNAAAAAAA=",
"hasNextPage": true
},
Wiki Markup |
---|
*"nodes": \[* |
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Body
For GET-requests:
...
Returværdier Returværdierne for HTTP-statuskoderne afhænger af hvilken Accept-header der specificeres. Disse værdier er hvis Accept-headeren ikke er angivet som beskrevet i "Headere i forespørgsel".
...
- Returnerer HTTP 200 – OK, ved succes.
- Returnerer HTTP 400 – Bad Request, ved angivelse af forkerte parametre.
- Returnerer HTTP 404 – Not Found, hvis den angivne ressource ikke kan findes.
- Returnerer HTTP 500 – Internal Server Error, hvis der er sket en ukendt fejl
...
Adgang
...
...
...
...
...
...
...
...