UNION中的SPARQL BIND太慢了

时间:2017-04-12 15:06:00

标签: sparql rdf rdfs wikidata wikidata-api

给定一个IMDb id,我想从维基数据中获取该电影的导演和演员列表。

问题是,我希望UNION将导演和演员查询分成一个列,同时还提供一个具有导演或演员角色的新专栏。

整体上非常容易查询:首先我从IMDb id获取电影实体,然后我从该电影中获取所有导演,然后从该电影获取所有演员并将UNION一起填充新列(?角色)与角色。

这就是我所拥有的:

PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?person ?personLabel ?role ?imdb WHERE
{
  ?movie wdt:P345 "tt0110912" .
  { ?movie p:P57 ?cast .
    ?cast ps:P57 ?person .
    BIND("director" as ?role) .
  } UNION {
    ?movie p:P161 ?cast .
    ?cast ps:P161 ?person .
    BIND("actor" as ?role) . }

  ?person wdt:P345 ?imdb .
  OPTIONAL { ?cast prov:wasDerivedFrom ?ref . }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?person ?personLabel ?role ?imdb
ORDER BY DESC(?role)
LIMIT 100

这可行,并给出我想要的结果,问题是它需要大约10秒。如果我以即时速度删除BIND,但我没有获得一个角色列。

有什么我想念的吗? 提前谢谢。

2 个答案:

答案 0 :(得分:2)

我猜BIND会导致查询优化器出现一些问题。您可以尝试将角色绑定在UNION子句之外,即

PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?person ?personLabel ?role ?imdb WHERE
{
  ?movie wdt:P345 "tt0110912" .
  ?person wdt:P345 ?imdb .
  { 
     ?movie p:P57 ?c1 . ?c1 ps:P57 ?person .
     ?movie p:P57 ?cast .
  } UNION {
     ?movie p:P161 ?c2 . ?c2 ps:P161 ?person .
     ?movie p:P161 ?cast . 
  }
  BIND(IF(bound(?c1), "director", "actor") as ?role)

  OPTIONAL { ?cast prov:wasDerivedFrom ?ref . }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?person ?personLabel ?role ?imdb
ORDER BY DESC(?role)
LIMIT 100

(如果您没有?ref变量,则可以省略三重模式以检索?cast子句中的UNION。)

答案 1 :(得分:2)

我使用代替 bind union 来编写此代码。这个想法是你说当属性是一回事时,那么?角色是一回事,当属性是另一回事时,?角色是另一回事。使用执行此操作的简单方法如下:

select ?owner ?pet ?petType {
  values (?hasPet ?petType) { 
    (:hasCat "cat")
    (:hasDog "dog")
  }
  ?owner ?hasPet ?pet
}

在您的情况下,这将是:

PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?person ?personLabel ?role ?imdb WHERE
{
  ?movie wdt:P345 "tt0110912" .

  values (?p ?ps ?role) {
    (p:P161 ps:P161 "actor")
    (p:P57 ps:P57 "director")
  }
  ?movie ?p ?cast .
  ?cast ?ps ?person .

  ?person wdt:P345 ?imdb .
  OPTIONAL { ?cast prov:wasDerivedFrom ?ref . }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?person ?personLabel ?role ?imdb
ORDER BY DESC(?role)
LIMIT 100

当我在query.wikidata.org运行时,它几乎立即生成35 results