- Created by Hanečák Peter, last modified on Jan 06, 2018
V januári 2016 začalo MV SR v spolupráci s NASES zverejňovať údaje z Registra adries (RA) v podobe otvorených údajov prostredníctvom portálu data.gov.sk.
Keďže RA obsahuje o čosi viac než len zoznam adresných bodov, je na data.gov.sk zverejnený ako sada viacerých datasetov, viď https://data.gov.sk/dataset?tags=register+adries .
Nuž a je tu napr. otázka "takže aký je postup pre niekoho kto chce zistiť všetky adresy v meste X?" (viď Platforma Slovensko.Digital).
Úvod
Dátový model RA obsahuje zoznamy viacerých typov objektov:
- adresné body
- vchody
- ulice
- obce
- ...
Zjednodušene povedané, jeden typ objektov = jeden zoznam = jedna DB tabuľka.
Mapovanie na datasety je teda realizované systémom jedna DB tabuľka = jeden dataset. V datasetoch sú potom údaje dostupne pod tzv. resources, konkrétne vždy dvojmo:
- konsolidované dáta: všetky časové verzie všetkých objektov - aktuálne aj historické
- zmenové dáta: jeden riadok v tabuľke predstavuje jednu zmenu a dokumentuje históriu zmien
A API je implementované pomocou CKAN DataStore, takže budeme postupovať podľa SQL API na baze CKAN DataStore: JOIN.
Krok 1
Chceme teda vyhľadávať cez názov mesta, takže nás najprv zaujíma dataset "Register Adries - Register obcí" (dokumentácia).
Údaje budeme brať z resource "Obce - konsolidované dáta" ku ktorému je podstatnou informáciou jeho ID "15262453-4a0f-4cce-a9e4-7709e135e4b8
" (viď už spomenutý článok o SQL API na báze CKAN DataStore).
Zaujímajú nás pre jednoduchosť tieto položky:
municipalityName
(názov obce): podla neho budeme vyhľadávaťobjectId
(identifikátor objektu): s ohľadom na dátovú schému, pomocou tohto identifikátora budeme filtrovať ulice patriace k mestu s týmto ID
Takže povedzme, že ideme hľadať adresy pre mesto Poprad. Prvý dopyt teda bude vyzerať takto:
SELECT "objectId", "municipalityName" FROM "15262453-4a0f-4cce-a9e4-7709e135e4b8" WHERE "municipalityName" = 'Poprad'
Výsledok (krátený):
{"help": "...", "success": true, "result": { "records":[{"municipalityName": "Poprad", "objectId": "2087"}], "fields": [{"type": "int8", "id": "objectId"}, {"type": "text", "id": "municipalityName"}], "sql": "SELECT \"objectId\", \"municipalityName\" from \"15262453-4a0f-4cce-a9e4-7709e135e4b8\" WHERE \"municipalityName\" = 'Poprad'"}}
Krok 2
Poďme sa teda pozrieť na ulice v danom meste. Zaujíma nás dataset "Register Adries - Register ulíc" (dokumentácia).
Údaje vezmeme z resource "Ulice - konsolidované dáta" ktorého ID je "47f0e853-3a67-487e-b45f-3f5d099105cf
".
Zaujímajú nás tieto položky:
streetName
(názov)municipalityIdentifiers
(buď identifikátor obce alebo identifikátory mestských častí, cez ktoré ulica prechádza): tot by malo byt ID obce ktora nas zaujimaobjectId
(identifikátor objektu): s ohľadom na dátovú schému, pomocou tohto identifikátora budeme filtrovať vchody patriace k ulici s týmto ID
Takže ďalší jednoduchý dopyt:
SELECT "objectId", "municipalityIdentifiers" FROM "47f0e853-3a67-487e-b45f-3f5d099105cf" WHERE "municipalityIdentifiers" = '2087'
Výsledok (krátený):
{"help": "...", "success": true, "result": { "records": [{"objectId": "39436", "municipalityIdentifiers": "2087"}, {"objectId": "40013", "municipalityIdentifiers": "2087"}, ...], "fields": [{"type": "int8", "id": "objectId"}, {"type": "text", "id": "municipalityIdentifiers"}], "sql": "..."}}
Zhruba to, čo sme čakali.
Takže poďme začať robiť JOIN:
SELECT "municipalityName", "streetName" FROM "15262453-4a0f-4cce-a9e4-7709e135e4b8", "47f0e853-3a67-487e-b45f-3f5d099105cf" WHERE "municipalityName" = 'Poprad' AND "15262453-4a0f-4cce-a9e4-7709e135e4b8"."objectId"::text = "47f0e853-3a67-487e-b45f-3f5d099105cf"."municipalityIdentifiers"
Výsledok (krátený):
{"help": "...", "success": true, "result": { "records": [{"municipalityName": "Poprad", "streetName": "Feldzamova"}, {"municipalityName": "Poprad", "streetName": "Marxova"}, ...], "fields": [{"type": "text", "id": "municipalityName"}, {"type": "text", "id": "streetName"}], "sql": "..."}}
Krok 3
A teraz poďme na vchody:
- dataset "Register Adries - Register vchodov (orientačných čísiel)"
- dokumentácia: https://data.gov.sk/dataset/register-adries-register-vchodov/resource/849d6364-10cf-40dd-a354-aba17ae06c52
- resource: "Vchody (orientačné čísla) - konsolidované dáta"
- resource ID:
011f4ec3-7a73-4dff-a63e-81b64cc52947
kde nás zaujímajú tieto položky:
buildingNumber
(orientačné číslo vchodu)streetNameIdentifier
(identifikátor (StreetName/objectId) ulice)
Poďme rovno na JOIN (a pridajme aj LIMIT, nech zbytočne nepreťažujeme)::
SELECT "municipalityName", "streetName", "buildingNumber" FROM "15262453-4a0f-4cce-a9e4-7709e135e4b8", "47f0e853-3a67-487e-b45f-3f5d099105cf", "011f4ec3-7a73-4dff-a63e-81b64cc52947" WHERE "municipalityName" = 'Poprad' AND "15262453-4a0f-4cce-a9e4-7709e135e4b8"."objectId"::text = "47f0e853-3a67-487e-b45f-3f5d099105cf"."municipalityIdentifiers" AND "47f0e853-3a67-487e-b45f-3f5d099105cf"."objectId" = "011f4ec3-7a73-4dff-a63e-81b64cc52947"."streetNameIdentifier" LIMIT 10
Výsledok (krátený):
{"help": "...", "success": true, "result": { "records": [{"municipalityName": "Poprad", "buildingNumber": "8", "streetName": "1.m\u00e1ja"}, {"municipalityName": "Poprad", "buildingNumber": "27", "streetName": "1.m\u00e1ja"}, ...], "fields": [{"type": "text", "id": "municipalityName"}, {"type": "text", "id": "streetName"}, {"type": "text", "id": "buildingNumber"}], "sql": "..."}}
Výsledok je vlastne tabuľka:
municipalityName | streetName | buildingNumber |
---|---|---|
Poprad | 1.mája | 8 |
Poprad | 1.mája | 27 |
... | ... | ... |
Záver
SQL dopyt z kroku 3 by nám teda mal dať časť odpovede na zadanie, zbytok ponechávam na čitateľa. Pre praktické využitie sa ešte treba viacej venovať zoznamu stľpcov ktoré si vypýtame, zoradeniu a tomu, či kompletný výsledok stiahneme na jeden šup alebo použijeme stránkovanie na báze OFFSET + LIMIT či ORDER BY + WHERE.
Príklady sú naschvál zjednodušené, aby sa to čo najľahšie čítalo. Asi najväčším opomenutím je to, že v príkladoch neberiem do úvahy platnosť údajov (t.j. aktuálny dátum a položky validFrom
a validTo
). Možno niekedy nabudúce.
Doplnky
Indexy
Doplnok k 2.3.3016: V OpenData.sk skupine na Facebooku bol dopyt ohľadom toho, na ktorých stĺpcoch sú nastavené indexy. Keďže cez CKAN DataStore API zatiaľ nefunguje "explain", tak vedomosť o indexoch môže napomôcť pri vylaďovaní výkonu dopytov.
dataset | resource | stĺpce na ktorých je index |
---|---|---|
Register budov (súpisných čísiel) | Budovy (súpisné čísla) - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, municipalityIdentifier, districtIdentifier |
Budovy (súpisné čísla) - konsolidované dáta | objectId, versionId, validFrom, validTo, municipalityIdentifier, districtIdentifier | |
Register bytov | Byty - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, buildingNumberIdentifier |
Byty - konsolidované dáta | objectId, versionId, validFrom, validTo, buildingNumberIdentifier | |
Register častí obcí
| objectId, versionId, validFrom, validTo, modified_timestamp, municipalityIdentifier | |
objectId, versionId, validFrom, validTo, municipalityIdentifier | ||
Register krajov | Kraj - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp |
Kraj - konsolidované dáta | objectId, versionId, validFrom, validTo | |
Register obcí | Obce - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, countyIdentifier, cityIdentifier |
Obce - konsolidované dáta | objectId, versionId, validFrom, validTo, countyIdentifier, cityIdentifier | |
Register okresov | Okresy - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, regionIdentifier |
Okresy - konsolidované dáta | objectId, versionId, validFrom, validTo, regionIdentifier | |
Register ulíc | Ulice - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, districtIdentifiers, municipalityIdentifiers |
Ulice - konsolidované dáta | objectId, versionId, validFrom, validTo, districtIdentifiers, municipalityIdentifiers | |
Register vchodov (orientačných čísiel) | Vchody (orientačné čísla) - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, propertyRegistrationNumberIdentifier, streetNameIdentifier |
objectId, versionId, validFrom, validTo, propertyRegistrationNumberIdentifier, streetNameIdentifier |