首先,处理一些真实数据总是更容易。我们无法针对我们没有的数据编写真正的 SPARQL 查询。将来,请务必提供一些我们可以使用的样品。现在,这里有一些示例数据,描述了您提到的属性的域和范围。另请注意,属性不连接类;属性连接个人。属性可以具有域和范围,这为我们提供了一种推断与属性相关的个人的附加信息的方法。无论如何,这是数据:
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <https://stackoverflow.com/q/29737549/1281433/> .
:hascountry rdfs:domain :tour ; rdfs:range :country .
:hascity rdfs:domain :country ; rdfs:range :city .
:hasward rdfs:domain :city ; rdfs:range :ward .
:hashouse rdfs:domain :ward ; rdfs:range :house .
现在,请注意,如果您按照 rdfs:domain 属性向后 到 :hascountry,然后按照 rdfs:range 属性向前,您可以从 :tour 到 :country em> 到:国家。在 SPARQL 中,您可以将其写为属性路径:
:tour ^rdfs:domain/rdfs:range :country
如果您可以跟踪该属性路径的链,则可以找到“介于” :tour 和 :house: 之间的所有属性:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <https://stackoverflow.com/q/29737549/1281433/>
select ?domain ?property ?range where {
#-- find ?properties that have a domain
#-- and range...
?property rdfs:domain ?domain ;
rdfs:range ?range .
#-- where there's a ^rdfs:domain to rdfs:range
#-- chain from :tour to ?domain...
:tour (^rdfs:domain/rdfs:range)* ?domain .
#-- and from ?range to :house.
?range (^rdfs:domain/rdfs:range)* :house .
}
-------------------------------------
| domain | property | range |
=====================================
| :ward | :hashouse | :house |
| :city | :hasward | :ward |
| :country | :hascity | :city |
| :tour | :hascountry | :country |
-------------------------------------
“按顺序”获取结果
如果您希望属性“按顺序”从开始类到结束类,您可以计算从开始类到每个属性的距离并按此排序。您可以使用my answer 到Is it possible to get the position of an element in an RDF Collection in SPARQL? 中的技术来做到这一点。这是 SPARQL 查询的样子:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <https://stackoverflow.com/q/29737549/1281433/>
select ?domain ?property ?range
(count(?mid) as ?dist)
where {
#-- find ?properties that have a domain
#-- and range...
?property rdfs:domain ?domain ;
rdfs:range ?range .
#-- where there's a ^rdfs:domain to rdfs:range
#-- chain from :tour to ?domain...
:tour (^rdfs:domain/rdfs:range)* ?domain .
#-- and from ?range to :house.
?range (^rdfs:domain/rdfs:range)* :house .
#-- then, compute the "distance" from :tour
#-- to the property. This is based on binding
#-- ?mid to each class in between them and
#-- taking the number of distinct ?mid values
#-- as the distance.
:tour (^rdfs:domain/rdfs:range)* ?mid .
?mid (^rdfs:domain/rdfs:range)* ?domain .
}
group by ?domain ?property ?range
order by ?dist
--------------------------------------------
| domain | property | range | dist |
============================================
| :tour | :hascountry | :country | 1 |
| :country | :hascity | :city | 2 |
| :city | :hasward | :ward | 3 |
| :ward | :hashouse | :house | 4 |
--------------------------------------------
我在选择中包含了 ?dist 以便我们可以看到这些值。您不必选择它就可以按它排序。你也可以这样做:
select ?domain ?property ?range {
#-- ...
}
group by ?domain ?property ?range
order by count(?mid)
-------------------------------------
| domain | property | range |
=====================================
| :tour | :hascountry | :country |
| :country | :hascity | :city |
| :city | :hasward | :ward |
| :ward | :hashouse | :house |
-------------------------------------