2017-04-12 7 views
2

私はIMDb IDを与えられているので、Wikidataからその映画の監督と俳優のリストを取得したいと思います。UNION内のSPARQL BINDが遅すぎる

問題は、ディレクターとアクターの両方のクエリーを1つのカラムに結合し、ディレクターまたはアクターの役割を持つ新しいカラムを提供することです。

私は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

私は値の代わりにバインド組合を使用して、これを記述します。そのアイデアは、プロパティが1つのこと、次にロールが1つ、プロパティが別の場合はロールが別のものであると言っているということです。

お使いの場合には
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は、クエリオプティマイザにいくつかの問題が発生していると思います。あなたはすなわち

は(あなたが ?ref変数をしない場合、あなたは UNION句で ?castを取得するために、トリプル・パターンを省略することができます。)
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 

UNION句の外で役割をバインドするための代替として試すことができます

+0

ここでも組合は必要ありません。 'values(?p?role){(p:P57" director ")(p:P161" actor ")}'などを使用してください。 –

+0

右ははるかにエレガントです。もし私が本当に理解していれば、UNION部分全体を 'values(?p role){(p:P57" director ")(p:P161" actor ")} ?movie?p?cast .'、右?残念ながら、これはタイムアウトにつながります(少なくとも書面では)。私はそれがBINDのパフォーマンスの問題に似ていると思います。私は、Blazegraphがどのように最適化されているか分かりません。一見すると、これは簡単なクエリのようです。 – AKSW

+0

AKSW、私は私が書いたことで間違っていた。 OPは共用体の各側面(例えば、p:P171およびps:P161)において2つの特性を使用する。それは 'values(?p?ps?role)... 'でなければなりません。私は[答え](http://stackoverflow.com/a/43392591/1281433)を追加しました。結果はほぼ即時です。 –