如何使用SPARQL查询两件事之间的距离

时间:2014-07-02 18:10:24

标签: xml rdf semantic-web

我用RDF / XML创建了一个小地铁地图,并想知道如何查询两站之间的距离。我是SPARQL的新手,不知道如何开始。

“距离”是指,我想知道,两个站之间有多少站。后来,我想计算持续时间,但这是另一点。

这是我的第一个方法:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ex: <http://example.com>

SELECT (count(?mid) as ?distance) WHERE {
  <http://example.com/StopD> ex:via* ?mid .
  ?mid ex:via+ <http://example.com/StopC> .
}

我认为,我的查询不起作用,因为我使用空白节点?不起作用意味着,我没有得到两个停靠点之间的图形数量(如StopA和StopB)。我脑子里有这样的事情:http://answers.semanticweb.com/questions/3491/how-can-i-calculate-the-length-of-a-path-between-2-graph-nodes-in-sparql/24609

这是我的地图草图。这些行旁边的数字表示两个站点之间的行程持续时间:

semantic-metro-map.JPG

我的RDF代码描述了每个电台及其邻居停靠的可用线路和行程持续时间。初看起来它看起来很冗余,但我想在将来包括单向路线(例如公交车),所以我认为第一次尝试是可以的。

RDF(在此处下载文件:http://gopeter.de/misc/metro.rdf

<?xml version="1.0"?>
<rdf:RDF 
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:ex="http://example.com/">

    <rdf:Description rdf:about="http://example.com/StopA">

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopB" />
            <ex:Line rdf:resource="http://example.com/Line1" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopB" />
            <ex:Line rdf:resource="http://example.com/Line2" />     
            <ex:Duration>7</ex:Duration>            
        </ex:via>       

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopD" />
            <ex:Line rdf:resource="http://example.com/Line4" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>               

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopD" />
            <ex:Line rdf:resource="http://example.com/Line2" />     
            <ex:Duration>6</ex:Duration>            
        </ex:via>                       

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopE" />
            <ex:Line rdf:resource="http://example.com/Line1" />     
            <ex:Duration>1</ex:Duration>            
        </ex:via>                               

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopF" />
            <ex:Line rdf:resource="http://example.com/Line4" />     
            <ex:Duration>3</ex:Duration>            
        </ex:via>                                       

    </rdf:Description>

    <rdf:Description rdf:about="http://example.com/StopB">

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopA" />
            <ex:Line rdf:resource="http://example.com/Line1" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopA" />
            <ex:Line rdf:resource="http://example.com/Line2" />     
            <ex:Duration>7</ex:Duration>            
        </ex:via>       

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopC" />
            <ex:Line rdf:resource="http://example.com/Line2" />     
            <ex:Duration>10</ex:Duration>           
        </ex:via>               

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopF" />
            <ex:Line rdf:resource="http://example.com/Line3" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>                       

    </rdf:Description>      

    <rdf:Description rdf:about="http://example.com/StopC">

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopB" />
            <ex:Line rdf:resource="http://example.com/Line2" />     
            <ex:Duration>10</ex:Duration>           
        </ex:via>

    </rdf:Description>  

    <rdf:Description rdf:about="http://example.com/StopD">

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopA" />
            <ex:Line rdf:resource="http://example.com/Line2" />     
            <ex:Duration>6</ex:Duration>            
        </ex:via>

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopA" />
            <ex:Line rdf:resource="http://example.com/Line4" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>       

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopF" />
            <ex:Line rdf:resource="http://example.com/Line3" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>               

    </rdf:Description>      

    <rdf:Description rdf:about="http://example.com/StopE">

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopA" />
            <ex:Line rdf:resource="http://example.com/Line1" />     
            <ex:Duration>1</ex:Duration>            
        </ex:via>

    </rdf:Description>  

    <rdf:Description rdf:about="http://example.com/StopF">

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopA" />
            <ex:Line rdf:resource="http://example.com/Line4" />     
            <ex:Duration>3</ex:Duration>            
        </ex:via>

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopB" />
            <ex:Line rdf:resource="http://example.com/Line3" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>

        <ex:via rdf:parseType="Resource">
            <ex:Stop rdf:resource="http://example.com/StopD" />
            <ex:Line rdf:resource="http://example.com/Line3" />     
            <ex:Duration>2</ex:Duration>            
        </ex:via>               

    </rdf:Description>      

</rdf:RDF>

1 个答案:

答案 0 :(得分:4)

为什么你的不工作

让我们以更容易阅读的Turtle语法(下面)查看您的数据。 StopD使用ex:via属性连接到三个空白节点。这意味着您将?midStopD ex:via* ?mid进行四场比赛。但是,您不会再获得更多信息,因为空白节点没有外部链接,其属性为ex:via。这意味着?mid ex:via+ StopC没有匹配,因为?mid没有任何传出 ex:via links。像?mid ex:Stop/ex:via+ StopC之类的东西会更好,因为ex:Stop链接会让你从空白节点到另一个停止点。

@prefix ex:    <http://example.com/> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

ex:StopD  ex:via  [ ex:Duration  "6" ;
                    ex:Line      ex:Line2 ;
                    ex:Stop      ex:StopA
                  ] ;
        ex:via  [ ex:Duration  "2" ;
                  ex:Line      ex:Line4 ;
                  ex:Stop      ex:StopA
                ] ;
        ex:via  [ ex:Duration  "2" ;
                  ex:Line      ex:Line3 ;
                  ex:Stop      ex:StopF
                ] .

即使您可以添加ex:Stop到您的属性路径,但这仍然不会按照您想要的方式计算距离,因为您不会仅限于一行。也就是说,你会在多条路径上获得优势。

使这项工作

我重新创建了一个更简单的场景:

@prefix : <https://stackoverflow.com/q/24538144/1281433/> .

#             B
#            * *
#        2  *   * 4
#          *     *
#         *       *
#       A +++++++++ C
#             3
#
# *** line 1
# +++ line 2

:StopA a :Stop ; :toLink :Link1 , :Link3 .
:StopB a :Stop ; :toLink :Link2 .
:StopC a :Stop .

:Link1 :hasDuration 2 ;
       :toStop :StopB ;
       :Line1Self :Link1 .

:Link2 :hasDuration 4 ;
       :toStop :StopC ;
       :Line1Self :Link2 .

:Link3 :hasDuration 3 ;
       :toStop :StopC ;
       :Line2Self :Link3 .

每个站点都可以连接到任意数量的链接:toStop。每条链接的行用rolification property表示。例如,link2 line1self link2表示link2在line1上。这意味着我们使用属性路径“保持在正确的位置”。然后,要查找从第1行的stopA到stopB的行程持续时间,您可以使用如下查询:

prefix : <https://stackoverflow.com/q/24538144/1281433/>

select (sum(?duration) as ?length) where {
  :StopA :toLink/(:toStop/:toLink)*/:Line1Self ?link .
  ?link :hasDuration ?duration ;
        :toStop/(:toLink/:Line1Self/:toStop)* :StopC .
}

----------
| length |
==========
| 6      |
----------

要检查其他行,只需更改:LineXSelf属性即可。例如,对于第2行:

prefix : <https://stackoverflow.com/q/24538144/1281433/>

select (sum(?duration) as ?length) where {
  :StopA :toLink/(:toStop/:toLink)*/:Line2Self ?link .
  ?link :hasDuration ?duration ;
        :toStop/(:toLink/:Line2Self/:toStop)* :StopC .
}
----------
| length |
==========
| 3      |
----------

限制

但这种方法有一些局限性。属性路径是您执行此类任意深度查询的唯一选项,但您不能在属性路径中使用变量,这意味着您无法执行以下操作来获取每条线路上的距离:

prefix : <https://stackoverflow.com/q/24538144/1281433/>

select ?line (sum(?duration) as ?length) where {
  values ?line { :Line1Self :Line2Self }

  :StopA :toLink/(:toStop/:toLink)*/?line ?link .
  ?link :hasDuration ?duration ;
        :toStop/(:toLink/?line/:toStop)* :StopC .
}
group by ?line