【问题标题】:why sparql query below do not return cartesian product为什么下面的 sparql 查询不返回笛卡尔积
【发布时间】:2014-02-16 22:08:07
【问题描述】:

我是 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

我根据来自古腾堡项目的数据运行它。数据形式为:

 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 中的错误还是功能?

请注意,片段?ID1 ?p ?autor1. 中的?p 之所以存在,是因为数据中没有“作者真实姓名”属性。 Guttenberg 只给出这样的字符串:http://www.w3.org/1999/02/22-rdf-syntax-ns#_1 用于第一作者,http://www.w3.org/1999/02/22-rdf-syntax-ns#_2 用于第二等。


例如(使用真实数据)它看起来像这样:

The Mystery     http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag  http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag

The Mystery     White, Stewart Edward, 1873-1946    White, Stewart Edward, 1873-1946

The Mystery     Adams, Samuel Hopkins, 1871-1958    Adams, Samuel Hopkins, 1871-1958

并且“The Mystery”一书没有其他三元组(title, author1 author2)。

【问题讨论】:

标签: sparql virtuoso


【解决方案1】:

文字不能是主语:

您没有准确地向我们展示数据或结果。如果数据实际上是以下形式:

S1 pp:title "TITLE11"
S1 pp:creator "CREATOR11"
S1 pp:creator "CREATOR12"

如果creator 属性的值是字符串,那么您不应该得到 任何 匹配

?s pp:creator ?ID1.
?ID1 ?p ?autor1.

因为?ID1 会绑定到一个字符串,然后第二行就不能有任何匹配项,因为字符串不能是 RDF 三元组的主题。

重写查询

我从RDF data available from Project GutenbergCurrent RDF Format 部分下载了rdf-files.tar.bz2。在注意到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?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 )
  }
}
---------------------------------------------------------------------
| title         | name_i                  | name_j                  |
=====================================================================
| "The Mystery" | "Adams, Samuel Hopkins" | "White, Stewart Edward" |
| "The Mystery" | "White, Stewart Edward" | "Adams, Samuel Hopkins" |
---------------------------------------------------------------------

【讨论】:

  • 是的,看起来我使用的是旧数据格式。我会尝试更新的,我会看看它会得到什么......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 2017-02-21
  • 2015-05-06
  • 1970-01-01
  • 2016-01-02
  • 2019-06-07
相关资源
最近更新 更多