Can I constrain the owl:onProperties when traversing over owl:Restrictions? - sparql

I'd like to use ChEBI to determine which molecular entities could be considered "taxanes", in the informal language that physicians use.
The Anatomical and Therapeutic Classification places both docetaxel and paclitaxel in class L01CD "Taxanes", but in ChEBI the paths include both subclass relations and
'has parent hydride' some 'taxane' relations, from an OWL perspective. The following SPARQL finds both docetaxel and paclitaxel
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
select * where {
?drug (rdfs:subClassOf|owl:someValuesFrom)*
<http://purl.obolibrary.org/obo/CHEBI_36064> .
optional {
?drug rdfs:label ?l .
}
}
order by ?l
I'm not explicitly requiring here that the owl:someValuesFrom predicate is applied to an owl:Restiction in the rdfs:subClassOf path. How could I limit this query so that only certain owl:onPropertys (like 'has parent hydride') are allowed in combination with that implicit owl:Restriction?
I'm afraid that this query is dangerously under specified as it is.

Related

Construct loop in SPARQL

The following SPARQL query
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix msc: <http://msc.org/resources/MSC/msc2020/>
construct {?s skos:broader msc:00-XX . }
where
{
?s a skos:Concept ; skos:notation ?notation.
filter regex (?notation, "00-\d\d")
}
searches all notations 00-01, 00-02, etc. and constructs a relation to the top level class 00-XX. However, this is only the first of 63 top level classes altogether, so I would like to "loop" over all top level classes automatically. On top, I would like to adapt this to other patterns. Is there a way to do this with SPARQL? If not, what would you recommend instead?
In the meantime we found a solution without SPARQL.
The SPARQL CONSTRUCT query was supposed to create a skos:broader relation between a skos:Concept with a notation like "00-01" (and all other concepts with 00-\d\d notation) and its proper subordinate concept, which for 00-01 is the skos:Concept with the notation 00-XX.
The data originate from a table and Open Refine is much faster in creating the skos:broader statements than using the SPARQL query proposed above and adjusting it to other notation patterns.
We use GREL's value.replace on the cells with the notations to create a new column:
value.replace(/-\d\d/, "-XX").replace(/\d\d>/, "xx>")
The two replacements give us the notation of the original notation's superordinate concept in one step. The second replace already adapts to the other patterns mentioned in the question (e.g. 00A01).
With the original notation and the value in the new column, we can easily create the skos:broader triples by concatenating text and the values from both columns. These can then be exported from OpenRefine and just be copy-pasted to our SKOS vocabulary.
Here is a SPARQL answer based on the query in the question. Using filters and regex (as suggested in the comment by Yahalnaut as a reply to UninforomedUser above) is needed. Creating a skos:broader relation based on two concept's notations requires them to hava an identical sequence of digits before the - . The comparison should only between the first part of the notations, so each 00- should match another 00-but not a 01-. As asked, the solution below only considers topConcepts of the Vocabulary as potential objects for skos:broader. The concepts should also not relate to themselves, therefore the last filter. This should then be adoptable to other patterns as well. Depending on the number of Concepts and the memory available for the query, this may last a while or even stop before finished. It eliminates lot of the effort though.
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix msc: <http://msc.org/resources/MSC/msc2020/>
construct {?s skos:broader ?y . }
where {
?s a skos:Concept ; skos:notation ?notation.
?y skos:topConceptOf msc: ; skos:notation ?not2.
bind (REPLACE (?not2 , "-XX" , "") as ?1)
bind (REPLACE (?notation , "-\d\d", "" ) as ?2 )
filter (?1 = ?2)
filter (?not2 != ?notation)
}

skos broader and narrow inverse not working

I have setup GraphDB SE trial version and trying out inference functionality with OWL2-RL ruleset. I have built a simple SKOS knowledge with a single broader relationship. Some how, when I try to query for narrower relationship am not getting any results. Am I going wrong in the usage ?
Insertion:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
INSERT DATA {
ex:mammals rdf:type skos:Concept;
skos:prefLabel "mammals"#en;
ex:animals rdf:type skos:Concept;
skos:prefLabel "animals"#en;
skos:broader ex:mammals .
}
Query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
select * where {
?s skos:narrower ?o .
}
In the query result I don't see any response. Shouldn't it return below result -
ex:mammals skos:narrower ex:animals
I just came across this question and the OP is correct: Although the official SKOS reference explicitly states that skos:broader and skos:narrower are inverse, the actual RDF implementation does not include this statement. However, properties skos:broaderTransitive and skos:narrowerTransitive are declared as inverse.
And, although not relevant to the original question, the implementation does not state properties skos:topConceptOf and skos:hasTopConcept as inverse either.

DBPedia-France (fr.dpbedia.org/sparql) query giving different result from a call to another

I'm calling on http://fr.dbpedia.org/sparql
the following SPARQL query:
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select distinct ?lcs where {
{
?lcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class .
filter not exists {
?llcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class ;
rdfs:subClassOf+ ?lcs .
}
}
}
On some call I've http://dbpedia.org/ontology/Person as result, on others call I'm getting http://dbpedia.org/ontology/Person and http://dbpedia.org/ontology/Agent and with others the previous answers plus http://www.w3.org/2002/07/owl#Thing
without nothing to know that a response isn't complete. How can I use the result, if it is a little randomized
The main reason for your query not working as expected is that the data the data is i) split into separate graphs and ii) not all graphs were added to the default graph.
To keep it short, the instance data is contained inside the graph http://fr.dbpedia.org whereas the schema triples will be accessible via http://dbpedia.org graph only. Sometimes, if no graph is given, then the union of some graphs is used as the default graph which will be the dataset at query time. Unfortunately, this doesn't hold for the French DBpedia endpoint, only the instance data graph will be used.
You can check this with
DESCRIBE <http://dbpedia.org/ontology/Person>
which is empty when using either no graph explicitly or the graph http://fr.dbpedia.org, but non-empty for graph http://dbpedia.org.
The way to define the default graph is using the keyword FROM. For your query, it should therefore be
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select distinct ?lcs
from <http://fr.dbpedia.org>
from <http://dbpedia.org>
where {
?lcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class .
filter not exists {
?llcs ^(rdf:type/rdfs:subClassOf*) <http://fr.dbpedia.org/resource/Honoré_Daumier> ,
<http://fr.dbpedia.org/resource/Auguste_Rodin>;
a owl:Class ;
rdfs:subClassOf+ ?lcs .
}
}
Note, while this seems to return the correct result, you should also consider the comment from #TallTed regarding possible differences among language chapters (e.g. English vs French Wikipedia as source), release dumps (2016 vs 2018 or even the DBpedia Live) as well as Virtuoso versions used as backend.

How does a SPARQL type expression work internally (e.g. ?a rdf:type ?b)?

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX my: <http://www.ex.com#>
SELECT distinct ?person ?nationality
WHERE{
?person rdf:type ?p.
?person my:Nationality ?nationality.
filter (?nationality = "Some nationality")
}
I have created an ontology in Protege which describes a music production company. I have trouble understanding the SPARQL queries and the way they work.
Some explanations
?person: variable in which I want to output people. They are individuals in Protege
?nationality a variable in which I want to output nationalities. They are
data properties in Protege
Nationality: data property which contains nationalities as strings and every person has one
my: prefix I created
How does this work ?person rdf:type ?p and how does it select the right type? Does it work automatically? I don't feel like I have set the ?person variable as a type Person variable (which is a class I have created and it describes a person as an entity), even though it outputs exactly the outcome I need.
How does this work "?person rdf:type ?p" and how does it select the right type? I don't feel like I have set the ?person variable as a type Person variable (which is a class I have created and it describes a person as an entity), even though it outputs exactly the outcome I need.
It doesn't select the right type. It selects a type, any type (and also any individual). Presumably the reason you are seeing the expect outcome is the second part of your query:
?person my:Nationality ?nationality.
In your data, only person-individuals have this property, so only they will match the full query (even if there are other individuals that have a different type).
How SPARQL works is essentially pattern matching. You specify a template for your RDF graph, the variables in the query are the "holes" in that template. Whichever parts of your graph fit the entire template get returned.
Put another way, your query asks the following: "give me all things that have both a type, and a nationality". There may be many things that have a type, but since only persons have a nationality, only persons are returned.
If you want, you can make it explicit that you are only interested in individuals of type Person, by replacing the variable ?p with the class identifier for persons, for example:
?person rdf:type my:Person.
?person my:Nationality ?nationality.

SPARQL - Inverse Path of dynamic discovered relationship

I have a Graph Database that implements only one side of relationships in the model structures. For instance, All Broader relationships are mapped as skos:broader. All Narrower relationships are mapped as ^skos:broader (for whatever reasons they chose to do this, I have no control over this.)
I am trying to write a SPARQL Query that delivers something like
Query for all relationships of a given IRI, and their associated values.
The goal is to make a JSON or XML Representation of all the content.
Here is what I have working.
PREFIX skosxl: <http://www.w3.org/2008/05/skos-xl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?relation ?value
where
{
<CONCEPT_URI> ?r ?c
OPTIONAL {
?r rdfs:label|skosxl:prefLabel ?l
}
OPTIONAL {
?c skosxl:prefLabel/skosxl:literalForm|skosxl:literalForm ?d .
}
BIND ( if (bound(?d), ?d, ?c) as ?value )
BIND ( if (bound(?l), ?l, strafter(?r, '#')) as ?relation )
}
This works to give me all the concept relationships (IE: Broader), but it does not give me the narrower items (IE: ^broader).
Is there anyway that I can extend this generic query to produce the inverses of any relationships it finds, as well? I Tried simply adding the ^ to the ?r in the where clause but it does not like that syntactically.
Thanks,