Solution to exercises on mappings

1. Direct mappings

<store.customer.id/1> rdf:type <store.customer> ;
  <store.customer.name> "Kari" .

<store.customer.id/2> rdf:type <store.customer> ;
  <store.customer.name> "Peter" .

<store.product.pid/1> rdf:type <store.product> ;
  <store.product.name> "Milk" ;
  <store.product.price> 0.8 .

<store.product.pid/2> rdf:type <store.product> ;
  <store.product.name> "Apple" ;
  <store.product.price> 2.1 .

<store.product.pid/3> rdf:type <store.product> ;
  <store.product.name> "Laptop" ;
  <store.product.price> 120.9 .

[] rdf:type <store.orders> ;
  <store.orders.customer> <store.customer.id/1> ;
  <store.orders.product> <store.product.pid/2> .

[] rdf:type <store.orders> ;
  <store.orders.customer> <store.customer.id/1> ;
  <store.orders.product> <store.product.pid/3> .

[] rdf:type <store.orders> ;
  <store.orders.customer> <store.customer.id/2> ;
  <store.orders.product> <store.product.pid/2> .

2. Direct mappings with Triplelore

IMPORT 'http://leifhka.org/lore/library/direct_mappings.lore';

mappings.direct_mapping('store', 'customer', 'http://example.org/', 'ex', true);
mappings.direct_mapping('store', 'product', 'http://example.org/', 'ex', true);
mappings.direct_mapping('store', 'orders', 'http://example.org/', 'ex', true);

mappings.primary_key('store', 'customer', 'id');
mappings.primary_key('store', 'product', 'pid');
mappings.primary_key('store', 'orders', 'customer');
mappings.primary_key('store', 'orders', 'product');

mappings.foreign_key(1, 'store', 'orders', 'customer', 'store', 'customer', 'id');
mappings.foreign_key(1, 'store', 'orders', 'product', 'store', 'product', 'pid');

Store this in a file, e.g. state_dms.lore, and then execute:

java -jar lore.jar <flags> state_dms.lore
java -jar triplelore.jar -m directmappings <flags> -o dms.lore
java -jar lore.jar <flags> dms.lore

where <flags> are the common database-connection flags. Now your database contains relations representing classes (ex.customer, ex.product, etc.) and properties (ex.customer_name, ex.product_price, etc.).

If you want to query them with SPARQL, execute the following:

java -jar triplelore.jar -m r2rml <flags> -o mappings.ttl
ontop/ontop query --db-url=<url> --db-user=<user> --db-password=<password> -m mappings.ttl -q query.sparql

where <url> is the URL to your database, <user> is the username, <password> is the password and query.sparql is a file containing your SPARQL-query.

3. R2RML and Ontop

R2RML:

@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix ex: <http://example.org/>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix store-o: <http://mystore.com/ont/> .

<#CustomerMap>
    rr:logicalTable [ rr:tableName "store.customer" ] ;
    rr:subjectMap [
        rr:template "http://mystore.com/customer{id}" ;
        rr:class store-o:Customer
    ] ;
    rr:predicateObjectMap [
        rr:predicate rdfs:label ;
        rr:objectMap [
            rr:column "name" ;
            rr:termType rr:Literal ;
            rr:datatype xsd:string
        ]
    ] .

<#ProductMap>
    rr:logicalTable [ rr:tableName "store.product" ] ;
    rr:subjectMap [
        rr:template "http://mystore.com/product{pid}" ;
        rr:class store-o:Product
    ] ;
    rr:predicateObjectMap [
        rr:predicate rdfs:label ;
        rr:objectMap [
            rr:column "name" ;
            rr:termType rr:Literal ;
            rr:datatype xsd:string
        ]
    ] ;
    rr:predicateObjectMap [
        rr:predicate store-o:price ;
        rr:objectMap [
            rr:column "price" ;
            rr:termType rr:Literal ;
            rr:datatype xsd:float
        ] 
    ] .

<#OrdersMap>
    rr:logicalTable [ rr:tableName "store.orders" ] ;
    rr:subjectMap [
        rr:template "http://mystore.com/customer{customer}"
    ] ;
    rr:predicateObjectMap [
        rr:predicate store-o:orders ;
        rr:objectMap [
            rr:parentTriplesMap <#ProductMap>;
            rr:joinCondition [ 
              rr:child "product";
              rr:parent "pid";
            ]
        ]
    ] .

Ontop mappings:

[PrefixDeclaration]
store:      http://mystore.com/
store-o:    http://mystore.com/ont/
rdfs:       http://www.w3.org/2000/01/rdf-schema#
xsd:        http://www.w3.org/2001/XMLSchema#

[MappingDeclaration] @collection [[

mappingId   customerMap
target      store:customer{id} a store-o:Customer ; rdfs:label {name}^^xsd:string . 
source      SELECT * FROM store.customer

mappingId   productMap
target      store:product{pid} a store-o:Product ; rdfs:label {name}^^xsd:string ; store-o:price {price}^^xsd:float. 
source      SELECT * FROM store.product

mappingId   ordersMap
target      store:customer{customer} store-o:orders store:product{product} . 
source      SELECT * FROM store.orders

]]

You can now query the database directly with Ontop:

ontop/ontop query --db-url=<url> --db-user=<user> --db-password=<password> -m <mappings> -q query.sparql

where <mappings> is the file you stored your R2RML or Ontop-mappings in.