首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这个联邦SPARQL查询在TopBraid中工作,而在Apache中不工作?

为什么这个联邦SPARQL查询在TopBraid中工作,而在Apache中不工作?
EN

Stack Overflow用户
提问于 2016-07-12 11:45:51
回答 2查看 613关注 0票数 2

我有以下联邦SPARQL查询,如我在TopBraid Composer免费版(Version5.1.4)中所期望的那样工作,但在Apache (2.3.1版)中不起作用:

代码语言:javascript
复制
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX movie: <http://data.linkedmdb.org/resource/movie/>
PREFIX dcterms: <http://purl.org/dc/terms/>

SELECT ?s WHERE {
    SERVICE <http://data.linkedmdb.org/sparql> {
        <http://data.linkedmdb.org/resource/film/1> movie:actor ?actor .
        ?actor movie:actor_name ?actorName .
    }
    SERVICE <http://dbpedia.org/sparql?timeout=30000> {
        ?s ?p ?o .
        FILTER(regex(str(?s), replace(?actorName, " ", "_"))) .
    }
}

我监视在外壳下执行的子SPARQL查询,并注意到TopBraid正确地对http://dbpedia.org/sparql端点执行以下查询:

代码语言:javascript
复制
SELECT  *
WHERE
  { ?s ?p ?o
    FILTER regex(str(?s), replace("Paul Reubens", " ", "_"))
  }

当Apache执行以下子查询时:

代码语言:javascript
复制
 SELECT  *
WHERE
  { ?s  ?p  ?o
    FILTER regex(str(?s), replace(?actorName, " ", "_"))
  }

注意其中的区别;TopBraid将变量?actorName替换为特定的值“Paul”,而Apache则没有。这会导致来自http://dbpedia.org/sparql端点的错误,因为在结果集中使用了?actorName,但没有分配。

这是Apache中的一个bug,还是TopBraid中的一个特性?如何使Apache正确地执行这个联邦查询。

更新1:,以澄清TopBraid和Apache之间的行为差异。TopBraid首先执行linkedmdb.org子查询,然后对linkedmdb.org查询的每个结果执行dbpedia.org子查询(并用来自linkedmdb.org查询的结果替换?actorName )。我假设Apache的行为类似,但是对dbpedia.org的第一个子查询失败了(因为在结果集中使用了actorName,而没有分配),所以它不会继续。但是现在我不确定它是否真的想要多次执行对dbpedia.org的子查询,因为它永远不会执行。

更新2: --我认为TopBraid和Apache都使用Jena/ARQ,但是我注意到,在TopBraid的堆栈跟踪中,包名类似于com.topbraid.jena.*,这可能表明它们使用了Jena/ARQ的修改版本?

更新3:约书亚·泰勒说:“你肯定不会期望第二个服务块会对每个服务块执行吗?”TopBraid和Apache都使用此方法进行以下查询:

代码语言:javascript
复制
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX movie: <http://data.linkedmdb.org/resource/movie/>
PREFIX dcterms: <http://purl.org/dc/terms/>

SELECT ?film ?label ?subject WHERE {
    SERVICE <http://data.linkedmdb.org/sparql> {
        ?film a movie:film .
        ?film rdfs:label ?label .
        ?film owl:sameAs ?dbpediaLink 
        FILTER(regex(str(?dbpediaLink), "dbpedia", "i"))
    }
    SERVICE <http://dbpedia.org/sparql> {
        ?dbpediaLink dcterms:subject ?subject
    }
}
LIMIT 50

但我同意,原则上,他们应该执行两部分,并加入他们,但也许出于性能原因,他们选择了不同的策略?

另外,请注意上面的查询是如何在Apache上工作的,而这个帖子的第一个查询则没有。因此,Apache实际上在这种特殊情况下与TopBraid的行为类似。与在FILTER函数中使用字符串变量(?actorName)中的字符串变量(?actorName)相比,它似乎与在两个三重模式(在Fuseki中工作)中使用URI变量(?dbpediaLink)有关。

EN

回答 2

Stack Overflow用户

发布于 2016-07-12 14:31:06

更新(更简单)响应

在我写的最初的答案(下面)中,我说问题是SPARQL查询是最内部首先执行的。我认为这仍然适用于这里,但我认为这个问题可以更容易地被孤立。如果你有

代码语言:javascript
复制
service <ex1> { ... }
service <ex2> { ... }

然后,结果必须是在端点上分别执行每个查询,然后加入结果时得到的结果。联接将合并所有公共变量具有相同值的结果。例如,

代码语言:javascript
复制
service <ex1> { values ?a { 1 2 3 } }
service <ex2> { values ?a { 2 3 4 } }

将执行,并且在外部查询(2和3)中有两个可能的值用于?一个。在您的查询中,第二个服务不能产生任何结果。如果你采取:

代码语言:javascript
复制
?s ?p ?o .
FILTER(regex(str(?s), replace(?actorName, " ", "_"))) .

在DBpedia上执行它,您不应该得到任何结果,因为?actorName没有绑定,所以筛选器永远不会成功。看来,TopBraid首先执行第一个服务,然后将结果值注入第二个服务。这很方便,但我不认为它是正确的,因为它返回的结果与您首先执行DBpedia查询和执行另一个查询时得到的结果不同。

原始答案

SPARQL中的子查询首先在内部执行。这意味着类似于

代码语言:javascript
复制
select * {
  { select ?x { ?x a :Cat } }
  ?x foaf:name ?name
}

首先找到所有的猫,然后找到它们的名字。X的“候选”值首先由子查询确定,然后将这些值提供给外部查询。现在,当有两个子查询时,例如,

代码语言:javascript
复制
select * {
  { select ?x { ?x a :Cat } }
  { select ?x ?name { ?x foaf:name ?name } }
}

第一个子查询将找到所有的猫。第二个子查询查找所有具有名称的东西的名称,然后在外部查询中,将结果连接起来,只获取猫的名称。在执行第二个子查询期间,第一个子查询中的?x值不可用。(至少在原则上,查询优化器可能会发现某些事情应该受到限制。)

我的理解是,服务块具有相同的语义。在您的查询中,您有:

代码语言:javascript
复制
SERVICE <http://data.linkedmdb.org/sparql> {
    <http://data.linkedmdb.org/resource/film/1> movie:actor ?actor .
    ?actor movie:actor_name ?actorName .
}
SERVICE <http://dbpedia.org/sparql?timeout=30000> {
    ?s ?p ?o .
    FILTER(regex(str(?s), replace(?actorName, " ", "_"))) .
}

您说跟踪显示TopBraid正在执行

代码语言:javascript
复制
SELECT  *
WHERE
  { ?s ?p ?o
    FILTER regex(str(?s), replace("Paul Reubens", " ", "_"))
  }

如果TopBraid已经执行了第一个服务块并获得了唯一的解决方案,那么这可能是一个可以接受的优化,但是如果第一个查询返回了多个针对?actorName的绑定怎么办?您肯定不会期望对每个服务块执行第二个服务块吗?相反,第二个服务块将以编写的方式执行,并将返回一个结果集,该结果集将与第一个结果集连接。

它在Jena中可能“不起作用”的原因是因为第二个查询实际上没有绑定任何变量,所以它几乎需要查看数据中的每个三重,这显然需要很长时间。

我认为您可以通过嵌套服务调用来解决这个问题。如果嵌套的服务全部由“本地”端点启动(即嵌套服务调用不会要求远程端点进行另一个远程查询),那么您可以这样做:

代码语言:javascript
复制
SERVICE <http://dbpedia.org/sparql?timeout=30000> {
    SERVICE <http://data.linkedmdb.org/sparql> {
      <http://data.linkedmdb.org/resource/film/1> movie:actor ?actor .
      ?actor movie:actor_name ?actorName .
    }
    ?s ?p ?o .
    FILTER(regex(str(?s), replace(?actorName, " ", "_"))) .
}

这可能会使您获得所需的优化,但这似乎仍然无法工作,除非DBpedia有一些有效的方法来根据计算替换找出要检索的三元组。您要求DBpedia查看其所有三元组,然后保持主题的字符串形式与特定正则表达式匹配的那些三元组。最好在子查询中手动构造IRI,然后搜索它。也就是说,

代码语言:javascript
复制
SERVICE <http://dbpedia.org/sparql?timeout=30000> {
  { select ?actor {
      SERVICE <http://data.linkedmdb.org/sparql> {
        <http://data.linkedmdb.org/resource/film/1> movie:actor ?actor . 
        ?actor movie:actor_name ?actorName .
      }
      bind(iri(concat("http://dbpedia.org/resource",
                      replace(?actorName," ","_")))
           as ?actor)
    } } 
  ?actor ?p ?o 
}
票数 3
EN

Stack Overflow用户

发布于 2016-07-12 20:26:23

(长话短说)

考虑:

代码语言:javascript
复制
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX movie: <http://data.linkedmdb.org/resource/movie/>
PREFIX dcterms: <http://purl.org/dc/terms/>

SELECT ?s WHERE {
    {
        <http://data.linkedmdb.org/resource/film/1> movie:actor ?actor .
        ?actor movie:actor_name ?actorName .
    }
    {
        ?s ?p ?o .
        FILTER(regex(str(?s), replace(?actorName, " ", "_"))) .
    }
}

这是相同的查询,但没有服务调用。?actorName不是内部第二个{}的模式。

由于联接是一种交换操作,这与第一个查询具有相同的答案。

代码语言:javascript
复制
SELECT ?s WHERE {
    {
        ?s ?p ?o .
        FILTER(regex(str(?s), replace(?actorName, " ", "_"))) .
    }
    {
        <http://data.linkedmdb.org/resource/film/1> movie:actor ?actor .
        ?actor movie:actor_name ?actorName .
    }
}

服务版本突出显示这一点,因为部件是在不同的机器上单独执行的。

这两个部分的连接发生在每个部分的结果上。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38328020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档