I want to retrieve the name of the city associated to a person in a triplestore which links a person to a geonames entry. I am using a local server (Apache Jena Fuseki) on this minimal triplestore (in turtle):
#prefix ex: <http://www.example.audio/ex> .
#prefix foaf: <http://xmlns.com/foaf/0.1/> .
#prefix gn: <http://www.geonames.org/ontology#> .
ex:Cristina rdf:type foaf:Person ;
foaf:firstName "Cristina" ;
foaf:based_near <https://sws.geonames.org/3164527/> .
https://sws.geonames.org/3164527/ is the URI of the city of Verona
This is the query I am trying to perform:
SELECT ?person
WHERE {
?person foaf:based_near ?city .
?city gn:name "Verona" .
}
As you can see, what I wish to do is using the gn:name predicate.
How can I achieve this? Obviously I am doing something wrong.
Related
This is an evolution of this question.
Basically I am having trouble getting all the solutions to a SPARQL query from a remote endpoint. I have read through section 2.4 here because it seems to describe a situation almost identical to mine.
The idea is that I want to filter my results from DBPedia based on information in my local RDF graph. The query is here:
PREFIX ns1:
<http://www.semanticweb.org/caeleanb/ontologies/twittermap#>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT *
WHERE {
?p ns1:displayName ?name .
SERVICE <http://dbpedia.org/sparql> {
?s rdfs:label ?name .
?s rdf:type foaf:Person .
}
}
And the only result I get is dbpedia:John_McCain (for ?s). I think this is because John McCain is the only match in the first 'x' results, but I can't figure out how to get the query to return all matches. For example, if I add a filter like:
SERVICE <http://dbpedia.org/sparql> {
?s rdfs:label ?name .
?s rdf:type foaf:Person .
FILTER(?name = "John McCain"#en || ?name = "Jamie Oliver"#en)
}
Then it correctly returns BOTH dbpedia:Jamie_Oliver and dbpedia:John_McCain. There are dozens of other matches like Jamie Oliver that do not come through unless I specifically add it to a Filter like this.
Can someone explain a way to extract the rest of the matches? Thanks.
It looks like the cause of this issue is that the SERVICE block is attempting to pull all foaf:Persons from DBPedia, and then filter them based on my local Stardog db. Since there is a 10,000 result limit when querying DBPedia, only matches which occur in that set of 10,000 arbitrary Persons will be found. To fix this, I wrote a script to put together a FILTER block containing every string name in my Stardog db and attached it to the SERVICE block to filter remotely and thereby avoid hitting the 10,000 result limit. It looks something like this:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX ns1: <http://www.semanticweb.org/caeleanb/ontologies/twittermap#>
CONSTRUCT{
?s rdf:type ns1:Person ;
ns1:Politician .
}
WHERE {
?s rdfs:label ?name .
?s rdf:type dbo:Politician .
FILTER(?name IN ("John McCain"#en, ...)
}
I have built an ontology for live concerts, Concert_Ontology.ttl. This contains definitions for concerts, artists, repertoires, and songs. I want to match the artists in my ontology and the artists in the dbpedia Person ontology based on the attributes c:artistName and dbp:name. I have written the following query to access the dbpedia endpoint and retrieve additional information about the artists.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX c: <http://localhost:8080/Concert_Ontology.ttl#>
SELECT ?performer ?artistname ?dob
WHERE {
?performer a c:Artist ;
c:artistName ?artistname .
SERVICE <http://dbpedia.org/sparql> {
?person a dbo:Person ;
dbo:birthDate ?dob ;
dbp:name ?n .
FILTER (str(?n) = ?artistname)
}
}
However, I do not seem to be able to access the ?artistname variable from within the SERVICE expression. If I put the FILTER method outside the SERVICE expression the query works, but since dbpedia has a return cap of 10000 results, I am not able to retrieve and match all the artists.
Could someone guide me in finding a solution to this problem?
I found a solution to my problem. The filter function will not work with a local variable on the remote endpoint. However, if I omit the filter function and simply use the same variable name for the local and remote variable, it will return the correct results. Like this:
SELECT ?performer ?artistname ?dob
WHERE {
?performer a :Performer ;
:artistName ?artistname .
SERVICE <http://dbpedia.org/sparql> {
?person a dbo:Person ;
dbo:birthDate ?dob ;
dbp:name ?artistname .
}
}
SERVICE executes the pattern at the server. The server does not know the value of ?artistname (of which there can be many and is local information to the caller). So the best that can happen is to execute the
?person a dbo:Person ;
dbo:birthDate ?dob ;
dbp:name ?n .
and filter locally.
You can pass variable as IRI to SERVICE.
bind(iri(concat("http://dbpedia.org/resource/",replace(? artistname," ","_"))) as ?person)
and no need to filter by name.
I have an OWL file that includes a taxonomic hierarchy that I want to write a query where the answer includes each individual and its immediate taxonomic parent. Here's an example (the full query is rather messier).
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix rdf: <http:://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix : <urn:ex:> .
:fido rdf:type :Dog .
:Dog rdfs:subClassOf :Mammal .
:Mammal rdfs:subClassOf :Vertebrate .
:Vertebrate rdfs:subClassOf :Animal .
:fido :hasToy :bone
:kitty rdf:type :Cat .
:Cat rdfs:subClassOf :Mammal .
:kitty :hasToy :catnipMouse .
And this query does what I want.
prefix rdf: <http:://www.w3.org/1999/02/22-rdf-syntax-ns#> .
prefix : <urn:ex:> .
SELECT ?individual ?type
WHERE {
?individual :hasToy :bone .
?individual rdf:type ?type .
}
The problem is that I'd rather use a reasoned-over version of the OWL file, which unsurprisingly includes additional statements:
:fido rdf:type :Mammal .
:fido rdf:type :Vertebrate .
:fido rdf:type :Animal .
:kitty rdf:type :Mammal .
:kitty rdf:type :Vertebrate .
:kitty rdf:type :Animal .
And now the query results in additional answers about Fido being a Mammal, etc. I could just give up on using the reasoned version of the file, or, since the SPARQL queries are called from java, I could do a bunch of additional queries to find the least inclusive type that appears. My question is whether there is a reasonable pure SPARQL solution to only returning the Dog solution.
A generic solution is that you make sure you ask for the direct type only. A class C is the direct type of an instance X if:
X is of type C
there is no C' such that:
X is of type C'
C' is a subclass of C
C' is not equal to C
(that last condition is necessary, by the way, because in RDF/OWL, the subclass-relation is reflexive: every class is a subclass of itself)
In SPARQL, this becomes something like this:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <urn:ex:> .
SELECT ?individual ?type
WHERE {
?individual :hasToy :bone .
?individual a ?type .
FILTER NOT EXISTS { ?individual a ?other .
?other rdfs:subClassOf ?type .
FILTER(?other != ?type)
}
}
Depending on which API/triplestore/library you use to execute these queries, there may also be other, tool-specific solutions. For example, the Sesame API (disclosure: I am on the Sesame dev team) has the option to disable reasoning for the purpose of a single query:
TupleQuery query = conn.prepareTupleQuery(SPARQL, "SELECT ...");
query.setIncludeInferred(false);
TupleQueryResult result = query.evaluate();
Sesame also offers an optional additional inferencer (called the 'direct type inferencer') which introduces additional 'virtual' properties you can query, such as sesame:directType, sesame:directSubClassOf, etc. Other tools will undoubtedly have similar options.
The first ontology has the following:
Issue Ontology members(classes):
<http://www.issueonto.com/ontologies/issues#issues>
<http://www.issueonto.com/ontologies/issues#products>
Predicate/Properties:
<http://www.issueonto.com/ontologies/issues#hasIssues>
Triple store for this ontology (raw data), I show it here in Turtle format:
#prefix : <http://www.issueonto.com/ontologies/issues#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix xml: <http://www.w3.org/XML/1998/namespace> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#base <http://www.issueonto.com/ontologies/issues> .
:Fido rdf:type :products ,
owl:NamedIndividual ;
:productName "FidoProdCEO_12"^^xsd:string ;
:hasIssues :issue_1239 .
### http://www.issueonto.com/ontologies/issues#issue_1239
:issue_1239 rdf:type :issues ,
owl:NamedIndividual ;
:issueName "FeatureIssue"^^xsd:string .
The Second ontology has the following:
Project Ontology members (classes):
<http://www.projectexample.com/ontology/project#GroupProject>
<http://www.projectexample.com/ontology/project#Project>
<http://www.projectexample.com/ontology/project#ProjectVersion>
Predicate/Properties:
<http://www.projectexample.com/ontology/project#belongsTo>
<http://www.projectexample.com/ontology/project#dependsOn>
Triple store for the ontology (raw data), I show it here in Turtle format:
#prefix : <http://www.projectexample.com/ontology/project#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix xml: <http://www.w3.org/XML/1998/namespace> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#base <http://www.projectexample.com/ontology/project> .
### http://www.projectexample.com/ontology/project#Apple
:Apple rdf:type :ProjectVersion ,
owl:NamedIndividual ;
:hasProjectName "AppleTowandOne"^^xsd:string ;
:belongsTo :RedBlueCompany .
### http://www.projectexample.com/ontology/project#Fido
:Fido rdf:type :ProjectVersion ,
owl:NamedIndividual ;
:hasProjectName "FidoProdCEO"^^xsd:string ;
:dependsOn :Apple .
### http://www.projectexample.com/ontology/project#RedBlueCompany
:RedBlueCompany rdf:type :GroupProject ,
owl:NamedIndividual ;
:groupName "RedGroupCompant lmt"^^xsd:string .
Question
1- I would like to say, project:projectversion from ontology project same as issues:product from ontology issues, is that possible and how?
2- if question (1) is yes, how could I infer the similar individuals from the shared concepts, i.e, if we say projectversion is same as product it does not mean all the individuals are similar, in the example, i would like to automatically infer the individual issues:Fido type of issue:products is same as the individual prject:Fido type of project:projectversion. From that inferred fact, i would infer automatically that project:Fido issue:hasissue issues:issues_1239. Finally, I would like to run SPARQL query as follow:
SELECT ?product ?issue FROM <namegraph>
WHERE{
?product issues:hasIssues ?issue.
}
The results that I should get as follow:
?product ?issue
--------------------------------------------------------------------------
<http://www.projectexample.com/ontology/project#Fido> <http://www.issueonto.com/ontologies/issues#issue_1239>
<http://www.issueonto.com/ontologies/issues#Fido> <http://www.issueonto.com/ontologies/issues#issue_1239>
I would like to say, project:projectversion from ontology project same
as issues:product from ontology issues, is that possible and how?
All you need is the triple
project:projectversion owl:equivalentClass issues:product
I don't know how you're combining these ontologies; whether you're just loading the data from both into a triple store, or creating a third ontology that imports both and loading that (along with its imports) into a triple store, but somewhere you need that axiom. For a "merging" ontology like this, I'd usually create a third ontology that imports both (but leaving them unchanged) and add the axiom to that third ontology.
2- if question (1) is yes, how could I infer the similar individuals
from the shared concepts, i.e, if we say projectversion is same as
product it does not mean all the individuals are similar, in the
example, i would like to automatically infer the individual
issues:Fido type of issue:products is same as the individual
prject:Fido type of project:projectversion. From that inferred fact, i
would infer automatically that project:Fido issue:hasissue
issues:issues_1239.
You still have told us what criteria you would use to decide that issues:Fido and project:Fido are the same individual. The only apparent similarity that they have is the strings "FidoProdCEO_12" and "FidoProdCEO". Is that what the decision is supposed to be based on? If so, then you could do something like the following. I've created a minimal amount of data for convenience:
#prefix o1: <urn:ex:ont1#> .
#prefix o2: <urn:ex:ont2#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
o1:A a o1:Product ;
o1:productName "ProductA_1234" ;
o1:hasIssue o1:issue42 .
o2:B a o2:ProjectVersion ;
o2:projectName "ProductA" .
o1:Product owl:equivalentClass o2:ProjectVersion .
prefix o1: <urn:ex:ont1#>
prefix o2: <urn:ex:ont2#>
prefix owl: <http://www.w3.org/2002/07/owl#>
select ?product ?issue where {
#-- A *product* is something that's an instance of
#-- o1:Product or another class that's equivalent
#-- to it.
?product a/(owl:equivalentClass|^owl:equivalentClass)* o1:Product
#-- The issues of a product are any of its
#-- o1:hasIssue values, or the o1:hasIssue
#-- value of any product that has a name
#-- beginning with its o2:projectName.
{ ?product o1:hasIssue ?issue }
union
{ ?product o2:projectName ?projectName .
?_product o1:productName ?productName ;
o1:hasIssue ?issue .
filter strstarts(?productName,?projectName)
}
}
------------------------
| product | issue |
========================
| o2:B | o1:issue42 |
| o1:A | o1:issue42 |
------------------------
Of course, the fact that you still end up having to examine projectName and productName values means that the equivalent class axiom isn't actually buying you all that much (at least in terms of this query). That is, it would be sufficient to just ask for "products (and projects with matching names) and their issues." That is, you get the same results from this query, which is just the second part of the first query:
prefix o1: <urn:ex:ont1#>
prefix o2: <urn:ex:ont2#>
prefix owl: <http://www.w3.org/2002/07/owl#>
select ?product ?issue where {
{ ?product o1:hasIssue ?issue }
union
{ ?product o2:projectName ?projectName .
?_product o1:productName ?productName ;
o1:hasIssue ?issue .
filter strstarts(?productName,?projectName)
}
}
The solution here is an owl:equivalentClass relation. To make this work you have to perform the following tasks:
Create and RDF document into which you place the owl:equivalentClass relation -- alternatively you can use SPARQL 1.1 INSERT to place the relation into a Virtuoso hosted Named Graph
Create an Inference Rule that functions as a Context-Lense when viewing the data in Virtuoso -- be it via SPARQL Query Results of an Entity Description Page etc.
Command (issued via SQL CommandLine of Conductor UI) for associating a Named Graph with an Inference Rule:
RDFS_RULE_SET ('{rule-name}', '{named-graph-uri-or-rdf-document-url}');
Links:
Sample file (note SQL part is commented out re., Rules and Named Graph association)
Live Example -- showcasing owl:equivalentClass reasoning via Schema.org, FOAF, and GoodRelations ontologies.
I am trying to extract the hierarchy of Wikipedia category or Yago classification for DBpedia resources using the SPARQL endpoint. For instance, I would like to find out all the possible categories and classes in hierarchical form of entity, say, http://dbpedia.org/resource/Nokia, like Thing → Organization → Company → … → Nokia.
A simple SPARQL select can retrieve the information that you're interested in, though it won't be arranged hierarchically. You're interested in getting all the types of a resource, as well as the rdfs:subClassOf relations between them. Here's a very simple query for Nokia that can be run on the DBpedia SPARQL endpoint
SELECT * WHERE {
dbpedia:Nokia a ?c1 ; a ?c2 .
?c1 rdfs:subClassOf ?c2 .
}
SPARQL results
If you treat each pair of classes in that result set as a directed edge and perform a topological sort , then you'll see the hierarchy of the classes to which the Nokia resource belongs. In fact, since it is probably convenient to treat this as a graph, you can get it in the form of an RDF graph by using a SPARQL construct query.
CONSTRUCT WHERE {
dbpedia:Nokia a ?c1 ; a ?c2 .
?c1 rdfs:subClassOf ?c2 .
}
SPARQL results
The construct query produces this graph (in N3 format):
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix dbpedia-owl: <http://dbpedia.org/ontology/> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix yago: <http://dbpedia.org/class/yago/> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix dbpedia: <http://dbpedia.org/resource/> .
dbpedia-owl:Agent rdfs:subClassOf owl:Thing .
dbpedia-owl:Company rdfs:subClassOf dbpedia-owl:Organisation .
dbpedia-owl:Organisation rdfs:subClassOf dbpedia-owl:Agent .
yago:CompaniesBasedInEspoo rdfs:subClassOf yago:Company108058098 .
dbpedia:Nokia rdf:type yago:CompaniesListedOnTheHelsinkiStockExchange ,
owl:Thing ,
yago:CompaniesBasedInEspoo ,
dbpedia-owl:Agent ,
yago:DisplayTechnologyCompanies ,
yago:ElectronicsCompaniesOfFinland ,
dbpedia-owl:Company ,
dbpedia-owl:Organisation ,
yago:Company108058098 ,
yago:CompaniesEstablishedIn1865 .
yago:CompaniesEstablishedIn1865 rdfs:subClassOf yago:Company108058098 .
yago:CompaniesListedOnTheHelsinkiStockExchange rdfs:subClassOf yago:Company108058098 .
yago:DisplayTechnologyCompanies rdfs:subClassOf yago:Company108058098 .
yago:ElectronicsCompaniesOfFinland rdfs:subClassOf yago:Company108058098 .
Remarks
The queries above retrieve the rdf:type hierarchy for Nokia. In the question, you also mention Wikipedia categories. DBpedia resources are associated with the Wikipedia categories to which their corresponding articles belong by the dcterms:subject property. Those Wikipedia categories are then structured hierarchically by skos:broader. These really are not types for the individuals though. For instance, the data contain:
dbpedia:Nokia dcterms:subject category:Finnish_brands
category:Finnish_brands skos:broader category:Brands_by_country
While it probably makes sense to say that Nokia is a Finnish_brand, it makes much less sense to say that Nokia is a Brand_by_country.