How to construct a list in SPARQL - sparql

I have a ttl file that looks like this:
ex:Shape1
a sh:NodeShape ;
sh:property ex:Property-1
rdfs:label "Shape 1"
ex:Property-1
a sh:PropertyShape ;
sh:path ex:property1
sh:in (
"Option 1"
"Option 2"
) ;
sh:name "Property 1"
ex:property1
a owl:DatatypeProperty
After loading the above data into my triple store (which contains many shapes already), what query can I use to retrieve the same data back?
This query gets everything I need except for the list. For the list it only gives a blank node.
PREFIX sh: <http://www.w3.org/ns/shacl#>
PREFIX ex: <http://example.com/#>
CONSTRUCT {
?subject ?predicate ?object
}
WHERE {
{
bind(ex:Shape1 as ?subject)
ex:Shape1 ?predicate ?object
}
UNION
{
ex:Shape1 sh:property ?subject .
?subject ?predicate ?object
}
UNION
{
ex:Shape1 sh:property/sh:path ?subject .
?subject ?predicate ?object
}
}

First of all, why do you need to query to get the same data back? Do you mean you need to get it in the same syntax and formatting?
to get the same data in the form of triples, you can simply execute SELECT * from ?s ?p ?o and it will give you all the triples. It also depends on your triplestore.
The standard query to fetch the items in your list would be the following:
PREFIX sh: <http://www.w3.org/ns/shacl#>
PREFIX ex: <http://example.com/#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?item
WHERE {
ex:Property-1 sh:in/rdf:rest*/rdf:first ?item
}
You can read more about how the list items are stored internally. This link will be helpful.
You can bind the ex:Property-1 in the same way in UNION or WHERE clause in your construct query to get the desired result.
I hope it is helpful. Good luck.

Related

Querying DBPedia using SPARQL to find subjects with same objects

I am trying to find all those resources from dbpedia for eg rdf:type person who have same object eg date of birth.?
I thought of doing it with subquery but its definitely not the solution.
Can anyone provide some useful pointer?
From what you describe I think you mean:
prefix dbp: <http://dbpedia.org/property/>
prefix foaf: <http://xmlns.com/foaf/0.1/>
select ?s1 ?s2 ?dob
where {
?s1 a foaf:Person ; dbp:birthDate ?dob . # Find a person, get their dob
?s2 a foaf:Person ; dbp:birthDate ?dob . # Find a person with the same dob
}
Adjust type and predicate to suit.
This will include some redundancy: you will find answers where the subjects are the same ('Napoleon' 'Napoleon') and get answers twice ('Daniel Dennett' 'Neil Kinnock', 'Neil Kinnock' 'Daniel Dennett'). You can remove that with a filter:
filter (?s1 < ?s2)
which just ensures that one comes before the other (however the query engine wants to do that).
prefix dbp: <http://dbpedia.org/property/>
prefix foaf: <http://xmlns.com/foaf/0.1/>
select ?s1 ?s2 ?dob
where {
?s1 a foaf:Person ; dbp:birthDate ?dob .
?s2 a foaf:Person ; dbp:birthDate ?dob .
filter (?s1 < ?s2)
}
See the result
A SPARQL query is basically a set of triple patterns, i.e., a join (logical AND) of queries of the form
?subject ?predicate ?object.
What you need is identical ?object. Considering that you only care about ?subject (?predicate is not of importance), you can perform such a query you by ordering the results depending on ?object. Thus you will see results sharing ?object together.
select ?s ?p ?o where {
?s ?p ?o.
}
order by ?o
If you care about ?predicate as well, you should order the result using it second.
select ?s ?p ?o where {
?s ?p ?o.
}
order by ?o ?p
As those couple of queries may involve too many results as they will retrieve all the results possible. I recommend filtering ?object depending on some specific criteria. For example, to select all ?subject sharing an instance of Person as their ?object, use:
select ?s where {
?s ?p ?o.
{select ?o where{
?o a <http://dbpedia.org/ontology/Person>}
}
}
An alternative solution to the others is using aggregate functions like in this query template
select ?o (count(distinct ?s) as ?cnt) (group_concat(distinct ?s; separator=";") as ?subjects) {
?s a <CLASS> ;
<PREDICATE> ?o .
}
group by ?o
order by desc(count(distinct ?s))
which returns for each object the number of subjects and the list of subject belonging to a class CLASS for a given predicate PREDICATE
For example, asking for the dates of soccer players one could use
prefix dbo: <http://dbpedia.org/ontology/>
select ?date (count(distinct ?s) as ?cnt) (group_concat(distinct ?s; separator=";") as ?subjects) {
?s a dbo:SoccerPlayer ;
dbo:birthDate ?date .
}
group by ?date
order by desc(count(distinct ?s))
select * where {
?person1 a <http://dbpedia.org/ontology/Person>.
?person1 dbo:birthYear ?date.
?person2 a <http://dbpedia.org/ontology/Person>.
?person2 dbo:birthYear ?date
FILTER (?person1 != ?person2)
}
limit 10
Dbpedia will not allow you to execute that query on its public endpoint because it consumes more time that allowed, and you cannot change that time. Nevertheless, there are ways to execute it

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 queries gives different answers on different servers

I am trying to run the following sparql query :
PREFIX dct: <http://purl.org/dc/terms/>
select distinct ?subject
where
{
?concept rdfs:label 'Artificial intelligence'#en .
?concept ^dct:subject ?subject .
}
LIMIT 100
When I run this on dbpedia's public server, I get the following results :
http://dbpedia.org/sparql?default-graph-uri=&query=PREFIX++dct%3A++%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Fterms%2F%3E+select+distinct+%3Fsubject+where+%7B+%3Fconcept+rdfs%3Alabel+%27Artificial+intelligence%27%40en+.+%3Fconcept+%5Edct%3Asubject+%3Fsubject+.+%7D++LIMIT+100&format=text%2Fhtml&CXML_redir_for_subjs=121&CXML_redir_for_hrefs=&timeout=30000&debug=on
However, running the same query on a locally hosted instance of dbpedia, yields : http://34.195.108.80:8891/sparql?default-graph-uri=&query=PREFIX++dct%3A++%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Fterms%2F%3E+select+distinct+%3Fsubject+where+%7B+%3Fconcept+rdfs%3Alabel+%27Artificial+intelligence%27%40en+.+%3Fconcept+%5Edct%3Asubject+%3Fsubject+.+%7D++LIMIT+100&format=text%2Fhtml&CXML_redir_for_subjs=121&CXML_redir_for_hrefs=&timeout=30000&debug=on
Why is there a discrepancy in the answers to the point where it's entirely different?
I don't know what do you mean by "different", but without ORDER BY results will be returned more or less randomly simply influenced by the underlying system. There is even no guarantee that running the same query twice on the same server will return the results in the same order. Your query returns only 100 due to the LIMIT 100
The total number of results is the same for both queries, 271:
PREFIX dct: <http://purl.org/dc/terms/>
SELECT count(distinct ?subject) WHERE {
?concept rdfs:label 'Artificial intelligence'#en ;
? ^dct:subject ?subject .
}
For comparison, you have to use ORDER BY:
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?subject WHERE {
?concept rdfs:label 'Artificial intelligence'#en ;
^dct:subject ?subject .
}
ORDER BY ?subject

Not able to get Indian cities abstract from Sparql

I am trying to get abstract using Sqarql with dbpedia datasets.
When I am running the following query on Virtuoso,
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT DISTINCT ?abstract WHERE {
[ rdfs:label ?name
; dbpedia-owl:abstract ?abstract
] .
FILTER langMatches(lang(?abstract),"en")
VALUES ?name { "London"#en }
}
LIMIT 10
I am getting the result, however if I modify the name to say 'Gokarna' which is a south indian tourist spot, I am not getting any data. However I do see the resource page online on dbpedia for Gokarna(http://dbpedia.org/page/Gokarna,_India). What am I doing wrong? I need to get similar data for close to 800 indian places.
When you use values, you'd get only those that exactly match your string. For Gokarna, that would work for #de, #it, #fr, but not for #en, as there the label is different, as you can see also from the previous answer.
I would suggest to use contains, instead of values:
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT DISTINCT ?abstract WHERE {
[ rdfs:label ?name
; dbpedia-owl:abstract ?abstract
] .
FILTER langMatches(lang(?abstract),"en")
FILTER langMatches(lang(?name),"en")
FILTER CONTAINS (?name, "Gokarna" )
}
LIMIT 10
I am not that experience with Sqarql but as much i can see in your code and checked with dbpedia library...
it is not just Gokarna. it is "Gokarna,_India".
This should work..
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT DISTINCT ?abstract WHERE {
[ rdfs:label ?name
; dbpedia-owl:abstract ?abstract
] .
FILTER langMatches(lang(?abstract),"en")
VALUES ?name { "Gokarna,_India"#en }
}
LIMIT 10
If you look through the DBpedia page for Gokarna, India that you linked to, you'll notice that its rdfs:label is "Gokarna, India". But its foaf:name is just "Gokarna". This would mean you should modify your query to:
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT DISTINCT ?abstract WHERE {
[ foaf:name ?name
; dbpedia-owl:abstract ?abstract
] .
FILTER langMatches(lang(?abstract),"en")
VALUES ?name { "Gokarna"#en }
}
LIMIT 10
Though this will return other Gokarnas too: Gokarna, Nepal, Gokarna, Bangladesh and Gokarna (film). If you want to remove these, you will have to figure out another filter (possibly dbo:country dbr:India).

Querying subclasses through Fuseki

I use the following simple SPARQL query to obtain a list of classes of an ontology and their subclasses through Fuseki:
SELECT DISTINCT ?subject ?object
WHERE { ?subject rdfs:subClassOf ?object }
This way, I can see the complete URI of all the classes. Now, I would like to query the subclasses of a specific class, say abc
I look at the output of the query and I see the URI of the class in focus abc is this:
http://blahblahblah/file.owl#abc
So, I pose the following SPARQL query to get its subclasses:
SELECT DISTINCT ?subject
WHERE { ?subject rdfs:subClassOf http://blahblahblah/file.owl#abc }
But the output is empty. I also trying enclosing the URL within single quote and double quotes, to no avail.
SELECT DISTINCT ?subject
WHERE { ?subject rdfs:subClassOf 'http://blahblahblah/file.owl#abc' }
SELECT DISTINCT ?subject
WHERE { ?subject rdfs:subClassOf "http://blahblahblah/file.owl#abc" }
What am I doing wrong?
Thanks,
The syntax for IRIs in SPARQL encloses IRIs in angle brackets (< and >). Your query should be written as:
SELECT DISTINCT ?subject
WHERE { ?subject rdfs:subClassOf <http://blahblahblah/file.owl#abc> }