I'm having trouble getting the optional tag to return rows where some attributes may not exist. For example in the following query I return some information about the MMA fighter Lyoto Machida http://goo.gl/cWFk9N
SELECT ?surname ?givenName ?nick ?height ?born ?nationality ?birthplace
where {
<http://dbpedia.org/resource/Lyoto_Machida>
foaf:surname ?surname ;
foaf:givenName ?givenName ;
dbp:otherNames ?nick ;
dbo:height ?height ;
dbp:birthDate ?born ;
dbp:nationality ?nationality ;
dbp:birthPlace ?birthplace
}
Now if I want to use that same query, except with the MMA fighter Luke Rockhold I get no results. This is because he does not have a listed nationality or otherNames. So I tried using the optional tags around all my attributes but this still didn't work.
SELECT ?surname ?givenName ?nick ?height ?born ?nationality ?birthplace
where {
<http://dbpedia.org/resource/Luke_Rockhold>
OPTIONAL {foaf:surname ?surname ;}
OPTIONAL {foaf:givenName ?givenName ;}
OPTIONAL {dbp:otherNames ?nick ;}
OPTIONAL {dbo:height ?height ;}
OPTIONAL {dbp:birthDate ?born ;}
OPTIONAL {dbp:nationality ?nationality ; }
OPTIONAL {dbp:birthPlace ?birthplace }
}
Is there an error with my syntax or logic? I'm quite new to using sparql and dbpedia, any help is greatly appreciated
You can't split a single pattern with OPTIONAL like that. The parts outside and inside OPTIONAL have to be valid patterns on their own. One way to do this would be to use BIND:
SELECT ?surname ?givenName ?nick ?height ?born ?nationality ?birthplace
WHERE {
BIND(:Luke_Rockhold AS ?x)
OPTIONAL {?x foaf:surname ?surname}
OPTIONAL {?x foaf:givenName ?givenName}
OPTIONAL {?x dbp:otherNames ?nick}
OPTIONAL {?x dbo:height ?height}
OPTIONAL {?x dbp:birthDate ?born}
OPTIONAL {?x dbp:nationality ?nationality}
OPTIONAL {?x dbp:birthPlace ?birthplace}
}
Related
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")
}
I am trying to query dbpedia to get some people data and I don't have subjects just names of the people I want to query and their birth/death dates.
I am trying to do a query along these lines. I want the name, birth date, death date and thumbnail of everyone with the surname Presley. What I then intend to do is loop through the results returned and find the best match for Elvis Presley 1935-1977 which is the data I have.
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?Name ?thumbnail ?birthDate ?deathDate WHERE {
{
dbo:name ?Name ;
dbo:birthDate ?birthDate ;
dbo:birthDate ?deathDate ;
dbo:thumbnail ?thumbnail ;
FILTER contains(?Name#en, "Presley")
}
What is the best way to construct my sparql query?
UPDATE:
I have put together this query which seems to work to some extent but I don't entirely understand it, and I can't figure out the contains, but it does at least run and return results.
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?subject ?thumbnail ?birthdate ?deathdate WHERE {
{
?subject rdfs:label "Elvis Presley"#en ;
dbo:thumbnail ?thumbnail ;
dbo:birthDate ?birthdate ;
dbo:deathDate ?deathdate ;
a owl:Thing .
}
UNION
{
?altName rdfs:label "Elvis Presley"#en ;
dbo:thumbnail ?thumbnail ;
dbo:birthDate ?birthdate ;
dbo:deathDate ?deathdate ;
dbo:wikiPageRedirects ?s .
}
}
Some entities might not have all of that information, so it's better to use optional. You can use foaf:surname to check for surname directly.
select * where {
?s foaf:surname "Presley"#en
optional { ?s dbo:name ?name }
optional { ?s dbo:birthDate ?birth }
optional { ?s dbo:deathDate ?death }
optional { ?s dbo:thumbnail ?thumb }
}
I am trying to get the hierarchy of super and subclass of dbpedia ontolgy.
Sparql query:
SELECT DISTINCT ?superclass ?subclass
WHERE
{
?subclass a owl:Class .
?subclass rdfs:subClassOf ?superclass
}
ORDER BY ?superclass ?subclass
It gives me all classes. But when I am trying to get the counts of entity inside classes. Some classes have entity while some don't have.
Sparql query to get the count of entity inside classes.
Getting Entities:
SELECT DISTINCT ?label AS ?label
?name AS ?name
?link AS ?link
WHERE
{
?link rdf:type <http://www.wikidata.org/entity/Q12136> .
OPTIONAL { ?link foaf:name ?name }
OPTIONAL { ?link rdfs:label ?label }
FILTER( lang(?label) = "en" )
}
Not getting Entities:
SELECT DISTINCT ?label AS ?label
?name AS ?name
?link AS ?link
WHERE
{
?link rdf:type <http://www.wikidata.org/entity/Q18553493> .
OPTIONAL { ?link foaf:name ?name }
OPTIONAL { ?link rdfs:label ?label }
FILTER(lang(?label) = "en" )
}
Why some classes don't have entities? Or Am I doing something wrong? Any help please?
First of all, you are talking about classes and not ontologies. I don't know why you think that entities are instances of ontologies, especially when you're talking about individuals/instances/resources.
Second, why shouldn't there be classes that do not have instances yet?
I have to use this Spaql query to retrive information about a person, my problem is to break the optional construct up into multiple optional constructs.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbpprop: <http://dbpedia.org/property/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?label ?abstract ?placeOfBirth
?birthPlace ?birthDate ?page ?thumbnail
WHERE {
<http://dbpedia.org/resource/Ismail_Kadare> rdfs:label ?label ;
dbo:abstract ?abstract ;
foaf:page ?page .
OPTIONAL {
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth ;
dbpprop:birthPlace ?birthPlace ;
dbo:birthDate ?birthDate ;
dbo:thumbnail ?thumbnail .
}
FILTER (LANG(?label) = 'en')
FILTER (LANG(?abstract) = 'en')
}
LIMIT 1
Splitting the OPTIONAL pattern into parts
The pattern
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth ;
dbpprop:birthPlace ?birthPlace ;
dbo:birthDate ?birthDate ;
dbo:thumbnail ?thumbnail .
is shorthand for four triple patterns:
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth .
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:birthPlace ?birthPlace .
<http://dbpedia.org/resource/Ismail_Kadare> dbo:birthDate ?birthDate .
<http://dbpedia.org/resource/Ismail_Kadare> dbo:thumbnail ?thumbnail .
Instead of OPTIONAL { …first pattern… }, you just need to use four optional blocks, one for each of the four triple patterns:
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth }
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbpprop:birthPlace ?birthPlace }
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbo:birthDate ?birthDate }
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbo:thumbnail ?thumbnail }
Other issues
It's worth nothing that language matching is a bit more complicated than string matching, so rather than
FILTER (LANG(?label) = 'en')
FILTER (LANG(?abstract) = 'en')
you should really be using
filter(langMatches(lang(?label),'en'))
filter(langMatches(lang(?abstract),'en'))
which allows you to retrieve results that use different language tags that are all English.
select distinct and limit 1 aren't both necessary
Notice that select distinct ensures that you don't have any duplicate rows in your results. However, limit 1 means that you'll only have one result at most anyhow, so there won't be any duplicates to remove.
Standard Namespaces
It looks like you're querying against DBpedia, so it might be worthwhile to use the same namespace prefixes that the public endpoint defines, so that you can copy and paste queries and experiment more easily. Doing that (and using a values ?x { dbpedia:Ismail_Kadare } to avoid some typing, we end up with this query:
select ?label ?abstract ?placeOfBirth ?birthPlace ?birthDate ?page ?thumbnail
where {
values ?x { dbpedia:Ismail_Kadare }
?x rdfs:label ?label ;
dbpedia-owl:abstract ?abstract ;
foaf:page ?page .
optional { ?x dbpprop:placeOfBirth ?placeOfBirth }
optional { ?x dbpprop:birthPlace ?birthPlace }
optional { ?x dbpedia-owl:birthDate ?birthDate }
optional { ?x dbpedia-owl:thumbnail ?thumbnail }
filter langMatches(lang(?label),'en')
filter langMatches(lang(?abstract),'en')
}
limit 1
The DBpedia endpoint won't return anything for that query, but that's because http://dbpedia.org/resource/Ismail_Kadare doesn't have a foaf:page property, not because the query is malformed. I don't know whether you're actually running this against DBpedia or not, so that may or not matter.
I want to obtain some data from dbpedia.
I have entities urls and want to get some information about localization.
Now i call query like this:
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT DISTINCT * WHERE
{
<{0}> rdfs:label ?label .
OPTIONAL {
<{0}> geo:lat ?lat ;
geo:long ?long .
} .
OPTIONAL {
<{0}> dbo:Country ?dboCountry
} .
OPTIONAL {
<{0}> dbpedia-owl:country ?dbpediaContry .
?dbpediaContry dbpprop:cctld ?ccTLD
}.
OPTIONAL {
<{0}> dbpprop:country ?dbpropContry
}
FILTER ( lang(?label) = "en" )
}
for each url (replace {0} with url).
But I would like to optimize it and get result for more entities in one query.
Also is it possible to not set url in each line?
Regards
Piotr
Hmm, it looks I already have found an answer for both questions.
Do you know this(http://en.wikipedia.org/wiki/Rubber_duck_debugging)
Solution is:
SELECT DISTINCT *
WHERE {
?uri rdfs:label ?label .
OPTIONAL { ?uri geo:lat ?lat .
?uri geo:long ?long} .
FILTER (?uri IN ({0}, {1}, ...) )
}
Maybe it will be helpful for somebody else?
Or maybe someone knows better solution?