I'm trying to query a dataset which uses the RDF reification vocabulary, something like this:
myprefix:statement1 rdf:subject myprefix:object1 .
myprefix:statement1 rdf:predicate myprefix:isrelatedto .
myprefix:statement1 rdf:object myprefix:object2 .
myprefix:statement2 rdf:subject myprefix:object2 .
myprefix:statement2 rdf:predicate myprefix:isrelatedto .
myprefix:statement2 rdf:object myprefix:object3 .
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix myprefix: <mydomain#>
select *
from <mydomain>
where {
[ rdf:subject ?first ; rdf:predicate myprefix:isrelatedto ; rdf:object _:1 ] .
[ rdf:subject _:1 ; rdf:predicate myprefix:isrelatedto ; rdf:object ?second ] .
}
Result:
__________________ __________________
| first | second |
|__________________|__________________|
| myprefix:object1 | myprefix:object2 |
|__________________|__________________|
Can I replace the labelled blank node _:1 with the [ ] construction somehow?
EDIT: Should explain that the reason for the question was that in the real use case I have a much more complex query that needs to get a variable number of properties like this (the query is generated dynamically). So what I'm trying to do is get rid of the labelled node so that I don't have to generate unique labels dynamically.
[ ] works when there is at most one reference to it.
Here we have:
... rdf:object _:1
... rdf:subject _:1
so two references to the blank node as currently written.
If you can modify the rest of the query, it may be possible. Whether the intent is clearer is something you'll have to make a judgement on.
Because in the part:
[ rdf:subject _:1 ; ....]
isn't using the outer [ ] blank node for anything so it might be possible to have rdf:object/^rdf:subject as suggested in the comment.
Whether the intent is clearer is something you'll have to make a judgement on.
Related
Given the following schema, "driver-passenger" lineages can be easily seen:
tp:trip a owl:Class ;
rdfs:label "trip"#en ;
rdfs:comment "an 'asymmetric encounter' where someone is driving another person."#en .
tp:driver a owl:ObjectProperty ;
rdfs:label "driver"#en ;
rdfs:comment "has keys."#en ;
rdfs:domain tp:trip ;
rdfs:range tp:person .
tp:passenger a owl:ObjectProperty ;
rdfs:label "passenger"#en ;
rdfs:comment "has drinks."#en ;
rdfs:domain tp:trip ;
rdfs:range tp:person .
Consider the following data:
<alice> a tp:person .
<grace> a tp:person .
<tim> a tp:person .
<ruth> a tp:person .
<trip1> a tp:trip ;
tp:participants <alice> , <grace> ;
tp:driver <alice> ;
tp:passenger <grace> .
<trip2> a tp:trip ;
tp:participants <alice> , <tim> ;
tp:driver <alice> ;
tp:passenger <tim> .
<trip3> a tp:trip ;
tp:participants <tim> , <grace> ;
tp:driver <tim> ;
tp:passenger <grace> .
<trip4> a tp:trip ;
tp:participants <grace> , <ruth> ;
tp:driver <grace> ;
tp:passenger <ruth> .
<trip5> a tp:trip ;
tp:participants <grace> , <tim> ;
tp:driver <grace> ;
tp:passenger <tim> .
Now let a "driver-passenger descendent" be any tp:passenger at the end of a trip sequence where the tp:passenger of one trip is the tp:driver of the next trip
Ex. <ruth> is a descendent of <alice> according to the following sequence of trips:
<trip2> -> <trip3> -> <trip4>.
Question:
How to get the (ancestor,descendent) pairs of all driver-passenger lineages?
Attempt 1:
I initially tried the following CONSTRUCT subquery to define an object property: tp:drove, which can be easily used in a property path. However, this did not work on my actual data:
SELECT ?originalDriver ?passengerDescendent
WHERE {
?originalDriver tp:drove+ ?passengerDescendent .
{
CONSTRUCT { ?d tp:drove ?p . }
WHERE { ?t a tp:trip .
?t tp:driver ?d .
?t tp:passenger ?p .}
}
}
Attempt 2:
I tried to create property path which expresses an ancestor as the driver of a passenger, but I don't think I've properly understood how this is supposed to work:
(tp:driver/^tp:passenger)+
Regarding MWE: Is there some kind of RDF sandbox that would allow me to create an MWE by defining a simple ontology like tp above, along with some sample data? The following "playgrounds" are available but none of them seem to support defining a toy ontology: SPARQL Playground, SPARQL Explorer.
Notes on related content:
This question is directly related to a previous question, but no longer requires saving the paths themselves, a feature not directly supported by SPARQL 1.1.
This answer by Joshua Taylor seems relevant, but doesn't address the identification of specific types of paths, such as the lineages defined above.
This one seems to do the trick:
select ?driver ?passenger where {
?driver (^tp:driver/tp:passenger)+ ?passenger .
filter( ?driver != ?passenger)
}
The filter condition can be removed if you want to also see relationships that lead back to the same person.
I don't think its possible to do what I am asking using regular sparql path queries. I will ask here though in case someone has a great suggestion for me that I haven't tried.
So we have reified geosparql sfWithin and sfContains statements in a linkset. They look like this:
_:b1 rdf:subject :featureA1 ;
rdf:predicate geo:sfWithin ;
rdf:object :featureB301 .
_:b2 rdf:subject :featureB301 ;
rdf:predicate geo:sfContains ;
rdf:object :featureA1 .
_:b3 rdf:subject :featureB301 ;
rdf:predicate geo:sfWithin ;
rdf:object :featureC99 .
_:b4 rdf:subject :featureC99 ;
rdf:predicate geo:sfContains ;
rdf:object :featureB301 .
_:b5 rdf:subject :featureC99 ;
rdf:predicate geo:sfWithin ;
rdf:object :featureD4000 .
There are millions of these in our linkset, within a named graph in our larger graph.
I want to get something like "What are all the features that feature A1 is within?"
In a normal (non-reified) set of statements, we can do:
:featureA1 geo:sfWithin+ ?f .
I've tested that and it works as expected on a de-reified copy of the linkset, I get expected results of:
?f
--
:featureB301
:featureC99
:featureD4000
But I want to do a similar repeating path query on the original reified statements.
The closest I've got it something like this:
<http://example.org/featureA1> (^rdf:subject / rdf:object)+ ?f .
But that follows the sfContains statements as well as the sfWithins. I need just the sfWithin chain.
Attempting to fix I think I need to do something like this:
<http://example.org/featureA1> (^rdf:subject / rdf:predicate / ?p / ^rdf:predicate / rdf:object)+ ?f .
FILTER ( ?p = geo:sfWithin) .
But that doesn't work because you can't capture and compare a variable within a sparql path.
What SPARQL query should I use to show all values of union of two datatypes? Additionally how can I count the number of values in this union of datatypes? Each datatype was defined with DataOneOf(...) axiom.
EDIT: to start with something: what SPARQL query should I use to show all values of the selected datatype?
In the future, it would be much easier if you can provide minimal data that we can work with. It would also make the question a bit clearer. As I understand it, you've defined some datatypes using the dataOneOf construct to enumerate several literals. First, let's create some sample data. Here's an OWL ontology with two properties, each of which has an enmerated datatype expression as its range. One of them has {"one", "two"} as the range, and the other has {1, 2}:
#prefix : <http://example.org/datatypes#> .
#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#> .
:p1 a owl:DatatypeProperty ;
rdfs:range [ a rdfs:Datatype ;
owl:oneOf [ a rdf:List ;
rdf:first 1 ;
rdf:rest [ a rdf:List ;
rdf:first 2 ;
rdf:rest ()
]
]
] .
:p2 a owl:DatatypeProperty ;
rdfs:range [ a rdfs:Datatype ;
owl:oneOf [ a rdf:List ;
rdf:first "one" ;
rdf:rest [ a rdf:List ;
rdf:first "two" ;
rdf:rest ()
]
]
] .
Notice that the list of possible values in the datatype expression are given as an RDF list. It's easiest to query RDF lists using property paths, and there are lots of other examples of that here on Stack Overflow. Here's what the query could look like that will retrieve the datatypes along with each of their elements and the datatype of those elements (in case you want that, too).
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?dt ?element ?elementType {
?dt a rdfs:Datatype ;
owl:oneOf/rdf:rest*/rdf:first ?element .
bind(datatype(?element) as ?elementType)
}
---------------------------------------------------------------
| dt | element | elementType |
===============================================================
| _:b0 | "one" | <http://www.w3.org/2001/XMLSchema#string> |
| _:b0 | "two" | <http://www.w3.org/2001/XMLSchema#string> |
| _:b1 | 1 | <http://www.w3.org/2001/XMLSchema#integer> |
| _:b1 | 2 | <http://www.w3.org/2001/XMLSchema#integer> |
---------------------------------------------------------------
Note that often time such datatypes are represented by blank nodes, which means that they don't have associated IRIs. In this case, for example, they show up as _:b0 and _:b1. Hopefully, though, you have some way to identify the particular datatype expressions that you're interested in, e.g., by asking for the range of some particular property, or something like that.
I just start to learn Semantic Web and have a question about restriction class. I dug a while but haven't found any answer yet.. Any help would be much appreciated!
From text book, I see examples of define restriction class, they are all about to define a anonymous owl:Restriction class bnode and link this bnode with property owl:equivalentClass.
example:
example:restrictionClass owl:equivalentClass [
rdf:type owl:Restriction;
owl:onProperty example:resProp;
owl:someValuesFrom example:resValue.
]
My question is can we define a restriction class directly? Like:
example:restrictionClass rdf:type owl:Restriction;
owl:onProperty example:resProp;
owl:someValuesFrom example:resValue.
What's the advantage to define anonymous owl:Restriction?
No, you can't. The RDF you're seeing is the encoding of the OWL axiom like: EquivalentClasses(C ObjectSomeValuesFrom(p D)). It gets encoded as:
:C owl:equivalentClass [
rdf:type owl:Restriction;
owl:onProperty :p;
owl:someValuesFrom :D .
]
Now, suppose you also had the axiom EquivalentClasses(C ObjectSomeValuesFrom(r E)). That gets encoded as:
:C owl:equivalentClass [
rdf:type owl:Restriction;
owl:onProperty :r;
owl:someValuesFrom :E .
]
Now, if you could apply the abbreviation that you want, you'd get:
:C rdf:type owl:Restriction ;
owl:onProperty :p ;
owl:onProperty :r ;
owl:someValuesFrom :D ;
owl:someValuesFrom :E .
Now there's ambiguity. Which of the following would C be equal to?
ObjectSomeValuesFrom(p D)
ObjectSomeValuesFrom(p E)
ObjectSomeValuesFrom(r D)
ObjectSomeValuesFrom(r E)
From the RDF alone, you don't have a way to tell. You actually need to encode the EquivalentClasses axioms.
Addendum
To address questions from the comments: I used C, p, and D to make the text shorter. Your original RDF snippet is the RDF encoding of the axiom
EquivalentClasses(
example:restrictionClass
ObjectSomeValuesFrom(example:resProp example:resValue)
)
That's what
example:restrictionClass owl:equivalentClass [
rdf:type owl:Restriction;
owl:onProperty example:resProp;
owl:someValuesFrom example:resValue.
]
encodes. example:restrictionClass is the same IRI in both places. The entire blank node is the class expression ObjectSomeValuesFrom(example:resProp example:resValue). Then owl:equivalentClass just relates the two. Note that expressions aren't the same; the classes that they denote are the same. The mapping from OWL ontologies to RDF is given in OWL 2 Web Ontology Language: Mapping to RDF Graphs (Second Edition). Specifically, have a look at Table 1 in 2.1 Translation of Axioms without Annotations where you'll find the rules:
EquivalentClasses( CE1 ... CEn )
------------------------------------
T(CE1) owl:equivalentClass T(CE2) .
...
T(CEn-1) owl:equivalentClass T(CEn) .
and
ObjectSomeValuesFrom( OPE CE )
------------------------------
_:x rdf:type owl:Restriction .
_:x owl:onProperty T(OPE) .
_:x owl:someValuesFrom T(CE) .
When you go in the reverse direction, you can read in the RDF and reconstruct your axiom. But support that the mapping let you do the abbreviation that you're talking about, and you had two equivalent class axioms. You'd end up with ambiguous RDF, since you'd have two owl:onProperty triples, and two owl:someValuesFrom triples.
Maybe an example from arithmetic would help. We know that 4, 2+2, and 1+3 are all expressions that denote the same number. So we can have the axioms:
4 = 2 + 2
4 = 1 + 3
Now suppose that we encode that in RDF with something like:
:four :equals [ rdf:type :sum ; :left :two ; :right :two ] .
:four :equals [ rdf:type :sum ; :left :one ; :right :three ] .
That's nice, and we can reconstruct 4 = 2+2 and 4 = 1+3 from it. Now suppose we tried to move those properties to :four, rather than a blank node related by :equals. We'd end up with:
:four rdf:type :sum .
:four :left :two .
:four :right :two .
:four :left :one .
:four :right :three .
But what axioms is this supposed to represent? You have have four ways of picking a left and right from :four. Which of the following is it supposed to encode?
4 = 2 + 2
4 = 2 + 3
4 = 1 + 2
4 = 1 + 3
I have such a query:
CONSTRUCT {
?p a :IndContainer .
?p :contains ?ind .
} WHERE{
:ClassContainer_1 :contains ?class .
?ind a ?class .
BIND (IRI(...) AS ?p) .
}
An individual ClassContainer_1 relates to some classes. I get this classes and try to find individuals for these classes. Then I try to create an IndContainer that should store found individuals (dots are used only for simplification). So, I want to:
Create individual of IndContainer only when individuals for all bindings of ?class have been found;
Create individuals of IndContainer for all possible sets of individuals from ?ind (i.e. when some of ?class has a nuber of individuals).
Is it possible to create such a SPARQL query? Or it is necessary to use some rule engine?
EDIT (add illustration):
Positive example. Have:
test:ClassContainer_1
rdf:type test:ClassContainer ;
test:contains test:Type1 ;
test:contains test:Type2 ;
.
test:Type1_1
rdf:type test:Type1 ;
.
test:Type1_2
rdf:type test:Type1 ;
.
test:Type2_1
rdf:type test:Type2 ;
.
Want to receive:
test:IndContainer_1
rdf:type test:IndContainer ;
test:contains test:Type1_1 ;
test:contains test:Type2_1 ;
.
test:IndContainer_2
rdf:type test:IndContainer ;
test:contains test:Type1_2 ;
test:contains test:Type2_1 ;
.
Negative example: the same as positive except that there is no individuals of class Type2 and so no individuals of IndContainer should be generated.
EDIT 2 (problem essence):
We may look at this problem from the perspective of combination composing. We have two positions (in my example) in each combination. The number of positions is determined by the number of classes each ClassContainer depends on. Each position must be filled in with one individual of a class that correspond to that position. So in my example first position must be filled with one individual of Type1 class, the second - with Type2 class (but the order does not matter). We have two individuals for the first class and one individual for the second class. To get the number of combinations we may use the rule of product from combinatorics - 2*1 = 2, i.e. {Type1_1,Type2_1} - is the first combination and {Type1_2,Type2_1} - is the second combination. For each combination it is necessary to generate IndContainer individual.
If I understand your question correctly, you want a "container" for each class that is contained in a "class container" that contains the individuals that belong to that class. That's not too hard to do, as long as you can construct the IRI of the container from the IRI of the class. Here's some sample data with two classes, A and B, and a few instances (some of just A, some of just B, and some of A and B):
#prefix : <urn:ex:> .
:container a :ClassContainer ;
:contains :A, :B .
:w a :A . # an :A
:x a :A . # another :A
:y a :B . # a :B
:z a :A, :B . # both an :A and a :B
You query is already pretty close. Here's one that works, along with its result:
prefix : <urn:ex:>
construct {
?indContainer a :IndContainer ;
:contains ?ind .
}
where {
:container a :ClassContainer ;
:contains ?class .
?ind a ?class .
bind(IRI(concat(str(?class),"-container")) as ?indContainer)
}
#prefix : <urn:ex:> .
:B-container a :IndContainer ;
:contains :y , :z .
:A-container a :IndContainer ;
:contains :w , :x , :z .