2017-04-12 39 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)。結果幾乎是即時的。 –