How to add conditions to a query - sparql

I would like to add a condition to a query, so that, if a result is empty, it fills it with a result of another query.
For example : If a owl:Class has no "skos:definition", I would like to replace it by a "rdfs:comment"
Is this possible ?
Thank you !

COALESCE is can help, especially as you get more choices from skos:prefLabel, skos:altLabel and more.
OPTIONAL { ?property rdfs:label ?label }
OPTIONAL { ?property skos:definition ?definition .}
# ... other ways to choose ?comment ...
BIND ( COALESCE(?definition, ?label, "Unknown") AS ?comment )
COALESCE allows expressions (unlike BOUND)
https://www.w3.org/TR/sparql11-query/#func-coalesce

I found something with BIND (IF(BOUND(...) ..., ...) AS ...) statement.
SELECT DISTINCT ?type ?property ?comment ?propertyType ?domain
WHERE {
?property rens:hasAttributeType ?propertyType .
?property rens:hasForDomain ?domain .
?property rdf:type ?type .
?property rdfs:label ?label .
OPTIONAL {?property skos:definition ?definition .}
BIND(IF(BOUND(?definition), ?definition, ?label) AS ?comment) .
}
Is this the better way ?

Related

Problem with basics queries form dbpedia with sparql

Why can get results with this query:
SELECT *
WHERE {
?person rdfs:label "Kirk Douglas"#en;
dbo:birthPlace ?place. # With dbp: too
}
but not with another one:
SELECT *
WHERE {
?person rdfs:label "Kirk Douglas"#en;
dbo:starring ?film.
}
I'm following tags in https://dbpedia.org/page/Kirk_Douglas
Some tip to understand it.
Thx!
In dbr:Kirk_Douglas you can read:
dbo:birthPlace dbr:Amsterdam_(city),_New_York
...
is dbo:starring of dbr:The_Light_at_the_Edge_of_the_World
dbr:Cast_a_Giant_Shadow
dbr:Two-Fisted_Tales_(film)
...
where is dbo:starring of is a way of simulating an inverse property for dbo:starring.
Indeed, in dbo:starring you can read:
rdfs:domain dbo:Work
...
rdfs:range dbo:Actor
This means that you shouldn't build triples like ?actor dbo:starring ?work, while ?work dbo:starring ?actor is a valid triple.
So your query should be something like:
SELECT *
WHERE {
?person rdfs:label "Kirk Douglas"#en .
?film dbo:starring ?person .
}

Free text search in sparql when you have multiword and scaping character

I am wondering how I can use in sparql query when I have a word like :
Robert J. O'Neill
I am looking for the resource that have the multiword unit with quota or unicode character in the Label property.
SELECT DISTINCT ?resource ?abstract
WHERE {?resource rdfs:label ?s.
?s <bif:contains> "'Robert J. O'Neill'"
?resource dbo:abstract ?abstract
}
'''
Here is the query that will return all the elements that have "Robert J. O'Neill" as label.
SELECT DISTINCT ?s WHERE
{
?s rdfs:label ?label .
FILTER(regex(?label, "Robert J. O'Neill", "i"))
}
If you are sure that you need a specific string matching. This is faster :
SELECT DISTINCT ?s WHERE
{
?s rdfs:label ?label .
?label bif:contains "Robert J. O'Neill"
}
But be aware that, Virtuoso for example doesnt support such a query because of the spaces in the string. So an alternative is to avoid it as :
SELECT DISTINCT * WHERE
{
?s rdfs:label ?label .
?label bif:contains "Robert" .
FILTER (CONTAINS(?label, " J. O'Neill"))
}
I found following code faster that the regex:
SELECT ?s WHERE { ?s rdfs:label ?o FILTER ( bif:contains ( ?o, '"Robert" AND "J." AND "Neill"' ) ) }

How to query all properties of owl:Thing of dbpedia using SPARQL?

When I use the following SPARQL query I get all properties of the DBpedia class Country:
select ?range ?domain ?prop ?label
Where{
?class rdfs:subClassOf{0,1} ?domain.
?prop rdfs:domain ?domain.
?prop rdfs:range ?range.
?prop rdfs:label ?label.
FILTER(lang(?label) = 'en')
FILTER(?class = <http://dbpedia.org/ontology/Country>)
}
When I try to do this with 'Thing' or 'OWL:Thing' or 'A Thing' or anything equivalent instead of Country, I get an empty result.
I want to adopt the ontology of DBpedia's owl:Thing, so I want to retrieve all properties of http://mappings.dbpedia.org/server/ontology/classes/owl%3AThing (including labela and range).
Does anyone know how I can achieve this?
There is not property in DBpedia with the domain owl:Thing:
select * {
?prop rdfs:domain owl:Thing
}
The reason for this is probably that if no explicit domain is given, owl:Thing is the trivial domain. You can check this also if you look at particular properties from your referred list, e.g. dbo:abbreviation
Workaround query:
SELECT ?range (owl:Thing as ?domain) ?prop ?label {
VALUES ?type {owl:DatatypeProperty owl:ObjectProperty}
?prop a ?type
OPTIONAL {?prop rdfs:range ?range }
?prop rdfs:label ?label.
FILTER(langmatches(lang(?label), 'en'))
FILTER NOT EXISTS {?prop rdfs:domain ?domain}
}

Aggregate properties

I'm developing my own Fuseki endpoint from some DBpedia data.
I'm in doubt on how to aggregate properties related to a single resource.
SELECT ?name ?website ?abstract ?genre ?image
WHERE{
VALUES ?s {<http://dbpedia.org/resource/Attack_Attack!>}
?s foaf:name ?name ;
dbo:abstract ?abstract .
OPTIONAL { ?s dbo:genre ?genre } .
OPTIONAL { ?s dbp:website ?website } .
OPTIONAL { ?s dbo:image ?image } .
FILTER LANGMATCHES(LANG(?abstract ), "en")
}
SPARQL endpoint: http://dbpedia.org/sparql/
This query returns 2 matching results. They are different just for the dbo:genre value. There is a way I can query the knowledge base and retrieving a single result with a list of genres?
#chrisis's query works well on the DBpedia SPARQL Endpoint, which is based on Virtuoso.
However, if you are using Jena Fuseki, you should use more conformant syntax:
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT
?name
(SAMPLE(?website) AS ?sample_website)
(SAMPLE(?abstract) AS ?sample_abstract)
(SAMPLE(?image) AS ?sample_image)
(GROUP_CONCAT(?genre; separator=', ') AS ?genres)
WHERE {
VALUES (?s) {(<http://dbpedia.org/resource/Attack_Attack!>)}
?s foaf:name ?name ;
dbo:abstract ?abstract .
OPTIONAL { ?s dbo:genre ?genre } .
OPTIONAL { ?s dbp:website ?website } .
OPTIONAL { ?s dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")
} GROUP BY ?name
The differences from the #chrisis's query are:
Since GROUP_CONCAT is an aggregation function, it might be used with GROUP BY only;
Since GROUP BY is used, all non-grouping variables should be aggregated (e.g. via SAMPLE);
GROUP_CONCAT syntax is slightly different.
In Fuseki, these AS in the projection are in fact superfluous: see this question and comments.
Yes, the GROUP_CONCAT() function is what you want.
SELECT ?name ?website ?abstract (GROUP_CONCAT(?genre,',') AS ?genres) ?image
WHERE{
<http://dbpedia.org/resource/Attack_Attack!> a dbo:Band ;
foaf:name ?name;
dbo:abstract ?abstract .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbo:genre ?genre } .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbp:website ?website} .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")
}

How to use Sparql Contains to match similar String?

I'm trying to grab some definition in dbpedia inside my thesaurus.
Although can find country that have a label that match my country, i don't get all of them. So i try to match similar label with contains but it does not work.
Any idea why.
SELECT distinct ?idbcountry ?label ?labelDb ?def
WHERE {
?idbcountry a skos:Concept .
?idbcountry rdfs:label ?label .
?idbcountry skos:inScheme iadb:IdBCountries .
FILTER(lang(?label) = "en")
Service <http://dbpedia.org/sparql> {
?s a <http://dbpedia.org/ontology/Country> .
?s rdfs:label ?labelDb .
FILTER(CONTAINS (?labelDb, ?label)).
?s rdfs:comment ?def .
FILTER(lang(?def) = "en") .
FILTER(lang(?labelDb) = "en") .
}}
The exact matching query that works is as follows:
SELECT distinct ?idbcountry ?label ?def
WHERE {
?idbcountry a skos:Concept .
?idbcountry rdfs:label ?label .
?idbcountry skos:inScheme iadb:IdBCountries .
FILTER(lang(?label) = "en")
Service <http://dbpedia.org/sparql> {
?s a <http://dbpedia.org/ontology/Country> .
?s rdfs:label ?label .
?s rdfs:comment ?def
FILTER(lang(?def) = "en")
}
}
EDIT1
Data Samples:
<http://thesaurus.iadb.org/publicthesauri/10157002136735779158437>
rdf:type skos:Concept ;
dct:created "2015-03-27T16:43:48.052-04:00"^^xsd:dateTime ;
rdfs:label "BO"#en ;
rdfs:label "Bolivia"#en ;
rdfs:label "Bolivia"#es ;
rdfs:label "Bolivie"#fr ;
rdfs:label "Bolívia"#pt ;
skos:altLabel "BO"#en ;
skos:definition "Bolivia (/bəˈlɪviə/, Spanish: [boˈliβja], Quechua: Buliwya, Aymara: Wuliwya), officially known as the Plurinational State of Bolivia (Spanish: Estado Plurinacional de Bolivia locally: [esˈtaðo pluɾinasjoˈnal de βoˈliβja]), is a landlocked country located in western-central South America."#en ;
skos:inScheme :IdBCountries ;
skos:prefLabel "Bolivia"#en ;
skos:prefLabel "Bolivia"#es ;
skos:prefLabel "Bolivie"#fr ;
skos:prefLabel "Bolívia"#pt ;
skos:topConceptOf :IdBCountries ;
<http://xmlns.com/foaf/0.1/focus> <http://dbpedia.org/resource/Bolivia> ;
Without seeing your data, we can't know why your query isn't working. However, using contains is pretty straightforward. It's just a matter of contains(string,substring). As Jeen said, we can't reproduce your problem without knowing what your data looks like, but here's an example of contains in action:
select distinct ?country ?label {
?country a dbpedia-owl:Country ; #-- select countries
rdfs:label ?label . #-- and get labels
filter langMatches(lang(?label),"en") #-- but only English labels
filter contains(?label,"land") #-- containing "land"
}
SPARQL results