使用 SPARQL 查找列表中元素的相对位置
Finding the relative position of elements in a list using SPARQL
我正在尝试 return 基于主题在有序列表中的相对位置的主题。
一个主题可以与多个对象相关联(通过单个谓词),并且所有对象都在有序列表中。给定此列表中的参考对象,我想 return 按照对象与参考对象的相对距离顺序排列对象。
:a : :x
:b : :v
:b : :z
:c : :v
:c : :y
:ls :list (:v :w :x :y :z)
以x为我们在列表中的起始对象,下面的代码returns
:a :x :0
:c :y :1
:b :v :2
:b :z :2
:c :v :2
而不是 return 所有位置我只想 'distance' 与主题的最小对象相关的对象 returned (这可能意味着每个主题最多两个对象- 上下列表)。所以我想 return
:a :x :0
:c :y :1
:b :v :2
:b :z :2
到目前为止的代码...
(在 and Is it possible to get the position of an element in an RDF Collection in SPARQL? 的大力帮助下)
SELECT ?s ?p (abs(?refPos-?pos) as ?dif)
WHERE {
:ls :list/rdf:rest*/rdf:first ?o .
?s : ?o .
{
SELECT ?o (count(?mid) as ?pos) ?refPos
WHERE {
[] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node .
?node rdf:first ?o .
{
SELECT ?o (count(?mid2) as ?refPos)
WHERE {
[] :list/rdf:rest* ?mid2 . ?mid2 rdf:rest* ?node2 .
?node2 rdf:first :x .
}
}
}
GROUP BY ?o
}
}
GROUP BY ?s ?o
ORDER BY ?dif
我一直在尝试通过按 ?s 分组来获得最小 ?dif (difference/distance),但是因为我必须将此(类似于 ?dif = ?minDif)应用于 ?s? o 之前的分组我不知道如何在这两个分组之间来回移动。
感谢您提供的任何帮助
复合解决方案所需要的只是另一个 Joshua Taylor 的答案: or this。
下面我使用的是 Jena 函数,但我希望思路清晰。
查询 1
PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
SELECT ?s ?el ?dif {
?s : ?el .
:ls :list/list:index (?pos ?el) .
:ls :list/list:index (?ref :x) .
BIND (ABS(?pos -?ref) AS ?dif)
{
SELECT ?s (MIN (?dif_) AS ?dif) WHERE {
?s : ?el_ .
:ls :list/list:index (?pos_ ?el_) .
:ls :list/list:index (?ref_ :x) .
BIND (ABS(?pos_ - ?ref_) AS ?dif_)
} GROUP by ?s
}
}
查询 2
PREFIX list: <http://jena.apache.org/ARQ/list#>
SELECT ?s ?el ?dif {
?s : ?el .
:ls :list/list:index (?pos ?el) .
:ls :list/list:index (?ref :x) .
BIND (ABS(?pos -?ref) AS ?dif)
FILTER NOT EXISTS {
?s : ?el_ .
:ls :list/list:index (?pos_ ?el_) .
BIND (ABS(?pos_ - ?ref) AS ?dif_) .
FILTER(?dif_ < ?dif)
}
}
更新
查询 1 可以这样重写:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?s ?el ?dif {
?s : ?el
{ select (count(*) as ?pos) ?el {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el} group by ?el }
{ select (count(*) as ?ref) {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} }
BIND (ABS(?pos - ?ref) AS ?dif)
{
SELECT ?s (MIN(?dif_) AS ?diff) {
?s : ?el_
{ select (count(*) as ?pos_) ?el_ {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el_} group by ?el_ }
{ select (count(*) as ?ref_) {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} }
BIND (ABS(?pos_ - ?ref_) AS ?dif_)
} GROUP by ?s
}
FILTER (?dif = ?diff)
}
备注
- 如您所见,这不是 SPARQL 的设计目的。例如,Blazegraph 支持 Gremlin...
- 可能这不是 RDF 的设计目的。或者尝试其他建模方法:您真的需要 RDF 列表吗?
- 我还没有在 Virtuoso 中测试过上面的查询。
我正在尝试 return 基于主题在有序列表中的相对位置的主题。
一个主题可以与多个对象相关联(通过单个谓词),并且所有对象都在有序列表中。给定此列表中的参考对象,我想 return 按照对象与参考对象的相对距离顺序排列对象。
:a : :x
:b : :v
:b : :z
:c : :v
:c : :y
:ls :list (:v :w :x :y :z)
以x为我们在列表中的起始对象,下面的代码returns
:a :x :0
:c :y :1
:b :v :2
:b :z :2
:c :v :2
而不是 return 所有位置我只想 'distance' 与主题的最小对象相关的对象 returned (这可能意味着每个主题最多两个对象- 上下列表)。所以我想 return
:a :x :0
:c :y :1
:b :v :2
:b :z :2
到目前为止的代码...
(在
SELECT ?s ?p (abs(?refPos-?pos) as ?dif)
WHERE {
:ls :list/rdf:rest*/rdf:first ?o .
?s : ?o .
{
SELECT ?o (count(?mid) as ?pos) ?refPos
WHERE {
[] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node .
?node rdf:first ?o .
{
SELECT ?o (count(?mid2) as ?refPos)
WHERE {
[] :list/rdf:rest* ?mid2 . ?mid2 rdf:rest* ?node2 .
?node2 rdf:first :x .
}
}
}
GROUP BY ?o
}
}
GROUP BY ?s ?o
ORDER BY ?dif
我一直在尝试通过按 ?s 分组来获得最小 ?dif (difference/distance),但是因为我必须将此(类似于 ?dif = ?minDif)应用于 ?s? o 之前的分组我不知道如何在这两个分组之间来回移动。
感谢您提供的任何帮助
复合解决方案所需要的只是另一个 Joshua Taylor 的答案:
下面我使用的是 Jena 函数,但我希望思路清晰。
查询 1
PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
SELECT ?s ?el ?dif {
?s : ?el .
:ls :list/list:index (?pos ?el) .
:ls :list/list:index (?ref :x) .
BIND (ABS(?pos -?ref) AS ?dif)
{
SELECT ?s (MIN (?dif_) AS ?dif) WHERE {
?s : ?el_ .
:ls :list/list:index (?pos_ ?el_) .
:ls :list/list:index (?ref_ :x) .
BIND (ABS(?pos_ - ?ref_) AS ?dif_)
} GROUP by ?s
}
}
查询 2
PREFIX list: <http://jena.apache.org/ARQ/list#>
SELECT ?s ?el ?dif {
?s : ?el .
:ls :list/list:index (?pos ?el) .
:ls :list/list:index (?ref :x) .
BIND (ABS(?pos -?ref) AS ?dif)
FILTER NOT EXISTS {
?s : ?el_ .
:ls :list/list:index (?pos_ ?el_) .
BIND (ABS(?pos_ - ?ref) AS ?dif_) .
FILTER(?dif_ < ?dif)
}
}
更新
查询 1 可以这样重写:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?s ?el ?dif {
?s : ?el
{ select (count(*) as ?pos) ?el {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el} group by ?el }
{ select (count(*) as ?ref) {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} }
BIND (ABS(?pos - ?ref) AS ?dif)
{
SELECT ?s (MIN(?dif_) AS ?diff) {
?s : ?el_
{ select (count(*) as ?pos_) ?el_ {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el_} group by ?el_ }
{ select (count(*) as ?ref_) {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} }
BIND (ABS(?pos_ - ?ref_) AS ?dif_)
} GROUP by ?s
}
FILTER (?dif = ?diff)
}
备注
- 如您所见,这不是 SPARQL 的设计目的。例如,Blazegraph 支持 Gremlin...
- 可能这不是 RDF 的设计目的。或者尝试其他建模方法:您真的需要 RDF 列表吗?
- 我还没有在 Virtuoso 中测试过上面的查询。