Skip to content

AtomGraph/LTLOD

Repository files navigation

LTLOD — Lietuvos susietieji atvirieji duomenys

LTLOD tikslas — lietuviškas Knowledge Graph: Lietuvos atvirieji duomenys, sujungti į vientisą, standartais grįstą RDF grafą, kurį galima užklausti, papildyti ir susieti su pasauliniais duomenimis (Wikidata, ES žodynais).

Šiame repozitoriuje yra:

  • atkuriamos (re-runnable) ETL grandinės (etl/), kurios kiekvieno paleidimo metu parsisiunčia aktualius duomenis iš oficialių šaltinių ir sugeneruoja RDF rinkinius;
  • sugeneruoti duomenų rinkiniai (datasets/current/) — beveik milijonas RDF ketvertų apie administracinius vienetus, Seimo narius, įstaigas;
  • SPARQL užklausų pavyzdžiai su rezultatais (etl/queries/EXAMPLES.md).

RDF trumpai

RDF — W3C standartas duomenims užrašyti grafo pavidalu. Kiekvienas faktas yra trejetas subjektas → predikatas → objektas, o objektai identifikuojami URI adresais, kurie galioja viso interneto mastu. Dėl to skirtingi rinkiniai susijungia savaime — užtenka, kad jie naudotų tuos pačius URI.

Štai tikri duomenys iš šio repozitorijaus (Seimo narys, jo frakcija ir partija):

graph LR
    person(["persons/7194/#this"]) -->|foaf:name| name["Algirdas Butkevičius"]
    membership(["…/#membership-1322-…"]) -->|org:member| person
    membership -->|org:organization| faction(["…/seimas/org-units/1322/#this"])
    membership -->|org:memberDuring| interval["time:Interval<br/>nuo 2024-11-14"]
    faction -->|skos:prefLabel| fname["Demokratų frakcija<br/>„Vardan Lietuvos“"]
    faction -->|org:unitOf| seimas(["organizations/<br/>lietuvos-respublikos-seimas/#this"])
    person -->|ltlod:nominatedBy| party(["parties/demokratu-sajunga-…/#this"])
    person -->|owl:sameAs| wd(["wikidata: Q394006"])
Loading

Narystė čia — atskiras objektas su galiojimo intervalu (org:Membership + time:Interval), todėl grafas saugo ne tik dabartinę būseną, bet ir istoriją: pasikeitus pareigoms, sena narystė gauna pabaigos datą, o nauja — pradžios.

Kiekvienas objektas gyvena savo named graph'e (dokumente), kurio URI sutampa su dokumento adresu. Štai visas Birštono savivaldybės dokumentas (TriG sintakse; čia parodyta išskleista absoliuti forma — užfiksuoti failai naudoja santykines URI, pvz. <admin-units/12/#this>, o bazė pritaikoma krovimo metu):

<https://linkeddata.lt/admin-units/12/> {
    <https://linkeddata.lt/admin-units/12/>
        dct:title "Birštono savivaldybė"@lt ;
        foaf:primaryTopic <https://linkeddata.lt/admin-units/12/#this> .

    <https://linkeddata.lt/admin-units/12/#this>
        a cv:AdminUnit ;                                        # ES Core Location klasė
        cv:level atu-type:LTU_SV ;                              # ES klasifikatorius: savivaldybė
        skos:prefLabel "Birštono savivaldybė"@lt ;
        skos:notation "12" ;                                    # natūralus raktas iš Adresų registro
        dct:isPartOf <https://linkeddata.lt/admin-units/2/#this> ;   # → Kauno apskritis
        owl:sameAs <http://www.wikidata.org/entity/Q2015893> ;  # → Wikidata
        schema:validFrom "1998-06-01"^^xsd:date .
}

Užklausoms naudojama SPARQL — standartinė RDF užklausų kalba (kaip SQL reliacinėms DB). Pavyzdžiai — žemiau.

Duomenų rinkiniai

Rinkinys Objektai Šaltinis
admin-units 10 apskričių, 60 savivaldybių, 584 seniūnijos, 26 229 gyvenamosios vietovės ir 61 149 gatvės (streets) Adresų registras per get.data.gov.lt
seimas 148 Seimo nariai su ~3 000 pareigų/narysčių (galiojimo intervalai), 137 padaliniai (frakcijos, komitetai, komisijos, parlamentinės grupės), 11 partijų apps.lrs.lt XML API
legal-entities 6 025 valstybės ir savivaldybių biudžetinės įstaigos JAR per get.data.gov.lt
taxonomies 8 SKOS klasifikatoriai: teisinės formos (iš JAR), statusai, pareigų/padalinių/vietovių/gatvių tipai JAR + išvesta iš duomenų

Rinkiniai tarpusavyje susieti natūraliais raktais (Adresų registro kodai, JAR kodai, Seimo asmenų ID) — iš bet kurio išorinio rakto galima sukonstruoti objekto URI. Pavyzdžiui, kiekvienos biudžetinės įstaigos registruota buveinė susieta su administraciniu vienetu (locn:adminUnit). Administraciniai vienetai papildomai turi koordinates (geo:lat/geo:long, visi lygiai) ir supaprastintas ribų geometrijas (gsp:asWKT, stambieji lygiai). Objektai taip pat susieti su Wikidata (owl:sameAs) ir turi atvaizdus: administracinių vienetų herbus (foaf:img — reprezentacinis, „ypač tinkamas“ atvaizdas), Seimo narių oficialius portretus ir vietovių nuotraukas (foaf:depiction).

graph LR
    streets[gatvės] -->|dct:isPartOf| admin[admin-units]
    legal[biudžetinės įstaigos] -->|locn:adminUnit · reg. buveinė| admin
    seimas[Seimo nariai] -->|org:Membership| units[padaliniai]
    seimas -->|ltlod:nominatedBy| parties[partijos]
    seimas -->|org:role| tax[taxonomies · SKOS]
    legal -->|rov:companyType / rov:orgStatus| tax
    admin -->|cv:level| atu[ES ATU-type klasifikatorius]
    admin -->|geo:lat/long · gsp:asWKT| geo[koordinatės · geometrijos]
    admin -->|owl:sameAs + herbai · foaf:img| wd[(Wikidata)]
    seimas -->|owl:sameAs + nuotraukos| wd
Loading

URI schema ir raktų taisyklės: etl/URI-SCHEME.md.

Ontologijos ir žodynai

Principas: pirmiausia W3C standartai → tada srities žodynai (ES SEMIC, OP klasifikatoriai, FOAF) → schema.org kaip platus bendrasis fallback'as → savi terminai tik kraštutiniu atveju.

Sritis Žodynas
Administraciniai vienetai, adresai SEMIC Core Location 2.1.1 (cv:AdminUnit, cv:level) + ES ATU-type klasifikatorius (LTU_APS, LTU_SV, LTU_SEN…)
Juridiniai asmenys RegOrg / Core Business (rov:RegisteredOrganization, rov:companyType, rov:orgStatus)
Organizacijų struktūra, pareigos, narystės W3C ORG (org:Membership, org:role, org:memberDuring) + W3C Time intervalai — be reifikacijos ir be RDF-star
Asmenys FOAF (+ suderinama su Core Person 2.0)
Klasifikatoriai SKOS
Savi terminai vienintelis ltlod:nominatedBy (http://linkeddata.lt/ns#) — „iškėlusi partija“, kuriam ES/W3C atitikmens nėra

Pasirinkimų motyvacija ir žinomos modeliavimo skolos: etl/ONTOLOGY-NOTES.md.

Diegimas ir paleidimas

Reikalavimai:

  • Docker — tik atomgraph/csv2rdf konteineriui (CSV → RDF normalizacijai). docker-compose nereikia — jokios nuolat veikiančios infrastruktūros ETL nenaudoja.
  • Apache Jena 5.6.0 (atsisiųsti) — arq/riot CLI transformacijoms ir validacijai. Naujesnės 6.x versijos netinka: arq nebemoka išvesti kvadų CONSTRUCT rezultatų (TriG, žr. apache/jena#4091). Kelias nurodomas JENA_HOME arba etl/config.mk.
  • xsltproc — XML šaltinių (Seimo API) transformacijoms (macOS/Linux jau turi).
  • uv — Python įrankiams (Wikidata susiejimas, scraperiai); priklausomybes susitvarko pats.
  • make, curl.
cd etl
make                                  # viskas: taxonomies → admin-units → seimas → legal-entities
make -C seimas all                    # tik vienas domenas
make -C seimas photos                 # papildomai: oficialūs portretai iš lrs.lt
make BASE=https://linkeddata.lt/      # produkcinė bazinė URI (numatytoji — https://localhost:4443/)

Kiekvienas rinkinys pereina tas pačias keturias stadijas, tad naujo šaltinio pridėjimas — tik naujas katalogas su fetch + transformacijos užklausa:

graph LR
    src["Šaltiniai<br/>get.data.gov.lt · apps.lrs.lt"] -->|fetch| raw["CSV / XML"]
    raw -->|"CSV2RDF / XSLT"| norm["tarpinis RDF"]
    norm -->|"graphify:<br/>SPARQL CONSTRUCT"| trig["TriG<br/>(objektas = named graph)"]
    trig -->|validate| out["datasets/current/"]
    out -->|"reconcile:<br/>Wikidata"| align["alignments.trig<br/>+ herbai, nuotraukos"]
Loading

Rezultatas visada atspindi šaltinių būseną paleidimo metu — jokių rankinių žingsnių.

Publikavimas su LinkedDataHub

Rinkiniai publikuojami kaip naršomi Linked Data dokumentai per LinkedDataHub (toliau — LDH). Reikia tik Docker Desktop (Compose ≥ 2.23); visa infrastruktūra aprašyta docker-compose.yml (tas pats išdėstymas kaip linkeddatahub.com / Homepage projektuose — nginx, LDH, du Fuseki, Varnish kešai).

make up      # sugeneruoja slaptažodžius + serverio sertifikatą ir paleidžia LDH
make install # suteikia viešą skaitymo prieigą, sukuria konteinerių dokumentus ir vardų erdvės
             # ontologiją per LDH CLI (reikia ../LinkedDataHub);
             # interaktyvus: Enter×4 = lokali aplinka, kitas Base URL = bet kuri LDH instancija
make load    # užkrauna datasets/current/*/*.trig tiesiai į triplestore
             # (nereikia perkurti — rinkiniai bazei neutralūs; bazė pritaikoma krovimo metu)

Po make up LDH pasiekiamas adresu https://localhost:4443/ (savo pasirašytas sertifikatas — naršyklė įspės; pirmas paleidimas trunka ~1–2 min.). Administravimo aplinka — https://admin.localhost:4443/.

Svarbu dėl bazinės URI: repozitorijoje užfiksuoti datasets/current/ failai naudoja santykines URI (be @base), tad yra neutralūs bazei — tas pats rinkinys tinka bet kuriam diegimui. make load išsprendžia santykines URI pagal .env bazę (BASE_URI, lokaliai https://localhost:4443/) su riot prieš tdb2.tdbloader, tad dokumentų URI visada sutampa su LDH adresu. Perkurti prieš krovimą nebūtina — make -C etl reikia tik norint atsinaujinti duomenis iš gyvų šaltinių.

Duomenų struktūra kuriama dviem lygiais:

  • Karkasas (make install): šakninis dokumentas, konteineriai ir taksonomijų schemos iš app/ katalogo dokumentas po dokumento per LDH CLI (put.sh, kaip LinkedDataHub-Apps projektuose) — taip dokumentai gauna ldh:ChildrenView bloką, dėl kurio konteinerių puslapiai rodo vaikų sąrašus. Kartu įdiegiama vardų erdvės ontologija (app/ns.ttl) su 1:N rodiniais (ldh:inverseView): apskrities puslapis rodo jos savivaldybes, komiteto — dabartinius ir buvusius narius, Seimo — padalinius, partijos — jos iškeltus Seimo narius. Reikia šalia išklonintos LinkedDataHub repozitorijos (../LinkedDataHub, keičiama per make install LDH_HOME=…).
  • Duomenys (make load): ETL rinkiniai — vien dh:Item dokumentai su sioc:has_container nuorodomis į karkasą — rašomi tiesiogiai į fuseki-end-user TDB2 saugyklą (santykinės URI pirma išsprendžiamos pagal .env bazę su riot, tada tdb2.tdbloader per vienkartinį tdb-loader konteinerį), ne po vieną dokumentą per HTTP: ~1 mln. ketvertų užsikrauna per kelias minutes. Pabaigoje suteikiama vieša skaitymo prieiga (make public — LDH CLI make-public.sh atitikmuo, vykdomas tiesiogiai per fuseki-admin konteinerių tinkle). Triplestore prievadai neatveriami į host'ą — SPARQL užklausos teikiamos per LDH: https://localhost:4443/sparql. Krovimas yra append-only: pakartotinis make load tik papildo saugyklą; švariam perkrovimui:
make down && rm -rf fuseki/end-user && make up && make load

Dokumento patikrinimas (Birštono savivaldybė):

curl -k -H "Accept: text/turtle" https://localhost:4443/admin-units/12/

Pastabos:

  • make drop ištrina tik LDH vykdymo būseną (fuseki/, ssl/, secrets/, uploads/, datasets/owner, datasets/secretary) — datasets/current/ niekada neliečiamas.
  • Prievadai 81/4443/5443 sutampa su kitų lokalių LDH diegimų (pvz., LinkedDataHub repozitorijos) prievadais — vienu metu gali veikti tik vienas stack'as.
  • Dokumentai naršomi per LDH konteinerius: kiekvienas ETL dokumentas yra dh:Item su sioc:has_container, o konteineriai — LDH CLI sukurti dh:Container dokumentai iš app/ (pvz., https://localhost:4443/admin-units/).

Ką jau galima atsakyti?

Visi rinkiniai užkraunami į atmintį viena komanda ir užklausiami SPARQL'u:

etl/queries/run.sh <užklausa.rq>

Pavyzdys: kas šiuo metu vadovauja Seimo komitetams ir komisijoms, kuri partija juos iškėlė, nuo kada — ir kaip jie atrodo? Viena užklausa kerta šešis failus: asmenis, padalinius, pareigų taksonomiją, partijas, nuotraukas ir Wikidata susiejimus. Narystės su galiojimo intervalais leidžia klausti „kas vadovauja dabar“ — imamos tik narystės be pabaigos datos:

PREFIX foaf:  <http://xmlns.com/foaf/0.1/>
PREFIX org:   <http://www.w3.org/ns/org#>
PREFIX skos:  <http://www.w3.org/2004/02/skos/core#>
PREFIX time:  <http://www.w3.org/2006/time#>
PREFIX ltlod: <http://linkeddata.lt/ns#>

SELECT ?unit ?chair ?party ?since ?photo
FROM <urn:x-arq:UnionGraph>
WHERE
{
    ?membership a org:Membership ;
        org:member ?person ;
        org:organization ?org ;
        org:role ?roleConcept ;
        org:memberDuring ?interval .
    FILTER NOT EXISTS { ?interval time:hasEnd ?end }
    OPTIONAL { ?interval time:hasBeginning/time:inXSDDate ?since }

    ?roleConcept skos:prefLabel ?role .
    FILTER(LANG(?role) = "lt" && CONTAINS(LCASE(STR(?role)), "pirminink"))
    FILTER(!CONTAINS(LCASE(STR(?role)), "pavaduotoj"))

    ?org skos:prefLabel ?unit .
    ?person foaf:name ?chair .
    OPTIONAL { ?person ltlod:nominatedBy/skos:prefLabel ?party }
    OPTIONAL { ?person foaf:depiction ?photo . FILTER(CONTAINS(STR(?photo), "lrs.lt")) }
}
ORDER BY ?unit
Padalinys Pirmininkas Iškėlusi partija Nuo
Antikorupcijos komisija Arvydas Anušauskas Tėvynės sąjunga-Lietuvos krikščionys demokratai 2024-12-05
Aplinkos apsaugos komitetas Linas Jonauskas Lietuvos socialdemokratų partija 2024-11-21
Ateities komitetas Vytautas Grubliauskas Lietuvos socialdemokratų partija 2024-11-21
Audito komitetas Artūras Zuokas Partija „Laisvė ir teisingumas“ 2026-07-15
Europos reikalų komitetas Rasa Budbergytė Lietuvos socialdemokratų partija 2024-11-21

Daugiau klausimų, į kuriuos duomenys jau atsako (visi su užklausomis ir pilnais rezultatais etl/queries/EXAMPLES.md):

  • kurios savivaldybės turi daugiausia gyvenamųjų vietovių ir kaip atrodo jų herbai;
  • kur tiksliai yra bet kuri gatvė (gatvė → vietovė → savivaldybė → apskritis);
  • dabartinė Seimo frakcijų sudėtis su iškėlusiomis partijomis ir nuotraukomis;
  • kiek biudžetinių įstaigų veikia, o kiek išregistruota, pagal teisines formas;
  • kokia dalis objektų jau susieta su Wikidata (CONSTRUCT pavyzdys papildomai parodo, kaip iš grafo sugeneruoti schema.org profilius kitoms sistemoms).

Ateities darbai

Publikavimas. Lokalus LinkedDataHub diegimas jau yra — žr. Publikavimas su LinkedDataHub. Lieka produkcinis diegimas https://linkeddata.lt/ adresu (rinkiniai bazei neutralūs — santykinės URI — tad tuos pačius datasets/current/ failus užtenka užkrauti su produkcine .env baze; perkurti nereikia).

Nauji rinkiniai (integracijos taškai jau paruošti — žr. „kaip pridėti“ žemiau):

  • Adresų registro adresai ir jų koordinatės (~1 mln. taškų; locn:Address + GeoSPARQL) — administraciniai vienetai reprezentacines koordinates ir supaprastintas ribų geometrijas jau turi (geo:lat/geo:long, gsp:asWKT), lieka adresų lygmens tikslumas; įstaigų registruotos buveinės jau susietos su administraciniu vienetu (locn:adminUnit; JAR Buveine ⋈ AR Pastatas per aob_kodas, SEMIC org:hasRegisteredSite/locn:Address grandinė) — lieka tikslūs adresai ir smulkesni (seniūnija/vietovė/gatvė) ryšiai;
  • pilnas JAR (~540 tūkst. juridinių asmenų — dabar tik biudžetinės įstaigos);
  • VRK rinkimų duomenys (kandidatai, rezultatai) — atnaujintų 2012 m. archyvą;
  • viešieji pirkimai su ES ePO ontologija;
  • švietimo įstaigos, interesų deklaracijos (reikės savo žodyno).

Žodynų plėtra: apskritys jau turi tiesioginį skos:exactMatch į NUTS3 (savivaldybėms — LAU — dar lieka); Core Person terminai atsiradus asmenų gimimo datoms; belyčiai pareigų konceptai (dabar „pirmininkas“/„pirmininkė“ — atskiri konceptai, kaip šaltinyje).

Kaip pridėti naują rinkinį: sukurti etl/<domenas>/ su Makefile, fetch žingsniu ir LDH stiliaus mappings/*.rq (žr. etl/admin-units/ kaip šabloną); papildyti etl/URI-SCHEME.md konteineriu ir natūralaus rakto taisykle; jei objektai turi atitikmenis Wikidata — pridėti domeną į etl/tools/src/ltlod_etl/reconcile.py. Žodynams galioja kaskada ES → W3C → savas (http://linkeddata.lt/ns#).

Duomenų aktualumas ir patikimumas

datasets/current/ atspindi šaltinių būseną paskutinio ETL paleidimo metu — kada tai buvo, matyti tų failų git istorijoje; make visada sugeneruoja šviežią versiją.

Tai išvestinis, neoficialus rinkinys: autoritetingi šaltiniai lieka valstybės registrai ir Seimo kanceliarija. Wikidata susiejimai daromi automatiškai (deterministinės atitiktys pagal kodus ir etiketes) — nesusieti objektai fiksuojami peržiūros ataskaitose (etl/*/cache/unmatched*.csv), tačiau pavienės klaidingos atitiktys galimos. Radę klaidą — praneškite per GitHub issues.

Licencija

  • Kodas (ETL, užklausos, įrankiai) — Apache-2.0.
  • Sugeneruoti duomenys (datasets/current/) — CC BY 4.0, kaip ir šaltiniai: Adresų registro ir JAR duomenys © Registrų centras / Valstybės duomenų agentūra per get.data.gov.lt (CC BY 4.0), Seimo duomenys © Seimo kanceliarija (CC BY 4.0), susiejimai su Wikidata (CC0). Naudodami duomenis nurodykite šiuos šaltinius.
  • Seimo narių portretai neplatinami šiame repozitorijuje — duomenyse tik nuorodos (foaf:depiction) į lrs.lt ir Wikimedia Commons originalus.

Klausimai, idėjos, klaidos, nauji duomenų šaltiniai — laukiami per GitHub issues ir pull requests (žr. „Kaip pridėti naują rinkinį“) arba martynas@atomgraph.com.