我是sparql领域的初学者。我写了这个查询:
prefix pp: <http://purl.org/dc/elements/1.1/>
select ?title,?autor1, ?autor2
from <http://gutenberg.lib>
where {
?s pp:title ?title.
?s pp:creator ?ID1.
?ID1 ?p ?autor1.
optional{ ?s pp:creator ?ID2.
?ID2 ?p ?autor2.
}
} order by ?s
我根据guttenberg项目的数据运行它。数据格式为:
S1 pp:title "TITLE11"
S1 pp:creator "CREATOR11"
S1 pp:creator "CREATOR12"
S2 pp:title "TITLE21"
S2 pp:creator "CREATOR21"
S2 pp:creator "CREATOR22"
S2 pp:creator "CREATOR23"
等
我希望我能得到类似的东西:
TITLE11, CREATOR11, CREATOR11
TITLE11, CREATOR11, CREATOR12
TITLE11, CREATOR12, CREATOR11
TITLE11, CREATOR12, CREATOR12
但我得到了类似的东西:
TITLE11, CREATOR11, CREATOR11
TITLE11, CREATOR12, CREATOR12
所以没有笛卡尔积就像SQL一样。
这是Virtuoso中的错误还是功能?
请注意,片段?p
中的?ID1 ?p ?autor1.
存在,因为数据中没有“作者真实姓名”属性。 Guttenberg只提供这样的字符串:{1}用于第一作者,http://www.w3.org/1999/02/22-rdf-syntax-ns#_1
用于第二作者等。
例如(使用真实数据)它看起来像:
http://www.w3.org/1999/02/22-rdf-syntax-ns#_2
并且“神秘”一书中没有其他三元组(标题,作者1作者2)。
答案 0 :(得分:8)
您没有准确地向我们展示数据或结果。如果数据实际上是以下形式:
S1 pp:title "TITLE11"
S1 pp:creator "CREATOR11"
S1 pp:creator "CREATOR12"
creator
属性的值是字符串,那么你不应该
?s pp:creator ?ID1.
?ID1 ?p ?autor1.
因为?ID1
将绑定到一个字符串,然后你不能对第二行有任何匹配,因为字符串不能是RDF三元组的主题。
我从rdf-files.tar.bz2的Current RDF Format部分下载了RDF data available from Project Gutenberg。注意到The Mystery有10008后,我导航到文件cache/epub/10008/pg10008.rdf
,我看到了这些数据(缩写为相关部分):
<http://www.gutenberg.org/ebooks/10008>
dcterms:creator <http://www.gutenberg.org/2009/agents/1635> , <http://www.gutenberg.org/2009/agents/247> ;
dcterms:title "The Mystery" .
<http://www.gutenberg.org/2009/agents/1635>
pgterms:alias "Fabian, Warner" ;
pgterms:name "Adams, Samuel Hopkins" .
<http://www.gutenberg.org/2009/agents/247>
pgterms:name "White, Stewart Edward" .
值得注意的是,我认为该文件中没有使用rdf:Bag
。也许您正在使用也可以下载的旧版RDF格式。如果你致力于使用它,请添加评论,我们也可以做到这一点,但是在可用的情况下使用更新的数据似乎是有益的,所以我将继续这些数据。
如果您希望每个作者组合列出每个标题,您可以使用以下查询来获得结果。 (我注意到你说你期望重复的作者。这对我来说似乎有点不寻常,所以我添加了一个过滤器来删除它们,但如果你真的想要?name_i
和{{},你可以简单地删除过滤器{1}}可以绑定到相同的值。)
?name_j
prefix dcterms: <http://purl.org/dc/terms/>
prefix pgterms: <http://www.gutenberg.org/2009/pgterms/>
select ?title ?name_i ?name_j where {
?work dcterms:title ?title ;
dcterms:creator ?creator_i .
?creator_i pgterms:name ?name_i .
optional {
?work dcterms:creator ?creator_j .
?creator_j pgterms:name ?name_j .
filter( ?creator_i != ?creator_j )
}
}
上面的查询足以让你前进,但你实际上可以让它更简洁。
由于您没有预测---------------------------------------------------------------------
| title | name_i | name_j |
=====================================================================
| "The Mystery" | "Adams, Samuel Hopkins" | "White, Stewart Edward" |
| "The Mystery" | "White, Stewart Edward" | "Adams, Samuel Hopkins" |
---------------------------------------------------------------------
和?creator_i
的值,因此您实际上可以在此处使用空白节点;而不是写作:
?creator_j
你可以写
?work dcterms:title ?title ;
dcterms:creator ?creator_i .
?creator pgterms:name ?name_i .
由于您只关心创建者的一个属性,因此您可以使用属性路径缩短它:
?work dcterms:title ?title ;
dcterms:creator [ pgterms:name ?name_i ] .
完成后,您将获得此查询和结果:
?work dcterms:title ?title ;
dcterms:creator/pgterms:name ?name_i .
prefix dcterms: <http://purl.org/dc/terms/>
prefix pgterms: <http://www.gutenberg.org/2009/pgterms/>
select ?title ?name_i ?name_j where {
?work dcterms:title ?title ;
dcterms:creator/pgterms:name ?name_i .
optional {
?work dcterms:creator/pgterms:name ?name_j .
filter( ?name_i != ?name_j )
}
}