I am trying to complete the following case in SPARQL. I want to return the labels of the deathPlace for the Greek writer "Nikos Kazantzakis"
The workspace to copy-paste the queries below.
I am running the following query:
PREFIX dp: <https://dbpedia.org/page/West_Germany>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT (?musician as ?musicianName) ?nationality ?deathTime ?deathPlaceLabel ?abstarct
WHERE
{
?musician rdfs:label "Nikos Kazantzakis" #en .
?musician dbo:nationality ?nationality .
?musician dbo:deathDate ?deathTime .
?musician dbo:deathPlace ?deathPlaceLabel .
#dp:commonName ?deathPlaceLabel?deathPlaceLabel .
?musician dbo:abstract ?abstarct .
FILTER (lang(?abstarct) = 'en')
}
This has the following result:
The ?deathPlaceLabel value is printed but as the hyperlink resource. Is it feasible to enter each property (i.e. dbr:West_Germany, dbr:Germany, dbr:Freiburg) and print their labels?
What I tried is to pass the West_Germnay resource to a prefix and then call the "commonName" property from that prefix. Likewise,
PREFIX dp: <https://dbpedia.org/page/West_Germany>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT (?musician as ?musicianName) ?nationality ?deathTime ?deathPlaceLabel ?abstarct
WHERE
{
?musician rdfs:label "Nikos Kazantzakis" #en .
?musician dbo:nationality ?nationality .
?musician dbo:deathDate ?deathTime .
#?musician dbo:deathPlace ?deathPlaceLabel .
?dplabel dp:commonName ?deathPlaceLabel .
?musician dbo:abstract ?abstarct .
FILTER (lang(?abstarct) = 'en')
}
But I seem to retrieve an empty column(s) result.
To get the rdfs:label of the entities, you could use:
?musician dbo:deathPlace ?deathPlace .
?deathPlace rdfs:label ?deathPlaceLabel .
If you don’t need to do anything else with ?deathPlace, you can use a property path instead:
?musician dbo:deathPlace/rdfs:label ?deathPlaceLabel .
Full query:
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?musician ?nationality ?deathDate ?deathPlaceLabel ?abstract
WHERE
{
VALUES ?musician { dbr:Nikos_Kazantzakis }
?musician dbo:nationality ?nationality ;
dbo:deathDate ?deathDate ;
dbo:deathPlace/rdfs:label ?deathPlaceLabel ;
dbo:abstract ?abstract .
FILTER(lang(?abstract) = 'en') .
FILTER(lang(?deathPlaceLabel) = 'en') .
}
If you already know which entity you want to query, it’s better to use its URI instead of its label (it’s faster that way, and you make sure that you get exactly the entity you want, as there could be different entities with the same label).
So I replaced rdfs:label "Nikos Kazantzakis"#en with a VALUES block, in which you can add/remove the URIs of musicians.
Note that it’s important to use the URIs with /resource/ (which represents the musician) instead of /page/ (which represents the page about the musician).
In case you only want one result line, you could use GROUP_CONCAT for ?deathPlaceLabel:
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?musician ?nationality ?deathDate (GROUP_CONCAT(?deathPlaceLabel; separator=", ") AS ?deathPlaceLabels) ?abstract
WHERE
{
VALUES ?musician { dbr:Nikos_Kazantzakis }
?musician dbo:nationality ?nationality ;
dbo:deathDate ?deathDate ;
dbo:deathPlace/rdfs:label ?deathPlaceLabel ;
dbo:abstract ?abstract .
FILTER(lang(?abstract) = 'en') .
FILTER(lang(?deathPlaceLabel) = 'en') .
} GROUP BY ?musician ?nationality ?deathDate ?abstract
Alternatively, you could try to restrict which kind of death places you want. For example, only cities (with the drawback that it excludes results for which the city is unknown/unspecified).
Related
The following query works as expected:
PREFIX nct: <http://n2t.net/ark:/39333/ncg/type#>
PREFIX ncv: <http://n2t.net/ark:/39333/ncg/vocab#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?label ?url WHERE {
BIND("Chapel Hill" as ?placename)
{
?marker
a nct:HistoricalMarker ;
skos:prefLabel ?label ;
skos:note ?markerDescription ;
.
FILTER CONTAINS(?markerDescription, "Chapel Hill")
}
UNION
{
?musician skos:prefLabel ?label .
?place
skos:prefLabel ?placename ;
ncv:associatedWithAgent ?musician ;
.
}
UNION
{
?movie skos:prefLabel ?label .
?place
skos:prefLabel ?placename ;
ncv:filmingLocationFor ?movie ;
.
}
}
But if I change FILTER CONTAINS(?markerDescription, "Chapel Hill") in the first block to FILTER CONTAINS(?markerDescription, ?placename), it no longer works.
Try the working query.
Try the not working query.
Why?
Trying to run this piece of code on DBPEDIA and it doesn't return anything except headers.
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?diseasename ?personname where {
?disease a dbo:Disease .
?person dbo:deathCause ?disease .
?person rdfs:label ?personname FILTER (lang(?personname) = "en").
?disease rdfs:label ?diseasename FILTER (lang(?diseasename) = "en").
?disease rdfs:label ?diseasename FILTER (?diseasename = "Brain tumor")
}
Thanks for the help in advance!
Try this --
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?diseasename ?personname where {
?disease a dbo:Disease .
?person dbo:deathCause ?disease .
?person rdfs:label ?personname
FILTER (lang(?personname) = "en").
?disease rdfs:label ?diseasename
FILTER (lang(?diseasename) = "en").
?disease rdfs:label ?diseasename
FILTER (?diseasename = "Brain tumor"#en)
}
-- or, noting the redundancy in the query pattern above, this --
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?diseasename ?personname where {
?disease a dbo:Disease .
?person dbo:deathCause ?disease .
?person rdfs:label ?personname
FILTER (lang(?personname) = "en").
?disease rdfs:label ?diseasename
FILTER (?diseasename = "Brain tumor"#en)
}
In dbpedia I select some pages with label starting 'A'. Here I'm using additional filter by subject to narrow the set. In original version there are another conditions (result set is much bigger)
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX purl: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://dbpedia.org/page/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX dbr: <http://dbpedia.org/resource/>
SELECT DISTINCT
?pageType
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
}
FILTER ( strstarts(str(?pageType), 'http://dbpedia.org/ontology') )
}
LIMIT 1000
sparql results
Here I select only page types to be clear with rest of the question.
This is the whole set. Now I want to exclude some pages. Exclude all agents (persons, organization etc):
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX purl: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://dbpedia.org/page/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX dbr: <http://dbpedia.org/resource/>
SELECT DISTINCT
?pageType
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
MINUS { ?page a dbo:Agent }
}
FILTER ( strstarts(str(?pageType), 'http://dbpedia.org/ontology') )
}
LIMIT 1000
The result.
Ok. Then I want to exclude more types, for example Written_Work. I tried different approaches, but unabled to find the correct one.
This returns nothing:
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
MINUS { ?page a dbo:Agent }
MINUS { ?page a dbo:WrittenWork }
}
This is like no filter is set:
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
MINUS { ?page a dbo:Agent, dbo:WrittenWork }
}
The question is:
what way should I go to exclude pages of certain types (direct and superclass)?
It look's like this is working answer (how to exclude multiple of types)
{
?page purl:subject ?id .
?page a ?pageType .
FILTER NOT EXISTS {
?page a/rdfs:subClassOf* ?skipClasses .
FILTER(?skipClasses in (dbo:Agent, dbo:Place, dbo:Work))
}
}
In this example all dbo:Agents, db:Places, dbo:Works will be filtered out.
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 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.