查找属性path中的所有步骤

我是新来的SPARQL,我试图创build一个属性path查询,将吐出沿path的每个中间步骤。 到目前为止,我有这样的:

select ?object where { <subjectURI> <isRelatedTo>+ ?object . } 

这给了我一个关于整个path的主题URI的所有关系的列表,不pipe这个关系有多远(如果我错了,请纠正我的错误)。

但是,我想看看这些关系是如何组织的。 就像是:

 <subjectURI> <isRelatedTo> <object1> <object1> <isRelatedTo> <object2> <object2> <isRelatedTo> <object3> 

等等…这可能吗?

不,这是属性pathdevise的限制。

path可以用来压缩更复杂的查询模式,也可以用来testing任意长度的path,就像你的例子。

前者可能被转换成一个给你中间步骤的forms,例如

 SELECT * WHERE { ?s <http://predicate>/<http://predicate> ?o } 

可以转换为以下内容:

 SELECT * WHERE { ?s <http://predicate> ?intermediate . ?intermediate <http://predicate> ?o . } 

不幸的是,对于任意长度的path,这是不可能的。 但是,如果你知道path的上限是什么,你可以像这样重写你的查询:

 SELECT * WHERE { { ?s <http://predicate> ?step1 . ?step1 <http://predicate> ?o . } UNION { ?s <http://predicate> ?step1 . ?step1 <http://predicate> ?step2 . ?step2 <http://predicate> ?o . } # Add additional UNION for each length of path you want up to your upper bound } 

虽然你可以立即看到这使得事情非常冗长。

尽pipe属性path可以做什么有一些限制 ,根据您的具体要求,您可以在此获得所需的内容。 考虑这些数据:

 @prefix : <urn:ex:>. :a :relatedTo :b . :b :relatedTo :c . :c :relatedTo :d . :a :relatedTo :e . :e :relatedTo :f . :f :relatedTo :g . :h :relatedTo :i . :i :relatedTo :j . :j :relatedTo :k . :k :relatedTo :l . 

其中有三个:relatedTopath:

 a --> b --> c --> d a --> e --> f --> g h --> i --> j --> k --> l 

我知道在你的情况下,你有一个特定的主题,但我们可以概括一点,并要求每个这样的path中的每个边缘,像这样的查询:

 prefix : <urn:ex:> select * where { # start a path ?begin :relatedTo* ?midI . FILTER NOT EXISTS { [] :relatedTo ?begin } # grab next edge ?midI :relatedTo ?midJ . # get to the end of the path. ?midJ :relatedTo* ?end . FILTER NOT EXISTS { ?end :relatedTo [] } } order by ?start ?end 
 $ arq --data data.n3 --query query.sparql ----------------------------- | begin | midI | midJ | end | ============================= | :a | :a | :b | :d | | :a | :b | :c | :d | | :a | :c | :d | :d | | :a | :a | :e | :g | | :a | :e | :f | :g | | :a | :f | :g | :g | | :h | :h | :i | :l | | :h | :i | :j | :l | | :h | :j | :k | :l | | :h | :k | :l | :l | ----------------------------- 

其中显示了每条边的:relatedTopath。 你也可以使输出更漂亮些:

 prefix : <urn:ex:> select (concat(str(?begin),"--",str(?end)) as ?path) ?midI ?midJ where { # start a path ?begin :relatedTo* ?midI . FILTER NOT EXISTS { [] :relatedTo ?begin } # grab next edge ?midI :relatedTo ?midJ . # get to the end of the path. ?midJ :relatedTo* ?end . FILTER NOT EXISTS { ?end :relatedTo [] } } order by ?path 
 $ arq --data data.n3 --query query.sparql -------------------------------------- | path | midI | midJ | ====================================== | "urn:ex:a--urn:ex:d" | :a | :b | | "urn:ex:a--urn:ex:d" | :b | :c | | "urn:ex:a--urn:ex:d" | :c | :d | | "urn:ex:a--urn:ex:g" | :a | :e | | "urn:ex:a--urn:ex:g" | :e | :f | | "urn:ex:a--urn:ex:g" | :f | :g | | "urn:ex:h--urn:ex:l" | :h | :i | | "urn:ex:h--urn:ex:l" | :i | :j | | "urn:ex:h--urn:ex:l" | :j | :k | | "urn:ex:h--urn:ex:l" | :k | :l | -------------------------------------- 

同样的方法可以让你做一些有趣的事情,比如找出离开某个节点有多远:

 prefix : <urn:ex:> select ?begin ?end (count(*) as ?length) where { # start a path ?begin :relatedTo* ?midI . FILTER NOT EXISTS { [] :relatedTo ?begin } # grab next edge ?midI :relatedTo ?midJ . # get to the end of the path. ?midJ :relatedTo* ?end . FILTER NOT EXISTS { ?end :relatedTo [] } } group by ?begin ?end 
 ------------------------ | begin | end | length | ======================== | :a | :g | 3 | | :a | :d | 3 | | :h | :l | 4 | ------------------------ 

在上面提供的数据中,path碰巧是按照字母顺序排列的,所以sorting按照正确的顺序产生边。 但是,即使边缘节点不是按字母顺序排列的,我们仍然可以通过计算它们在列表中的位置来按顺序打印它们。 这个查询:

 prefix : <urn:ex:> select ?begin ?midI ?midJ (count(?counter) as ?position) ?end where { ?begin :relatedTo* ?counter . ?counter :relatedTo* ?midI . FILTER NOT EXISTS { [] :relatedTo ?begin } ?midI :relatedTo ?midJ . ?midJ :relatedTo* ?end . FILTER NOT EXISTS { ?end :relatedTo [] } } group by ?begin ?end ?midI ?midJ 
 ---------------------------------- | begin | midI | midJ | .1 | end | ================================== | :a | :a | :b | 1 | :d | | :a | :b | :c | 2 | :d | | :a | :c | :d | 3 | :d | | :a | :a | :e | 1 | :g | | :a | :e | :f | 2 | :g | | :a | :f | :g | 3 | :g | | :h | :h | :i | 1 | :l | | :h | :i | :j | 2 | :l | | :h | :j | :k | 3 | :l | | :h | :k | :l | 4 | :l | ---------------------------------- 

我们没有必要去看那个数字,但是你可以不用select这个位置,而是将它用作sorting条件:

 prefix : <urn:ex:> select ?begin ?midI ?midJ ?end where { ?begin :relatedTo* ?counter . ?counter :relatedTo* ?midI . FILTER NOT EXISTS { [] :relatedTo ?begin } ?midI :relatedTo ?midJ . ?midJ :relatedTo* ?end . FILTER NOT EXISTS { ?end :relatedTo [] } } group by ?begin ?end ?midI ?midJ order by ?begin ?end count(?counter) 

并保证让你的边缘顺序。