Sparql query for children, grandchildren, .. of a class

走远了吗. 提交于 2019-11-30 15:59:15
Joshua Taylor

This might be answered by Sparql query Subclass or EquivalentTo, but that question and its answer contain a lot more information that what you're asking for here. You can't really enforce the search strategy (depth first vs. depth first), but you can (sort of) order subclasses by their distance from the root, if there's a unique path from the root to the subclass. First, let's get some sample data:

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix : <https://stackoverflow.com/q/23094361/1281433/>.

#            a
#          /   \
#         b     c
#        / \   / \
#       d   e f   g 

:b rdfs:subClassOf :a .
:c rdfs:subClassOf :a .

:d rdfs:subClassOf :b .
:e rdfs:subClassOf :b .

:f rdfs:subClassOf :c .
:g rdfs:subClassOf :c .

You can use a query like this to get the subclasses of :a:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <https://stackoverflow.com/q/23094361/1281433/>

select ?subclass where {
  ?subclass rdfs:subClassOf* :a
}
------------
| subclass |
============
| :a       |
| :c       |
| :g       |
| :f       |
| :b       |
| :e       |
| :d       |
------------

The results include :a because we used the path rdfs:subClassOf*. This is logically correct, since a class is a subclass of itself, but if you don't want :a included, you could use rdfs:subClassOf+, or you could filter out :a with filter( ?subclass != :a ).

In the case that there's a single path from the root to the subclass, you can count the intermediate nodes between them to determine their depth. If you order by depth in this way, then you'll get your results in something like what a breadth first search would give you the following. This technique is described in more detail in Is it possible to get the position of an element in an RDF Collection in SPARQL? and Calculate length of path between nodes?.

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <https://stackoverflow.com/q/23094361/1281433/>

select ?subclass (count(?intermediate)-1 as ?depth) where {
  ?subclass rdfs:subClassOf* ?intermediate .
  ?intermediate rdfs:subClassOf* :a .
}
group by ?subclass
order by ?depth
--------------------
| subclass | depth |
====================
| :a       | 0     |
| :b       | 1     |
| :c       | 1     |
| :d       | 2     |
| :e       | 2     |
| :f       | 2     |
| :g       | 2     |
--------------------
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!