Reputation: 30232
What SPARQL syntax allows specifying root node, while consuming relation paths out of this node to a given limit.
Let Graph1
be an anatomical mapping of body parts.
k_anatomy:K403 a k:Anatomy ;
rdfs:label "Finger" ;
k_anatomy:has_parent k_anatomy:K393 .
k_anatomy:K393 a k:Anatomy ;
rdfs:label "Hand" ;
k_anatomy:has_parent k_anatomy:K370 .
k_anatomy:K370 a k:Anatomy ;
rdfs:label "Free Upper Limb" ;
k_anatomy:has_parent k_anatomy:K359 .
k_anatomy:K359 a k:Anatomy ;
rdfs:label "Upper Limb" ;
k_anatomy:has_parent k_anatomy:K358 .
k_anatomy:K358 a k:Anatomy ;
rdfs:label "Limb" ;
k_anatomy:has_parent k_anatomy:K2 .
k_anatomy:K2 a k:Anatomy ;
rdfs:label "Body_by_region" ;
k_anatomy:has_parent k_anatomy:K1 .
k_anatomy:K1 a k:Anatomy ;
rdfs:label "Body" ;
k_anatomy:has_parent k_anatomy:K0 .
Let root
be k_anatomy:K403
(rdfs:label "Finger").
What SPARQL query given IRI = k_anatomy:K403
and relation k_anatomy:has_parent
will compose the following result:
| BodyPart | PartOf |
-----------------------------------------
| Finger | Hand |
| Hand | Free Upper Limb |
| Free Upper Limb | Upper Limb |
| Upper Limb | Limb |
| Limb | Body_by_region |
| Body_by_region | Body |
Upvotes: 1
Views: 293
Reputation: 22052
There's no need to specify a root node for this. This query:
SELECT ?BodyPart ?PartOf
WHERE {
?S rdfs:label ?BodyPart;
k_anatomy:has_parent [ rdfs:label ?PartOf ].
}
will do the trick.
I just ran it on a local RDF4J Console. Output:
Evaluating SPARQL query...
+-------------------------------------+-------------------------------------+
| BodyPart | PartOf |
+-------------------------------------+-------------------------------------+
| "Finger" | "Hand" |
| "Hand" | "Free Upper Limb" |
| "Free Upper Limb" | "Upper Limb" |
| "Upper Limb" | "Limb" |
| "Limb" | "Body_by_region" |
| "Body_by_region" | "Body" |
+-------------------------------------+-------------------------------------+
6 result(s) (36 ms)
One caveat: the order of the solutions here is arbitrary, it just happens to align nicely with your expected results because the RDF4J engine in this case just spits results back out in the order in which they occurred in the original file - but that's not guaranteed to happen every time, and certainly not across triplestore implementations.
Update if your store contains more data than just the input file you provided, then to get the result you want you will need a slightly more complex query. Specifically, you will need to use a so-called "property path" expression. This allows you specify that you want arbitrary-length paths starting from a certain point. Like this:
SELECT ?BodyPart ?PartOf
WHERE {
k_anatomy:K393 k_anatomy:has_parent* ?S .
?S rdfs:label ?BodyPart;
k_anatomy:has_parent [ rdfs:label ?PartOf ].
}
You still want body parts with their parents (so the last part of the query is identical to the original query), but now we add an extra constraint by means of a property path to say that values for ?S
must be, through a path of length zero or more, linked to K393
via a has_parent
relation.
Result:
Evaluating SPARQL query...
+-------------------------------------+-------------------------------------+
| BodyPart | PartOf |
+-------------------------------------+-------------------------------------+
| "Hand" | "Free Upper Limb" |
| "Free Upper Limb" | "Upper Limb" |
| "Upper Limb" | "Limb" |
| "Limb" | "Body_by_region" |
| "Body_by_region" | "Body" |
+-------------------------------------+-------------------------------------+
5 result(s) (6 ms)
As you can see, this does not list 'Finger' as a result, as expected - though of course this will only work properly if the has_parent
relations do not form a cycle.
Upvotes: 1