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'
URL: https://data.gov.sk/api/action/datastore_search_sql?sql=SELECT%20%22objectId%22,%20%22municipalityName%22%20from%20%2215262453-4a0f-4cce-a9e4-7709e135e4b8%22%20WHERE%20%22municipalityName%22%20=%20%27Poprad%27
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'
URL: https://data.gov.sk/api/action/datastore_search_sql?sql=SELECT%20%22objectId%22,%20%22municipalityIdentifiers%22%20from%20%2247f0e853-3a67-487e-b45f-3f5d099105cf%22%20WHERE%20%22municipalityIdentifiers%22%20=%20%272087%27
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"
URL: https://data.gov.sk/api/action/datastore_search_sql?sql=SELECT%20%22municipalityName%22,%20%22streetName%22%20from%20%2215262453-4a0f-4cce-a9e4-7709e135e4b8%22,%20%2247f0e853-3a67-487e-b45f-3f5d099105cf%22%20WHERE%20%22municipalityName%22%20=%20%27Poprad%27%20AND%20%2215262453-4a0f-4cce-a9e4-7709e135e4b8%22.%22objectId%22::text%20=%20%2247f0e853-3a67-487e-b45f-3f5d099105cf%22.%22municipalityIdentifiers%22
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:
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
URL: https://data.gov.sk/api/action/datastore_search_sql?sql=SELECT%20%22municipalityName%22,%20%22streetName%22,%20%22buildingNumber%22%20from%20%2215262453-4a0f-4cce-a9e4-7709e135e4b8%22,%20%2247f0e853-3a67-487e-b45f-3f5d099105cf%22,%20%22011f4ec3-7a73-4dff-a63e-81b64cc52947%22%20WHERE%20%22municipalityName%22%20=%20%27Poprad%27%20AND%20%2215262453-4a0f-4cce-a9e4-7709e135e4b8%22.%22objectId%22::text%20=%20%2247f0e853-3a67-487e-b45f-3f5d099105cf%22.%22municipalityIdentifiers%22%20AND%20%2247f0e853-3a67-487e-b45f-3f5d099105cf%22.%22objectId%22%20=%20%22011f4ec3-7a73-4dff-a63e-81b64cc52947%22.%22streetNameIdentifier%22%20LIMIT%2010
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í | Časti obcí - zmenové dáta | objectId, versionId, validFrom, validTo, modified_timestamp, municipalityIdentifier |
Časti obcí - konsolidované dáta | 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 |
Vchody (orientačné čísla) - konsolidované dáta | objectId, versionId, validFrom, validTo, propertyRegistrationNumberIdentifier, streetNameIdentifier |