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:

  1. konsolidované dáta: všetky časové verzie všetkých objektov - aktuálne aj historické
  2. 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 zaujima
  • objectId (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

streetNamebuildingNumber
Poprad1.mája8
Poprad1.mája27
.........

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.

datasetresourcestĺpce na ktorých je index
Register budov (súpisných čísiel)Budovy (súpisné čísla) - zmenové dátaobjectId, versionId, validFrom, validTo, modified_timestamp, municipalityIdentifier, districtIdentifier
Budovy (súpisné čísla) - konsolidované dátaobjectId, versionId, validFrom, validTo, municipalityIdentifier, districtIdentifier
Register bytovByty - zmenové dátaobjectId, 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 krajovKraj - zmenové dátaobjectId, versionId, validFrom, validTo, modified_timestamp
Kraj - konsolidované dátaobjectId, versionId, validFrom, validTo
Register obcíObce - zmenové dátaobjectId, versionId, validFrom, validTo, modified_timestamp, countyIdentifier, cityIdentifier
Obce - konsolidované dátaobjectId, versionId, validFrom, validTo, countyIdentifier, cityIdentifier
Register okresovOkresy - zmenové dátaobjectId, versionId, validFrom, validTo, modified_timestamp, regionIdentifier
Okresy - konsolidované dátaobjectId, versionId, validFrom, validTo, regionIdentifier
Register ulícUlice - zmenové dátaobjectId, versionId, validFrom, validTo, modified_timestamp, districtIdentifiers, municipalityIdentifiers
Ulice - konsolidované dátaobjectId, versionId, validFrom, validTo, districtIdentifiers, municipalityIdentifiers
Register vchodov (orientačných čísiel)Vchody (orientačné čísla) - zmenové dátaobjectId, versionId, validFrom, validTo, modified_timestamp, propertyRegistrationNumberIdentifier, streetNameIdentifier

Vchody (orientačné čísla) - konsolidované dáta

objectId, versionId, validFrom, validTo, propertyRegistrationNumberIdentifier, streetNameIdentifier