Is it possible to use prefixes for template definition in RML/SPARQL mapping? - sparql

I'm trying to map tabular data into RDF using RML mapping.
I've figured out how to define and use prefixes for rr:constant definitions as indicated with the <<--- arrows in the code below. I've also figured out how to map column values using rr:template, as indicated with the <<<<<< arrow in the same code.
#prefix rr: <http://www.w3.org/ns/r2rml#>.
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
#prefix ex: <http://example.org/>.
[...]
:map_001 rr:predicateObjectMap [
rr:predicate rdf:type; # <<---
rr:objectMap [
rr:constant ex:MyClass; # <<---
rr:termType rr:IRI
]
];
rr:predicateObjectMap [
rr:predicate ex:myPredicate; # <<---
rr:objectMap [
rr:template "http://example.org/{some_column}" # <<<<<<
]
].
My question is: is it possible to somehow use prefixes in rr:template definitions, in order to not have to explicitly write the complete base URI? For example, I'd like to do something like what is shown below, although this clearly doesn't work:
:map_001 rr:predicateObjectMap [
rr:predicate ex:myPredicate;
rr:objectMap [
rr:template ex:"{some_column}" # <<--- DOESN'T WORK!
]
].
Is there any syntax for this, or is it simply not possible?

Related

SPARQL: How to retrieve a 1:N relationship?

After learning the basics of SPARQL I'm still trying to make sense of 1:N relationships. How can I retrieve an object with all its relationships as a single record?
For example, I have a Project linked to two Topics. And I try to retrieve it with:
SELECT ?projName ?topic ?topicName {
?proj hasName ?projName .
?proj hasTopic ?topic .
?topic hasName ?topicName .
FILTER (?proj = <$uri>) .
}
But what I get is:
result: [
[
projName: "My Project"
topic: "TOPIC1_URI"
topicName: "First Topic"
],
[
projName: "My Project"
topic: "TOPIC2_URI"
topicName: "Second Topic"
]
]
But I would want to get it as:
result: [
projName: "My Project"
topics: [
[
topic: "TOPIC1_URI"
topicName: "First Topic"
],
[
topic: "TOPIC2_URI"
topicName: "Second Topic"
]
]
]
How could I achieve this? I don't know what I'm missing but I don't see how to do this with SPARQL.
Thanks a lot in advance
As you can read here, the result of a SELECT SPARQL query is a set of bindings, i.e., assignments of values to the free variables of the query. You can think of such bindings as a matrix or a table, like for SQL queries, whose attributes are the variables' names. But you can't arrange such variables bindings as you wish if you have just a matrix for representing them.
What you can do is to collect all data about topics in a single variable using the GROUP_CONCAT function. For example:
SELECT
?projName
(GROUP_CONCAT(?topicData; separator=", ") AS ?topics)
WHERE {
?proj hasName ?projName .
?proj hasTopic ?topic .
?topic hasName ?topicName .
FILTER (?proj = <$uri>) .
BIND(CONCAT(?topic, ": ", ?topicName) AS ?topicData)
}
GROUP BY ?projName
But remember that the values assigned to ?topics will be strings, not JSON arrays:
result: [
projName: "My Project"
topics: "TOPIC1_URI: First Topic, TOPIC2_URI: Second Topic"
]
Clearly you can choose other separators than ": " and ", ".

R2RML Blank Node within rr:objectMap

I was wondering how I could model the following with r2rml:
Person -> has an address --> Blank Node [ Street Name, Postal Code, City ]
I'm note sure how I can add street name, postal code and city to the blank node within the rr:objectMap
(Additional question: Is a rr:class mandatory for a rr:BlankNode?)
Any suggestions? :)
<#Person>
rr:logicalTable [ rr:tableName "PERSON" ];
rr:subjectMap [
rr:template "http://ex.com/data/PersonClass/{ID}";
rr:class ex:PersonClass;
];
rr:preciateObjectMap [
rr:predicate ex:hasAddress;
rr:objectMap [
rr:termType rr:BlankNode;
## How/where can a add the street name, postal code, city? ##
];
].
Should be not too difficult. First you take the R2RML mapping you have created and create a blank node for the address. Give it a unique name by using a template, but do not give it an IRI so it is interpreted as a blank node.
<#Person>
rr:logicalTable [ rr:tableName "PERSON" ];
rr:subjectMap [
rr:template "http://ex.com/data/PersonClass/{ID}";
rr:class ex:PersonClass;
];
rr:preciateObjectMap [
rr:predicate ex:hasAddress;
rr:objectMap [
rr:template "BlankAddressNode{ADDRESSID}";
rr:termType rr:BlankNode;
];
].
Note: ADDRESSID in table PERSON is considered a foreign to the primary key of ADDRESS table.
Next you create the blank node with rdf:type and everything else.
<#Address>
rr:logicalTable [ rr:tableName "ADDRESS" ];
rr:subjectMap [
rr:template "BlankAddressNode{ID}";
rr:termType rr:BlankNode;
rr:class ex:AddressClass;
];
rr:predicateObjectMap [
rr:predicate ex:street;
rr:objectMap [ rr:column "Street"]
];
.
Note: ID is primary key of ADDRESS table.
You can do this with a join too... but I think from a tutorial point of view this is clearer.

Conditional creation of property in R2RML

I'm playing around with R2RML and I was wondering if I can create a property depending on the content of a RDB table cell.
The D2RQ mapping language has d2rq:condition that can handle that.
e.g.:
if value in column/table cell 'name' is 'abc' create property 'abc'
rr:predicateObjectMap [
rr:predicate ex:abc
rr:objectMap [
rr:column "name";
rr:datatype xsd:string;
# equivalent for d2rq:condition "name='abc'"
];
]
if value in column/table cell 'name' is 'xyz' create property 'xyz'
rr:predicateObjectMap [
rr:predicate ex:xyz
rr:objectMap [
rr:column "name";
rr:datatype xsd:decimal;
# equivalent for d2rq:condition "name='xyz'"
];
];
I couldn't find any suggestion in W3C's R2RML Recommendation.
Any ideas? :-)
Update:
I had the idea of using rr:sqlQuery
e.g.
rr:SQLQuery """
select (case TABLENAME.COLUMNNAME
when 'this' then 'propertyOne'
when 'that' then 'propertyTwo'
end) as VARIABLE_PREDICATE
from TABLENAME """;
and apply it to a rr:predicate or rr:predicateMap with
rr:predicateObjectMap [
rr:predicateMap [ rr:template "ex:{VARIABLE_PREDICATE}" ];
rr:objectMap [ rr:column "COLUMNNAME"; ];
];
But that didn't work. I guess predicateMaps can be rr:constants only and not rr:templates :( . At least the W3C Recommendation just shows constants within predicateMap.
Still searching for a solution... :/
P.S. I'm disappointed that a proprietary language like d2rq seems to be more powerful (at this point).
R2RML doesn't have conditional properties (like in D2RQ). The design was done on purpose in order not to complicate the language. Any type of "complex" mapping requires SQL.
A solution is the following:
#prefix rr: <http://www.w3.org/ns/r2rml#>.
<#Mapping> a rr:TriplesMap;
rr:logicalTable [ rr:SQLQuery """
select id, COLUMNNAME, (case TABLENAME.COLUMNNAME
when 'this' then 'http://ex.com/propertyOne'
when 'that' then 'http://ex.com/propertyTwo'
end) as VARIABLE_PREDICATE
from TABLENAME """; ];
rr:subjectMap [
rr:template "http://ex.com/foo/{id}";
];
rr:predicateObjectMap [
rr:predicateMap [ rr:column "VARIABLE_PREDICATE" ];
rr:objectMap [ rr:column "COLUMNNAME" ];
].
We routinely do that in mapping the Getty vocabs, for props that depend on key values (flags). Eg
<#ContribTermRelPreferred>
a rr:TriplesMap;
rr:logicalTable [ rr:sqlQuery """
SELECT ...
UDF_LOD_LOOKUP_PROPERTY('contrib_rels_term','preferred',CRT.PREFERRED) CONTRIBPREF
""" ];
rr:predicateObjectMap [
rr:predicateMap [ rr:column "CONTRIBPREF" ];
rr:objectMap [ rr:template "http://vocab.getty.edu/aat/contrib/{CONTRIB_ID}" ];
].

SPARQL update with optional parts

Consider the following SPARQL update:
INSERT {
?performance
mo:performer ?performer ; # optional
mo:singer ?singer ; # optional
mo:performance_of [
dc:title ?title ; # mandatory
mo:composed_in [ a mo:Composition ;
mo:composer ?composer # optional
]
]
}
WHERE {}
If I do not provide values (e.g. in Jena's ParameterizedSparqlString.setIri() for ?performer, ?singer, or ?composer, this update won't insert statements with the corresponding objects, which is as intended.
But how can I suppress [] a mo:Composition as well if ?composer is missing. Creating it in a second INSERT whose WHERE filters on ISIRI(?composer) doesn't seem to be an option because that INSERT won't know the blank node that has already been created by the first one.
So how can I support this kind of optional parameters in a single SPARQL update? E.g., is there any means for "storing" the blank node between two INSERTs?
The following seems to work, when the caller sets composition to a blank node if and only if it sets ?composer to an IRI.
if (composer != null) {
parameterizedSparqlString.setIri ("composer" , composer);
parameterizedSparqlString.setParam("composition", NodeFactory.createAnon());
}
INSERT {
?performance
mo:performer ?performer ; # optional
mo:singer ?singer ; # optional
mo:performance_of [
dc:title ?title ; # mandatory
mo:composed_in ?composition ] . # optional
?composition a mo:Composition ;
mo:composer ?composer .
}
WHERE {}
Hats off to #Joshua Taylor for the lead.
I'd still prefer a self-contained version that does not require the additional parameter ?composition (i.e. works without making additional demands on the caller), if that's possible at all.

Searching strings for a partial match in sparql

Suppose I have an RDF graph that looks like the following:
entity1 [
title [ obect1.svg]
description [
"This is sentence 1. This is sentence 2." ]
] .
entity2 [
title [ obect2.svg]
description [
"This is sentence 3. This is sentence 4." ]
].
entity3 [
title [ obect3.svg]
description [
"This is sentence 1. This is sentence 4." ]
] .
How would I write a query to find This is sentence 2?
See http://www.w3.org/TR/sparql11-query/#func-strings
Functions REGEX or CONTAINS.