D2R Server per mappare e importare ontologie da DB relazionali

I parte: Primi passi con D2Rdi

In questa serie dedicata ai temi del semantic web, presentiamo un tool come D2R Server che consente di 'acquisire' una sorgente relazionale, esaminarne i dati e mapparli rispetto a modelli ontologici. Nel corso delle varie puntate vedremo come è possibile effettuare questo mapping, presentando anche dei semplici esempi pratici.

Introduzione a D2R Server

D2R Server è un un tool che permette il wrapping di qualsiasi sorgente relazionale e di mapparne i dati rispetto a modelli ontologici. In pratica D2R Server, data una ontologia di mapping (un file .n3), permette di interrogare un DB relazionale connesso via JDBC, proprio come se fosse una ontologia, tramite un end point SPARQL rispetto ad un modello ontologico specifico.

Oltre all'interrogazione, D2R  permette di consultare i dati stessi del DB via web in modalità LinkedData o di generare un dump RDF/OWL da utilizzare per tool come SWED che si basano su file.

Figura 1 - Ecco, in questo schema generale, il modo in cui D2R Server è in grado di mappare i dati relazionali a modelli ontologici.

 

Un ruolo centrale nell'architettura lo ricopre quindi il file di mapping. Questo file non è altro che una ontologia OWL scritta usando i costrutti di un apposito linguaggio chiamato D2RQ [1] usato per mappare elementi relazionali (tabelle, colonne, id, join e così via) su elementi ontologici (classi, relazioni, URI, tipi XSD, etc.).

È quindi qui che risiede tutta la logica di mappatura dei dati presenti nelle tabelle del DB verso istanze di un modello ontologico già esistente o generato al momento. La complessità di questo mapping è direttamente proporzionale alla complessità del DB e alla quantità di informazioni/relazioni che si vogliono generare a partire dal DB. Sempre nello stesso file poi vengono racchiuse le parti di configurazione del server e di connessione al DB.

D2R inoltre è un set di utilissime API che possono essere usate programmaticamente via JAVA.

Risorse per l'esempio

Nel file allegato "Materiali.zip" (menu a destra) si trovano i materiali necessari per poter replicare gli esempi che saranno illustrati nel corso dei vari articoli. L'idea dell'esempio è quella di integrare descrizioni di Progetti e relativi Responsabili presenti in un DataBase esterno con le informazioni sui Requisiti e i Test-case descritti in un foglio elettronico. In particolare, i materiali sono costituiti da due sorgenti dati da mappare, in formato Access e Excel ("Progetti.accdb" e "Requisiti.xlsx"), da un modello ontologico OWL esterno ("modello_esempio.owl") e da un file di mapping preconfigurato ("D2R_UnionMapping_Prog_e_Req.n3").

Oltre a questo, occorre, ovviamente, il Server D2R che può essere scaricato da web (ultima versione)

http://sourceforge.net/projects/d2rq-map/files/D2R%20Server/

Il file di mapping

Una volta scaricato il server, il primo step da seguire per iniziare un mapping è quello di scrivere un nuovo mapping-file. Come già anticipato, questo file rappresenta l'unico input per D2R e descrive quattro parti principalmente:

  • prefissi e namespace usati
  • configurazione del server
  • configurazione e connessione al DB
  • mapping vero e proprio

Un mapping-file non è altro che una ontologia OWL/RDF in formato .n3 che istanzia concetti definiti in D2RQ (i costrutti del linguaggio). Come tale, ha la struttura tipica di un .n3 con prefissi, namepsace e statement RDF di configurazione e mapping. Di seguito vediamo nel dettaglio le varie parti.

Prefissi e namespace

All'inizio del file N3 vengono specificati i prefissi usati. Alcuni sono prefissi indispensabili come quelli rdf, rdfs, owl, d2rq, etc., altri sono prefissi che possiamo aggiungere noi in funzione del fatto che ci riferiamo a delle ontologie esterne. Si noti che non si tratta di importare nulla ma solo di specificare le associazioni fra prefissi e namespace di ontologie usate.

Nel caso dell'esempio si vogliono creare istanze di progetti, requisiti, test-case e valorizzare relazioni e proprietà tutte descritte nell'ontologia specfifiche.owl, identificata univocamente dal namespace http://www.imolinfo.it/ontologie/esempio_corso/specifiche#. Specificando un prefisso associato a questo namespace siamo autorizzati a referenziare i concetti definiti in quell'ontologia per creare il mapping rispetto al DB e all'Excel (p.e.: spec-m:RequisitoFunzionale). Servono anche altri namespace che sono importati da specifiche.owl.

Di seguito mostriamo la lista dei prefissi usati (e quindi dei namespace) nel mapping-file di esempio:

@prefix :         .
@prefix d2r: .
@prefix d2rq:    .
@prefix foaf:    .
@prefix doap:    .
@prefix jdbc:    .
@prefix owl:     .
@prefix rdf:     .
@prefix rdfs:    .
@prefix spec-m:  .
@prefix vocab:   .
@prefix xsd:     .
@prefix skos:    .

Con questi prefissi, potremo usare riferimenti del tipo: d2rq:Database, d2rq:column, map:Persona, spec-m:RequisitoNonFunzionale, rdfs:comment, foaf:firstName, etc.

Il prefisso vuoto (@prefix : ) rappresenta il namespace di base dell'ontologia generata e quindi, tutte le istanze create con uriPattern relativi saranno del tipo :qualcosa, con URI assoluto

http://www.imolinfo.it/ontologie/corso_infocert/istanze#qualcosa

Configurazione del server

La prima cosa che solitamente viene riportata (l'ordine non ha importanza in quanto è una ontologia e non un file di configurazione o un descriptor con uno schema predefinito) sono i parametri di configurazione del server [2].

<> 
       rdf:type d2r:Server ;
       rdfs:label "D2R Server" ;
       d2r:baseURI ;
       d2r:autoReloadMapping "false"^^xsd:boolean ;
       d2r:documentMetadata
             [ rdfs:comment "This comment is custom document metadata."
             ] ;
       d2r:port 2020 .

Nella configurazione di esempio troviamo un riferimento a una entità anonima <> che è il modo con cui D2R riconosce la configurazione per il server. Le proprietà di questa istanza di d2r:Server sono di fatto i parametri di configurazione del server stesso e quelli davvero importanti sono:

  • rdfs:label "D2R Server", è il nome del server e serve solo per la leggibilità dell'ontologia;
  • d2r:baseURI http://localhost:2020/>, è l'URL su cui viene lanciato il server e a cui si dovrà andare per navigare con linkedData ed effettuare le query SPARQL;
  • d2r:port 2020, indica la porta su cui viene lanciato il server.

Configurazione e connessione al DB

All'interno del mapping file possono essere definite più sorgenti relazionali da mappare. Questo perche' ogni connessione a DB è di fatto una istanza di d2rq:Database e quindi è possibile definire molteplici istanze di database e riferirle singolarmente all'interno del file per contestualizzare i mapping.

Una nota a tal proposito. Quanto detto significa che in linea di principio si potrebbe esporre un end-point SPARQL su cui effettuare query in maniera trasparente rispetto al numero di diverse sorgenti connesse come se fosse un'unica ontologia/grafo. Ciò al momento però non è completamente vero in quanto nella modalità server live (end-point SPARQL, appunto), alcune query SPARQL che vengono mappate in query SQL cross DB non funzionano. Questo è un limite attuale che gli sviluppatori di D2R Server stanno cercando di superare. Il problema invece non sussiste effettuando un Dump, cosa che vedremo nel terzo articolo di questa serie.

Di seguito riportiamo le due configurazioni presenti nel mapping file D2R_Union_Mapping_Prog_e_Req.n3 che definiscono rispettivamente due connessioni JDBC-ODBC verso un file Access e un file Excel.

###### Connessione JDBC-ODBC al DB Access dei Progetti ######
map:databaseProg rdf:type d2rq:Database ;
       d2rq:jdbcDSN "jdbc:odbc:Progetti" ;
       d2rq:jdbcDriver "sun.jdbc.odbc.JdbcOdbcDriver";
.
###### Connessione JDBC-ODBC al file Excel dei Requisiti ######
map:databaseReq a d2rq:Database;
       d2rq:jdbcDriver "sun.jdbc.odbc.JdbcOdbcDriver";
       d2rq:jdbcDSN "jdbc:odbc:Requisiti";
       d2rq:textColumn "Requisiti$.Tipo";
       d2rq:textColumn "Requisiti$.Codice";
       d2rq:textColumn "Requisiti$.Titolo";
       d2rq:textColumn "Requisiti$.Descrizione";
       d2rq:textColumn "Requisiti$.IdProgetto";
       d2rq:textColumn "TestCase$.Requisito";
       d2rq:textColumn "TestCase$.IdTest";
       d2rq:textColumn "TestCase$.Input";
       d2rq:textColumn "TestCase$.Output_atteso";
       .

Altra nota importante: nella serializzazione N3 di RDF, "rdf:type" e "a" sono equivalenti e specificano entrambi la classe (il tipo) dell'istanza (p.e.: map:databaseReq o map:databaseProg) che si sta definendo.

La lista completa dei parametri di configurazione per la connessione si trova online all'indirizzo riportato nel riferimento [3]. Di seguito riportiamo solo i parametri principali:

  • d2rq:jdbcDSN "jdbc:odbc:Progetti", specifica l'URL di connessione al DB (p.e.: nel caso di MySQL per esempio potrebbe essere qualcosa del tipo "jdbc:mysql://localhost/iswc")
  • d2rq:jdbcDriver "sun.jdbc.odbc.JdbcOdbcDriver", specifica la classe del driver JDBC (p.e.: per MySQL è "com.mysql.jdbc.Driver")
  • d2rq:username "user", specifica il nome utente per la connessione (se richiesto);
  • d2rq:password "password", specifica la password di connessione (se richiesta);
  • d2rq:textColumn "Requisiti$.Codice", nel caso il DB per qualche motivo non permetta di avere informazioni sul tipo delle colonne (p.e.: Excel) è possibile esplicitare il tipo tramite testo, numerico, data o timestamp.

Mapping vero e proprio

Il mapping effettivo consiste essenzialmente nella definizione di due tipi di oggetti: ClassMap e PropertyBridge associati.

Definizione di d2rq:ClassMap

Un d2rq:ClassMap è di fatto l'oggetto che specifica il mapping rispetto ad un certo d2rq:Database associando tutti gli identificativi delle istanze a una particolare classe del modello ontologico. A ogni ClassMap possono essere associati più PropertyBridge. Per una spiegazione approfondita di tutti i parametri di ClassMap si faccia riferimento alla documentazione ufficiale.

Di seguito, prendiamo in esame dal nostro esempio il ClassMap definito a partire dal databaseReq (il file Excel) in maniera condizionale ed esplicitando la classe di appartenenza e l'uriPattern (ID) di ogni istanza che verrà generata.

map:Requisito_fun a d2rq:ClassMap;
       d2rq:dataStorage map:databaseReq;
       d2rq:condition "Requisiti$.Tipo = 'fun'" ;
       d2rq:uriPattern "requisito-@@Requisiti$.Tipo@@_@@Requisiti$.Codice@@";
       d2rq:class spec-m:RequisitoFunzionale;
       .

Come si può notare map:Requisito_fun è una istanza di d2rq:ClassMap (map:Requisito_fun a d2rq:ClassMap;). Ciò ovviamente serve a D2R in fase di mapping per sapere come trattare questo elemento di mappping e i suoi attributi. I parametri usati sono:

  • d2rq:dataStorage map:databaseReq, specifica a quale d2rq:Database fare riferimento (e quindi quale connessione JDBC usare per fare le query);
  • d2rq:condition Requisiti$.Tipo = 'fun', specifica una condizione rispetto al valore di una certa colonna di una certa tabella. In questo caso considera tutte e sole le righe della tabella Requisiti$ (corrispondente al foglio Requisiti del file di Excel) in cui la colonna Tipo vale ‘fun'.
  • d2rq:uriPattern "requisito-@@Requisiti$.Tipo@@_@@Requisiti$.Codice@@", permette di specificare il pattern per la creazione dinamica degli ID di queste istanze. È possibile specificare del testo costante e inserire i valori variabili derivanti dal valore di una colonna per ogni riga presa in esame di quella tabella. In questo caso, per esempio, compone un ID (ossia il localName all'interno del namespace target http://www.imolinfo.it/ontologie/corso_infocert/istanze#) fatto da un testo fisso "requisito-" e concatenazione con "_" dei valori variabili Requisiti$.Tipo e Requisiti$.Codice. I caratteri "@@" sono caratteri speciali che fungono da delimitatori (apertura e chiusura) dei riferimenti alle colonne delle tabelle. Un esempio di un ID generato è requisito-fun_100.
  • d2rq:class spec-m:RequisitoFunzionale, specifica la classe di cui generare le istanze. Ciò fa si che nel dump RDF si abbia qualcosa del genere:
:requisito-fun_100 rdf:type spec-m:RequisitoFunzionale

Nota su RDF: in questo caso gli ID vengono generati come Relativi, ossia riferiti al namespace base

http://www.imolinfo.it/ontologie/corso_infocert/istanze#

e ciò significa che gli URI assoluti di queste istanze saranno del tipo

http://www.imolinfo.it/ontologie/corso_infocert/istanze#requisito-fun_100

Nell'uriPattern è anche possibile generare Uri assoluti nel seguente modo:

d2rq:uriPattern "http://www.conference.org/conf02004/paper#Paper@@Papers.PaperID@@";

Nota su D2R e riferimenti a tabelle: per i riferimenti alle tabelle e colonne, come si è detto, nei pattern vanno inseriti sempre fra @@...@@. Se si ha a che fare con un normale DB la sintassi è quella canonica @@NOME_TABELLA.NOME_COLONNA@@ mentre se si sta mappando rispetto ad un Excel è necessario usare il simbolo $ concatenato al nome della tabella nel seguente modo: @@NOME_TABELLA$.NOME_COLONNA@@

Definizione di d2rq:PropertyBridge

ClassMap permette solo di definire la modalità di generazione (condizionale o non) degli identificatori delle istanze e delle associazioni rispetto alle classi di modello. Per valorizzare poi le proprietà delle istanze create rispetto alle proprietà/relazioni del modello è necessario associare al ClassMap delle PropertyBridge.

In pratica, un PropertyBridge è un elemento del mapping che dichiara come valorizzare una certa proprietà di modello (sia owl:DatatypeProperty che owl:ObjectProperty) per le istanze di una certa classe (associata al ClassMap) e in funzione di regole condizionali, join ed eventuali espressioni SQL per i mapping più complessi. Per un approfondimento sui parametri da usabili per definire un PropertyBridge si veda la documentazione relativa [8].

Di seguito analizziamo alcuni dei parametri principali usati nel caso dell'esempio. Consideriamo il seguente ClassMap per la generazione delle istanze di foaf:Person a partire dalla tabella Responsabili del DB Access Progetti.accdb:

map:Persona a d2rq:ClassMap;
       d2rq:dataStorage map:databaseProg;
       d2rq:uriPattern "person-@@Responsabili.ID@@";
       d2rq:class foaf:Person;
       .

Questo genera istanze di persone con URI relativo nel seguente modo:

:person-3 rdf:type foaf:Person .

Il seguente PropertyBridge associato a map:Persone è abbastanza semplice e serve a valorizzare la proprietà foaf:firstname che è una owl:DatatypeProperty e quindi a valori di tipo semplice (string in questo caso)

map:Persona_firstName
       rdf:type d2rq:PropertyBridge ;
       d2rq:belongsToClassMap map:Persona ;
       d2rq:column "Responsabili.Nome" ;
       d2rq:datatype xsd:string ;
       d2rq:property foaf:firstName;
       .

Descriviamo i parametri usati:

  • d2rq:belongsToClassMap map:Persona, dichiara l'appartenenza ad una o più ClassMap. Una PropertyBridge infatti può essere usata per più ClassMap. Per esempio, per generare il rdfs:comment di due classi le cui istanze vengono dalla stessa tabella, come accade nel nostro esempio, per map:Requisito_fun e map:Requisito_nfun usiamo lo stesso Property Bridge configurato nel seguente modo:
map:Requisito_Comment
       rdf:type d2rq:PropertyBridge ;
       d2rq:belongsToClassMap map:Requisito_fun, map:Requisito_nfun ;
       d2rq:column "Requisiti$.Descrizione" ;
       d2rq:datatype xsd:string ;
       d2rq:property rdfs:comment .
  • d2rq:column "Responsabili.Nome", nel caso non sia necessario creare un uriPattern (cioè un riferimento a un altra istanza) e il valore della colonna sia già sufficiente per valorizzare la property, basterà specificare il nome della TABELLA.COLONNA col parametro d2rq:column (senza bisogno di @@...@@ in quanto non è un pattern e quindi deve per forza essere solo un riferimento a colonna di tabella).
  • d2rq:datatype xsd:string, nel caso di owl:DatatypeProperty è possibile anche fare il casting preciso del valore rispetto al rdfs:range della property da valorizzare (si usano i datatype di XSD).
  • d2rq:property foaf:firstName, il riferimento alla property del modello da valorizzare.

Vediamo ora un PropertyBridge più complesso per una owl:ObjectProperty (ossia un a proprietà che punta a un'altra istanza tramite un URI). Il seguente PropertyBridge valorizza la proprietà foaf:currentProject per la classe foaf:Persona, popolata tramite il ClassMap visto sopra (map:Persona). Questa proprietà lega una istanza di foaf:Person con uno o più progetti che sta correntemente seguendo.

map:Persona_current_project
       rdf:type d2rq:PropertyBridge ;
       d2rq:belongsToClassMap map:Persona ;
       d2rq:join "Responsabili.ID <= Progetti.Responsabile" ;
       d2rq:property foaf:currentProject ;
       d2rq:uriPattern "progetto-@@Progetti.ID@@" .

In questo caso si vede come il valore di una proprietà possa essere ottenuto anche tramite operazioni di join fra le tabelle. Esaminiamo i parametri nuovi:

  • d2rq:join "Responsabili.ID <= Progetti.Responsabile", permette di definire un join fra due colonne di tabelle specificando anche la direzione (PrimaryKey <= ForeignKey). In questo modo lego i valori della tabella principale da cui il ClassMap prende le istanze (nell'esempio la tabella Responsabili) con quelli di un'altra tabella legata tramite foreign key (nell'esempio Progetti) e posso fare riferimento ai campi dell'altra tabella per la valorizzazione della property di modello. In questo caso specifico, ho legato tutte le righe della tabella Responsabili (che è quella usata da map:Person per generare le istanze) con le righe della tabella Progetti tramite il join e quindi posso andare a leggere l'id del progetto associato per creare l'uriPattern relativo (ossia il riferimento a una istanza di progetto creata con map:Progetti).
  • d2rq:property foaf:currentProject, il nome della proprietà di modello da valorizzare.
  • d2rq:uriPattern "progetto-@@Progetti.ID@@", l'uriPattern per la creazione dell'URI di riferimento all'istanza relativa (in questo caso relativa a un spec-m:ProgettoSoftware).

Va notato quanto segue a riguardo della coerenza degli d2rq:uriPattern: quando si valorizza una proprietà ObjectProperty quindi che punta tramite un URI a un'altra istanza generata da un altro ClassMap si deve essere coerenti con lo stesso pattern usato nel ClassMap. Esempio: se nel ClassMap map:Progetti ho specificato che le istanze hanno un id generato tramite l'uriPattern "progetto-@@Progetti.ID@@" allora il propertyBridge di esempio usa lo stesso pattern in virtù del fatto che tramite il join è stato collegato alla tabella Progetti (sarebbe errato un uriPattern).

Conclusioni

Terminiamo qui la prima parte della serie dedicata a D2R Server, in cui abbiamo presentato le caratteristiche principali del problema del mapping tra dati relazionali e modelli ontologici. Nel prossimo articolo continueremo la trattazione, affrontando in particolare la gestione del modello e l'uso del server online.

Riferimenti

[1] Il linguaggio D2RQ

http://d2rq.org/d2rq-language

 

[2] I dettagli per la configurazione del server D2R

http://d2rq.org/d2r-server#configuration

 

[3] Parametri di configurazione per la connessione

http://d2rq.org/d2rq-language#database

 

[4] Un tutorial abbastanza completo sull'uso di D2R Server con un DB MySQL

http://sw.cs.technion.ac.il/d2rq/tutorial

 

[5] Guida per connettere una sorgente relazionale mappata tramite D2R con l'endpoint JOSEKI 2

http://www4.wiwiss.fu-berlin.de/bizer/d2rmap/usecases/joseki/D2R4joseki2.pdf

 

[6] D2R/Update Server, un tutorial sull'uso di D2R Server per effettuare query con SPARQL Update e quindi andare in scrittura sul DB

http://d2rqupdate.cs.technion.ac.il/tutorial

 

[7] SPARQL 1.1 Update. W3C Working Draft

http://www.w3.org/TR/2009/WD-sparql11-update-20091022/

 

[8] Le proprietà di d2rq:PropertyBridge

http://d2rq.org/d2rq-language#propertybridge

 

 

Condividi

Pubblicato nel numero
177 ottobre 2012
Nato a Imola nel 1978, ha conseguito la laurea Specialistica in informatica nel 2005 presso l‘Università di Bologna con una tesi sull‘"Estrazione di Ontologie da Framework standardizzati EDI/XML". Per tre anni ha lavorato come ricercatore presso il centro ENEA di Bologna seguendo progetti sull‘applicazione di tecnologie semantiche a framework e…
Articoli nella stessa serie
Ti potrebbe interessare anche