How to properly use SPARQL OPTIONAL to retrieve attributes for a resource that may exist? - sparql

I'm trying to use a SPARQL query to retrieve information about a DBpedia resource (a Person). I'd like to use the same query to retrieve data about any Person by parameterizing the resource URI. Since some attributes may not exist for a particular resource, I'm making use of the OPTIONAL statement. Here is my query:
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 ?deathDate ?page ?thumbnail
WHERE {
<http://dbpedia.org/resource/Neil_Simon> rdfs:label ?label ;
dbo:abstract ?abstract ;
foaf:page ?page .
OPTIONAL {
<http://dbpedia.org/resource/Neil_Simon> dbpprop:placeOfBirth ?placeOfBirth ;
dbpprop:birthPlace ?birthPlace ;
dbo:birthDate ?birthDate ;
dbo:deathdate ?deathDate ;
dbo:thumbnail ?thumbnail .
}
FILTER (LANG(?label) = 'en')
FILTER (LANG(?abstract) = 'en')
}
LIMIT 1
I've left everything except label, abstract and page in OPTIONAL, since if I use the same query for another person, they may not have those properties. The problem is, none of those optional attributes are showing up in the results. In Neil Simon's case, you can see that there are values for birthDate, birthPlace and thumbnail: http://dbpedia.org/resource/Neil_Simon. However, those values don't show up when I run the query: DBpedia SPARQL query. What am I doing wrong, and how can I optionally retrieve those properties?

Although you have used an OPTIONAL construct the map pattern itself needs all the attributes within to match. So only if you have birthPlace, birthDate, deathDate and thumbnail the inner optional construct is satisfied
I would suggest breaking the OPTIONAL construct up into multiple OPTIONAL constructs.

Related

SPARQL DBpedia get properties of a person knowing their name

new to SPARQL. Trying to figure out why I get different results on these two queries. It's based on this other question, where I'm trying to match properties to a name of a person. For example, I'm curious to know the birthday of J.K. Rowling, without knowing her URI directly. Here's the code from the link above:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT DISTINCT *
WHERE
{
?item rdfs:label ?itemLabel .
FILTER ( ?itemLabel = "Car"#en ) .
?item dbo:abstract ?itemDescription .
FILTER (lang(?itemDescription) = 'en')
}
ORDER BY ?itemLabel
compared to the query I'd like with J.K.:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT DISTINCT *
WHERE
{
?item rdfs:label ?itemLabel .
FILTER ( ?itemLabel = "J.K. Rowling"#en ) .
?item dbo:abstract ?itemDescription .
FILTER (lang(?itemDescription) = 'en')
}
ORDER BY ?itemLabel
The first one works fine, however, when I replace "Car" with "J.K. Rowling" as in the second, nothing is returned (her URI is return if I remove the dbo:abstract line and the filter line for it). J.K. Rowling does have a dbo:abstract in English. I'm not sure why it works for one and not the other. The only thing I can see that that 'Car' is a 'Thing', while J.K. is a 'person'

Simple SPARQL Query

I am working from this example, and I want to archieve the same, however with a different topic - Climate change
All i need to output is the abstract from this page: http://dbpedia.org/page/Climate_change
PREFIX dbp-res: <http://dbpedia.org/resource/>
PREFIX dbp-ont: <http://dbpedia.org/ontology/>
PREFIX dbp-prop: <http://dbpedia.org/property/>
SELECT *
WHERE
{
?Resource a dbp-ont:Agent .
?Resource dbp-ont:abstract ?Description .
?Resource rdfs:label ?Label .
FILTER( STR(?Label) = 'Climate_change' )
FILTER (langMatches(lang(?Description),'en'))
FILTER (langMatches(lang(?Label),'en'))
}
The problem seems to be the Agent, but I have no clue, as to what to replace it with.
My query

How to get dct:subjects for all entities using SPARQL

I am using the following query
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?subject WHERE {
?concept rdfs:label 'Exoskeleton'#en ;
^dct:subject ?subject .
}
ORDER BY ?subject
This doesn't give me any results. However, the rdfs:label exists. (See http://dbpedia.org/page/Exoskeleton.)
On querying with a different label, it works :
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?subject WHERE {
?concept rdfs:label 'Machine learning'#en ;
^dct:subject ?subject .
}
ORDER BY ?subject
The above query works and gives me the results. (See http://dbpedia.org/page/Machine_learning.)
What do I change, such that the first query works too?
The dct:subject predicate is used between a page and a category it belongs to. So, your second query is giving you results that are in Category:Machine learning. But since there is no Category:Exoskeleton, your first query gives you no results. This also means the two pages you liked to are irrelevant to your queries.
I don't know how to change the first query so that it works, because I don't understand what would "working" entail.
Devil is in the details:
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?concept WHERE {
?concept rdfs:label 'Machine learning'#en.
}
ORDER BY ?concept
Returns two results:
http://dbpedia.org/resource/Category:Machine_learning
http://dbpedia.org/resource/Machine_learning
While Exoskeleton has no corresponding concept:
http://dbpedia.org/resource/Exoskeleton
Thus your inverse property path finds resources under a http://dbpedia.org/resource/Category:Machine_learning concept but not under a http://dbpedia.org/resource/Machine_learning or http://dbpedia.org/resource/Exoskeleton pages.
If you drop the inverse modifier,
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?subject WHERE {
?concept rdfs:label 'Exoskeleton'#en ;
dct:subject ?subject .
}
ORDER BY ?subject
Will return the categories (subject) for the concepts under a given label.

SPARQL for getting movies list with proper attributes ordered

I'm trying to get list of movies in a specific year (just say 1990) with each movie and it's attributes. I tried different ways to get SPARQL but couldn't. How do I group genres into single column?
The format I would want is with some of the properties from here
http://schema.org/Movie
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
PREFIX wikibase: <http://wikiba.se/ontology#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX v: <http://www.wikidata.org/prop/statement/>
PREFIX q: <http://www.wikidata.org/prop/qualifier/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?q ?film_title (GROUP_CONCAT(DISTINCT(?genreID); separator=", ") as ?genre) WHERE {
?q wdt:P31 wd:Q11424.
?q rdfs:label ?film_title filter (lang(?film_title) = "en").
?q wdt:P136 ?genreID.
?genreID rdfs:label ?genre.
?q wdt:P161 ?actorID.
?actorID rdfs:label ?actor filter (lang(?actor) = "en").
} LIMIT 100
Usage of aggregate functions usually need to build the group of things/rows on which you want to apply the function, i.e. a GROUP_BY on the projection variables that do not denote the result of an aggregate function:
SELECT ?q ?film_title (GROUP_CONCAT(DISTINCT(?genreID); separator=", ") as ?genres) WHERE {
?q wdt:P31 wd:Q11424 .
?q rdfs:label ?film_title .
FILTER (lang(?film_title) = "en")
?q wdt:P136 ?genreID .
?genreID rdfs:label ?genre .
?q wdt:P161 ?actorID .
?actorID rdfs:label ?actor
FILTER (lang(?actor) = "en")
}
GROUP BY ?q ?film_title
LIMIT 100
Some comments:
it's not clear whether you want to get the genreID or the label of the genre, for the latter indeed you have to use the variable ?genre in the GROUP_CONCAT function: GROUP_CONCAT(DISTINCT(?genre); separator=", ")
it's not allowed to re-assign a variable name that has already been used in the query, that's why I changed the name to ?genres
don't put a comma after a FILTER, I don't know why you did so
you don't select the actor, thus, it remains unclear why you use the last triple pattern + FILTER in your query
your query is quite expensive, thus, its execution might timeout

SPARQL query does not give all the results that are on dbpedia

I'm executing this query in http://dbpedia.org/snorql/:
Query:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX type: <http://dbpedia.org/class/yago/>
PREFIX prop: <http://dbpedia.org/property/>
SELECT ?country_name ?population
WHERE {
?country a type:LandlockedCountries ;
rdfs:label ?country_name ;
prop:populationEstimate ?population .
}
The query looks for all land looked countries.
I don't understand why in the results there are not some countries which are classified on
"/dbpedia.org/class/yago/LandlockedCountries". For example, Paraguay (/dbpedia.org/page/ParaguAy) is classified but does not appear in the query result set. Can somebody explain me why?
Unfortunately, there are a small number of landlocked countries that do not have values for at least one of the country_name and populationEstimate properties. This is why they will not be returned in your query. If you run the following query, those countries will come up (those two attributes are set as OPTIONAL).
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX type: <http://dbpedia.org/class/yago/>
PREFIX prop: <http://dbpedia.org/property/>
SELECT ?country ?country_name ?population
WHERE {
?country a type:LandlockedCountries .
OPTIONAL {?country rdfs:label ?country_name Filter(lang(?country_name) = 'en')} .
OPTIONAL {?country prop:populationEstimate ?population} .
}
run query
For (slightly) better results, since some countries seem to be duplicated with erroneous capitalization (e.g. ParaguAy and Paraguay), the following query uses ?country dcterms:subject category:Landlocked_countries instead of the yago class.
run query