SPARQL 不同对

SPARQL Distinct pairs

我有一个 table,其中有相同作者的文档。我需要获取不同的文档对。我做了以下事情:

SELECT DISTINCT ?d1 ?d2  WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && ?d1!=?d2).
}
GROUP BY ?d1 ?d2

但是对于这个 DOC1, DOC2DOC2, DOC1 都在结果中。我需要摆脱其中一对。 这是整个三元组数据库:

@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> . 
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix myns: <http://my.local.namespace#> .

_:doc1 rdf:type myns:Document.
_:doc1 myns:creator _:Pete.
_:doc1 myns:year "2000"^^xsd:integer.
_:doc1 myns:publisher _:p1.

_:doc2 rdf:type myns:Document.
_:doc2 myns:creator _:John.
_:doc2 myns:year "2004"^^xsd:integer.
_:doc2 myns:publisher _:p2.


_:doc3 rdf:type myns:Document.
_:doc3 myns:creator _:Pete.
_:doc3 myns:publisher _:p3.

_:doc4 rdf:type myns:Document.
_:doc4 myns:creator _:Bob.
_:doc4 myns:year "2010"^^xsd:integer.
_:doc4 myns:publisher _:p2.

_:Pete rdf:type myns:Person.
_:Pete myns:knows _:Bob.
_:Pete myns:knows _:John .

_:John rdf:type myns:Person.
_:John myns:age "29"^^xsd:integer.
_:John myns:knows _:Bob.

_:Bob rdf:type myns:Person.
_:Bob myns:age "35"^^xsd:integer.

执行查询后我得到的结果是:

D1  D2
_:891f1e98-b411-4e54-9533-18d530f09c6ddoc1  _:891f1e98-b411-4e54-9533-18d530f09c6ddoc3
_:891f1e98-b411-4e54-9533-18d530f09c6ddoc3  _:891f1e98-b411-4e54-9533-18d530f09c6ddoc1

值得注意的是,从技术上讲,这两对是相同的。我只需要一个(即其中一个就足够了)。我不确定环境特征。但是有芝麻框架

你可以用一个小技巧来做到这一点:将 != 变成 <(或 >),并将值转换为字符串,这样你就可以进行词法比较:

SELECT DISTINCT ?d1 ?d2  WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && STR(?d1) < STR(?d2)).
}
GROUP BY ?d1 ?d2

这是基于这样的想法,即对于任何一对不相等的标识符,一个标识符总是大于另一个(按词法排序)。因此,在任何两对中,实际上只会选择一对。

更新 现在您已经显示了您的数据,我们可以看出问题是您没有使用 IRI 来区分您的文档,而是使用空白节点。上述查询不起作用,因为根据 SPARQL 标准,空白节点是无序的(因此直接通过 < 进行比较不起作用),而且 STR 函数被定义为仅对文字或IRI,不在空白节点上。

最好的解决办法是改变你的数据,并确保你使用正确的 IRIs,因为无论你是否能以某种方式使这个查询对这个数据起作用,结果几乎是无用的:空白节点没有意义在他们的本地范围之外,所以你的查询 returns 的文档标识符不能真正被重用;例如,您将无法执行 SPARQL 查询来获取文档 _:doc1 的任何属性(尽管公平起见,Sesame 在 API 中有解决此问题的方法)。

顺便说一下,将空白节点更改为 IRI 的一个非常简单的方法是将 turtle 文件中出现的所有 _: 替换为 myns:

这将在一些 系统中工作:

SELECT ?d1 ?d2  WHERE {
  ?d1 myns:creator ?x.
  ?d2 myns:creator ?y.
  FILTER (?x=?y && STR(IRI(?d1)) < STR(IRI(?d2))).
}

?d1?d2 将成为空白节点。但是空白节点是空白的。 因此,要为 < 提供排序,我们需要某种查询范围内的标签或与每个关联的值。

您的数据没有任何可区分的三元组 person.It 最好将真实姓名放入数据中:

_:Pete rdfs:label "Pete" .

更好的是,使用 FOAF 词汇。

有些系统允许 IRI() 中的空白节点 - 从技术上讲,它是 SPARQL 规范的扩展。然后,您可以采用 STR 形式进行比较。对我有用的数据 (Apache Jena) - 你没有说你使用的是哪个 RDF 系统。

最好的解决方案是将区分信息放入数据中。