是否有可能得到一个RDF集合中SPARQL元素的位置?是否有可能得到一个RDF集合中SPARQL元素

2019-05-08 16:43发布

假设我有以下龟声明:

@prefix : <http://example.org#> .

:ls :list (:a :b :c)

有没有办法让集合中的元素的位置?

例如,此查询:

PREFIX :     <http://example.org#>
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 

SELECT ?elem WHERE {
 ?x :list ?ls .
 ?ls rdf:rest*/rdf:first ?elem .
}

我得到:

--------
| elem |
========
| :a   |
| :b   |
| :c   |
--------

但我想查询获得:

--------------
| elem | pos |
==============
| :a   |  0  |
| :b   |  1  |
| :c   |  2  |
--------------

可能吗?

Answer 1:

一个纯洁SPARQL 1.1解决方案

我已经扩展了数据使问题有点困难。 让我们重复的元素添加到列表中,例如,额外的:a底:

@prefix : <http://example.org#> .

:ls :list (:a :b :c :a) .

然后,我们可以使用这样的查询,提取与列表中的节点的位置沿每个列表节点(和它的元素)。 我们的想法是,我们可以在列表中的所有各个节点匹配像模式[] :list/rdf:rest* ?node 。 每个节点的位置 ,不过,是该列表的头部和之间的中间节点的数量?node 。 我们可以通过打破模式分解成相互匹配的中间节点

[] :list/rdf:rest* ?mid . ?mid rdf:rest* :node .

那么,如果我们按?node ,不同的数量?mid绑定的位置?node列表。 因此,我们可以使用下面的查询(其也抓住元素( rdf:first与每个节点相关联的)),以获得在所述列表中的元素的位置:

prefix : <https://stackoverflow.com/q/17523804/1281433/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

select ?element (count(?mid)-1 as ?position) where { 
  [] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node .
  ?node rdf:first ?element .
}
group by ?node ?element
----------------------
| element | position |
======================
| :a      | 0        |
| :b      | 1        |
| :c      | 2        |
| :a      | 3        |
----------------------

这样做是因为一个RDF列表的结构是这样的一个链表(其中?head是列表(的对象的开头:list ),并且是另一个结合?mid因为该模式的[] :list/rdf:rest* ?mid ):

与耶拿ARQ扩展比较

这个问题的提问者还贴出答案使用耶拿的ARQ扩展与RDF名单的工作。 张贴在这个问题的答案的解决方案是

PREFIX :     <http://example.org#>
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>

SELECT ?elem ?pos WHERE {
 ?x :list ?ls .
 ?ls list:index (?pos ?elem).
}

这个问题的答案取决于使用耶拿的ARQ和有利的扩展,但它更简洁和透明。 什么是不很明显是一个是否具有显着较好的性能。 事实证明,对小名单,差别不是特别显著,但对于大名单中,ARQ扩展具有更好的性能。 对于纯SPARQL查询运行时很快变得过于长,而有使用ARQ扩展的版本几乎没有差别。

-------------------------------------------
| num elements | pure SPARQL | list:index |
===========================================
|      50      |    1.1s     |    0.8s    |
|     100      |    1.5s     |    0.8s    |
|     150      |    2.5s     |    0.8s    |
|     200      |    4.8s     |    0.8s    |
|     250      |    9.7s     |    0.8s    |
-------------------------------------------

这些具体的数据将根据您的设置明显的不同,但总的趋势应该是观察到的任何地方。 因为事情可能会改变未来,这里的ARQ的特定版本我使用:

$ arq --version
Jena:       VERSION: 2.10.0
Jena:       BUILD_DATE: 2013-02-20T12:04:26+0000
ARQ:        VERSION: 2.10.0
ARQ:        BUILD_DATE: 2013-02-20T12:04:26+0000

因此,如果我知道 ,我必须处理不平凡规模的名单,我得ARQ可用,我会使用该扩展。



Answer 2:

我已经找到一种方法使用ARQ属性函数库来做到这一点。 正如史蒂夫·哈里斯说,这是不规范的。

PREFIX :     <http://example.org#>
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>

SELECT ?elem ?pos WHERE {
 ?x :list ?ls .
 ?ls list:index (?pos ?elem).
}


Answer 3:

TL; DR - 简短的回答没有用,但长的答案是有如果。

简答

不是没有超出标准步进,除非您的列表是一个约束长度的,那么你可以做一些脏象:

{ ?x :list (:a) BIND(1 AS ?length) }
UNION
{ ?x :list ([], :a) BIND(2 AS ?length) }
UNION
{ ?x :list ([], [], :a) BIND(3 AS ?length) }
...

等等

一些RDF查询引擎非标准功能即会在RDF列表的操作,但你必须咨询你的系统的文档。

长一点的回答

这是有一个可怕的结构和定义RDF列出的症状。 不知怎的,我们结束了代表名单,这两者都是可怕的一起工作的两种不同的方法!

如果你控制了数据,使用一些更明智的表示,例如

<x> :member [
   rdf:value :a ;
   :ordinal 1 ;
], [
   rdf:value :b ;
   :ordinal 2 ;
], [
   rdf:value :c ;
   :ordinal 3 ;
]
...

那么你就可以查询:

{ <x> :member [ rdf:value :a ; :ordinal ?position ] }


文章来源: Is it possible to get the position of an element in an RDF Collection in SPARQL?
标签: rdf sparql