Reputation: 506
I wrote a query for this thesaurus: http://vocabs.ceh.ac.uk/evn/tbl/envthes.evn#http%3A%2F%2Fvocabs.lter-europe.net%2FEnvThes%2F10000
The Sparql endpoint is here: http://vocabs.ceh.ac.uk/evn/tbl/swp?_viewClass=endpoint:HomePage Just select "urn:x-evn-pub:envthes" as the default graph.
It returns every term that is sorted under the term "measure" (http://vocabs.lter-europe.net/EnvThes/10004). It works as desired, but the problem is that it neither elegant nor easy to write like that.
Therefore I am looking for a better way to write the following query:
select distinct ?concept (str(?prefLab) as ?label) (str(?altlab) as ?code)
(str(?p) as ?parent) (str(?pl) as ?parlab) ("EnvThes" as ?source)
WHERE {
?concept <http://www.w3.org/2004/02/skos/core#broader> ?level2.
?concept <http://www.w3.org/2004/02/skos/core#prefLabel> ?prefLab.
OPTIONAL {?concept <http://www.w3.org/2004/02/skos/core#altLabel> ?altlab.
FILTER (lang(?altlab)='en').
}.
OPTIONAL {?concept <http://www.w3.org/2004/02/skos/core#broader> ?p.
?p <http://www.w3.org/2004/02/skos/core#prefLabel> ?pl}
OPTIONAL
{?level2 <http://www.w3.org/2004/02/skos/core#broader> ?level3.
OPTIONAL
{?level3 <http://www.w3.org/2004/02/skos/core#broader> ?level4.
OPTIONAL
{?level4 <http://www.w3.org/2004/02/skos/core#broader> ?level5.
OPTIONAL
{?level5 <http://www.w3.org/2004/02/skos/core#broader> ?level6.
OPTIONAL
{?level6 <http://www.w3.org/2004/02/skos/core#broader> ?level7.
OPTIONAL
{?level7 <http://www.w3.org/2004/02/skos/core#broader> ?level8.
OPTIONAL
{?level8 <http://www.w3.org/2004/02/skos/core#broader> ?level9.
OPTIONAL
{?level9 <http://www.w3.org/2004/02/skos/core#broader> ?level10.
}.}.}.}.}.}.}.}.
FILTER(
?level10 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level9 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level8 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level7 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level6 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level5 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level4 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level3 = <http://vocabs.lter-europe.net/EnvThes/10004> ||
?level2 = <http://vocabs.lter-europe.net/EnvThes/10004>).
FILTER(lang(?prefLab) = 'en').
}
Is there any way to make this recursive? I'm still very new to Sparql and having a hard time writing queries that actually work in the first place.
Thanks.
EDIT: Wow. Thanks for the super helpful answer and comment. I was already able to rewrite the query. For the sake of completeness I'll put it here, but the credit belongs to Joshua Taylor.
Shortened query:
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix envthes: <http://vocabs.lter-europe.net/EnvThes/>
select * {
values ?category { envthes:10004 }
?concept skos:broader* ?category .
?concept skos:prefLabel ?prefLab .
filter langMatches(lang(?prefLab), 'en')
optional {
?concept skos:altLabel ?altlab
filter langMatches(lang(?altLabel), 'en')
}.
OPTIONAL {?concept skos:altLabel ?altlab.
FILTER (lang(?altlab)='en').}.
OPTIONAL {?concept skos:broader ?parent.
?parent skos:prefLabel ?parLab .
}.
}
Upvotes: 0
Views: 1078
Reputation: 85863
This isn't exactly the same as your query, and I may have reversed the direction of the link between the concept and the category (I never remember the exact semantics of skos:broader, and which way it's supposed to go). The main changes here, though, are to use a prefix to make the query more readable, and to use a property path (skos:broader*) to link ?category and ?concept. I also used a values block to bind ?concept to the particular fixed value that you mentioned.
prefix skos: <http://www.w3.org/2004/02/skos/core#>
select * {
#-- specify the value for ?category (you can just
#-- use this inline, too, but defining it with
#-- values makes it easier to add others later, and
#-- can make the query easier to read)
values ?category { <http://vocabs.lter-europe.net/EnvThes/10004> }
#-- require that ?concept is related to ?category
#-- by a chain skos:broader properties of length
#-- zero or more. (Zero means that ?concept can be
#-- ?category. Use skos:broader+ to require a path
#-- of length one or more.)
?concept skos:broader* ?category .
#-- get an preferred label in English (required)
?concept skos:prefLabel ?prefLab .
filter langMatches(lang(?prefLab), 'en')
#-- get an alternative label in English (optional)
optional {
?concept <http://www.w3.org/2004/02/skos/core#altLabel> ?altlab
filter langMatches(lang(?altLabel), 'en')
}
}
Upvotes: 3