LDT templates
This guide explains how to use LDT templates to change the way your application operates
Template is a core concept in an Linked Data Templates application ontology. It defines what SPARQL command gets executed when on the application's service when a certain URI is requested on that application. The service is usually backed by a triplestore.
When Linked Data is served from a triplestore, the RDF descriptions returned when
URIs are dereferenced are often results of the same default SPARQL query template.
A common one is
DESCRIBE ?this
, which returns all known triples about a resource identified here as ?this
. The final query is obtained from this template by setting
the requested URI as the value of the ?this
variable.
Templates allow you to customize this mechanism by only mapping a certain class of URIs to a certain SPARQL command. Moreover, they support write mode as well, by allowing mapping to SPARQL update. This means that different parts of your application's URI address space can change the dataset and respond in different ways when a software client interacts with them. This is a common requirement for real-world end-user applications backed by SPARQL services.
Use case
Lets reuse a geospatial RDF dataset from the CSV import example: any number of countries with coordinates. It could look like this in a Trig syntax (the base URI is not relevant in this context):
@base <https://linkeddatahub.com/demo/city-graph/> @prefix nsdd: <ns/domain/default#> @prefix ns: <ns#> { <countries/AD/> a nsdd:Item ; dct:title "Andorra" ; dh:slug "AD" ; foaf:primaryTopic <countries/AD/#this> . <countries/AD/#this> a ns:Country ; foaf:isPrimaryTopicOf <countries/AD/#this> ; dct:identifier "AD" ; geo:lat 42.5 ; geo:long 1.6 ; dct:title "Andorra" . }
By default, the resource URIs will match a default template, which depends on what LDT ontologies your application imports. But lets say that we want to override it with our own country-specific template, which:
- matches country document resources
- includes descriptions of nearby countries when dereferenced
- removes document as well as country when deleted
Template structure
Use case requirements above translate directly into main LDT template components:
- Match
- Use /countries/{id}/ URI template to match only country document URIs and not others
- Query
- A proper solution would be to use GeoSPARQL here, but for the sake of this example we can retrieve nearby countries by filtering coordinates that are within a bounding box:
-
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> PREFIX dct: <http://purl.org/dc/terms/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> DESCRIBE ?this ?country ?nearbyCountry WHERE { GRAPH ?g { ?this foaf:primaryTopic ?country . ?country geo:lat ?lat ; geo:long ?long OPTIONAL { GRAPH ?nearbyCountryGraph { ?nearbyCountry geo:lat ?nearbyLat ; geo:long ?nearbyLong FILTER ( ?country != ?nearbyCountry ) } } FILTER ( ( ?nearbyLat > ( ?lat - 10 ) ) && ( ?nearbyLat < ( ?lat + 10 ) ) ) FILTER ( ( ?nearbyLong > ( ?long - 10 ) ) && ( ?nearbyLong < ( ?long + 10 ) ) ) } }
- Update
-
PREFIX foaf: <http://xmlns.com/foaf/0.1/> DELETE { GRAPH ?graph { ?this ?p ?o . ?country ?countryP ?countryO . } } WHERE { GRAPH ?graph { ?this ?p ?o OPTIONAL { ?this foaf:primaryTopic ?country . ?country ?countryP ?countryO } } }
- Super-template
- Templates inherit properties from super-templates, to which they must be linked using
the subclass relationship. If you know of an existing template that already defines
the URI
pattern, query/update etc. that you need, you may define your template as a sub-template
of it. For example, an update analogous to the one above is defined on
thgt:Document
template in the THGT ontology.
Execution
Now lets consider GET
and DELETE
requests to our country document URI https://linkeddatahub.com/demo/city-graph/countries/AD/.
The URI will be set as the value of the variable ?this
before the query or update is executed. In other words, a variable binding (?this,
<https://linkeddatahub.com/demo/city-graph/countries/AD/>)
will be applied on the query/update string before execution.
GET
request will invoke execution of this query:
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
DESCRIBE <https://linkeddatahub.com/demo/city-graph/countries/AD/> ?country ?nearbyCountry
WHERE
{ GRAPH ?g
{ <https://linkeddatahub.com/demo/city-graph/countries/AD/> foaf:primaryTopic ?country .
?country geo:lat ?lat ;
geo:long ?long
OPTIONAL
{ GRAPH ?nearbyCountryGraph
{ ?nearbyCountry
geo:lat ?nearbyLat ;
geo:long ?nearbyLong
FILTER ( ?country != ?nearbyCountry )
}
}
FILTER ( ( ?nearbyLat > ( ?lat - 10 ) ) && ( ?nearbyLat < ( ?lat + 10 ) ) )
FILTER ( ( ?nearbyLong > ( ?long - 10 ) ) && ( ?nearbyLong < ( ?long + 10 ) ) )
}
}
The RDF result of the query will be returned as the Linked Data response body.
DELETE
request will invoke execution of this update:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
DELETE {
GRAPH ?graph {
<https://linkeddatahub.com/demo/city-graph/countries/AD/> ?p ?o .
?country ?countryP ?countryO .
}
}
WHERE
{ GRAPH ?graph
{ <https://linkeddatahub.com/demo/city-graph/countries/AD/> ?p ?o
OPTIONAL
{ <https://linkeddatahub.com/demo/city-graph/countries/AD/> foaf:primaryTopic ?country .
?country ?countryP ?countryO
}
}
}