如何使用 sparql 查询检索 2 class 与对象 属性 之间的关系

How can retrieve relation between 2 class with object property using sparql query

假设我们有一个 OWL 文件,其中包含以下具有域和范围的属性:

Domain   Property    Range
----------------------------
tour     hascountry  country
country  hascity     city
city     hasward     ward
ward     hashouse    house

使用 SPARQL,如何获得结果 "between" 旅游和房屋 类?也就是说,属性的域和范围使得从 Tour 到域以及从范围到 House 有 "path"。就这两个类,我们怎么能找到像下面这样的结果呢?似乎需要某种循环,但我不知道如何在 SPARQL 中执行此操作。

|tour    -------- (hascountry) ----- country|
|country -------- (hascity)    ----- city   |
|city    -------- (hasward)    ----- ward   |
|ward    -------- (hashouse)   ----- house  |

首先,使用一些真实数据总是更容易。我们不能针对我们没有的数据编写真正的 SPARQL 查询。将来,请务必提供一些我们可以使用的示例。现在,这里有一些示例数据,描述了您提到的属性的域和范围。另请注意,属性不连接 class;属性连接个人。属性可以有域和范围,这为我们提供了一种方法来 推断 有关与 属性 相关的个体的额外信息。无论如何,这是数据:

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : < .

: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 属性 backward 到达 :hascountry,然后跟随rdfs:range 属性 转发到:国家。在 SPARQL 中,您可以将其写为 属性 路径:

:tour ^rdfs:domain/rdfs:range :country

如果您可以遵循该 属性 路径的 chains,您可以找到 "between" :tour 和 :house:[= 的所有属性19=]

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <

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 |
-------------------------------------

得到结果"in order"

如果您想要从开始 class 到结束 class 的属性 "in order",您可以计算从开始 class 到每个 [=57] 的距离=] 并按此排序。您可以使用 my answer to 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 : <

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    |
--------------------------------------------

我在 select 中包含了 ?dist 以便我们可以看到这些值。您不必 select 它来按它排序。你也可以这样做:

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   |
-------------------------------------