2017-04-12 46 views
2

给出IMDb ID,我想从Wikidata获得该电影的导演和演员名单。UNION中的SPARQL BIND太慢

问题是,我想将导演和演员查询合并成一个列,同时还提供了一个新的导演或演员的角色列。总之,首先我从IMDb ID中获得电影实体,然后从电影中获取所有导演,然后从该电影中获取所有演员,并在填充新列时将它们联合在一起(?角色)与角色。

这是我有:

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 

这个工程,并给出我想要的结果,问题是它需要大约10secs。如果我删除BIND即时速度,但我没有得到与角色列。

有什么我失踪? 在此先感谢。

回答

2

我使用,而不是绑定工会写这篇文章。这个想法是你说什么时候属性是一回事,那么?角色是一回事,当属性是另一回事时,角色是另一回事。最简单的方法来做到这一点与是一样的东西:

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

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变量,则可以省略三重模式来检索UNION条款的?cast。)

+0

你甚至不需要这里的工会。只要使用'values(?p?role){(p:P57“导演”)(p:P161“actor”)}'等等。 –

+0

对,更优雅。如果我真的明白,你的意思是用'values(?p?role){(p:P57“director”)(p:P161“actor”)} ?movie?p?cast .'替换整个UNION部分,对?不幸的是,这导致超时(至少在写作时)。我想这与BIND的性能问题很相似。我不知道Blazegraph如何优化更多,乍一看这看起来像一个简单的查询。 – AKSW

+0

AKSW,我写错了。 OP在每个联合边使用两个属性(例如,p:P171和ps:P161)。它应该是'values(?p?ps?角色)...'。我添加了[答案](http://stackoverflow.com/a/43392591/1281433)。结果几乎是即时的。 –