2017-04-12 1 views
2

IMDb ID가 주어지면 Wikidata에서 해당 영화의 감독과 배우 목록을 가져오고 싶습니다.UNION 내의 SPARQL BIND가 너무 느림

문제는 디렉터와 액터 쿼리를 모두 단일 열로 UNION하고 디렉터 나 액터의 역할을 새 열에 제공하고 싶습니다.

전체적으로 간단한 쿼리 : 먼저 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

나는 대신 바인드조합를 사용하여이 쓰기 것입니다. 이 개념은 속성이 한 가지 일 때, 역할은 한 가지, 속성이 다른 경우 역할이 다른 것을 말하는 것입니다. 나는 query.wikidata.org에서이 프로그램을 실행할 때

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 

을 : 귀하의 경우에는

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

, 이것은 다음과 같습니다 쉬운 방법은 가 같은 것을해야 할 일 거의 즉시 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 "director") (p : P161 "actor")}'등을 사용하십시오. –

+0

오른쪽은 훨씬 우아합니다. 만약 내가 정말로 이해한다면, 전체 UNION 부분을 값 (? p? role) {(p : P57 "director") (p : P161 "actor")} ? movie? p? cast .', 권리? 불행하게도 이것은 (최소한 글쓰기의 시간에는) 타임 아웃으로 이어진다. BIND의 성능 문제와 비슷합니다. Blazegraph가 어떻게 최적화되어 있는지 알지 못합니다. 언뜻보기에는 간단한 쿼리처럼 보입니다. – AKSW

+0

AKSW, 나는 내가 쓴 것에 착각했다. OP는 각 공용 영역 (예 : p : P171 및 ps : P161)에서 두 속성을 사용합니다. 그것은'values ​​(? p? ps? role) ... '이어야합니다. 나는 [대답] (http://stackoverflow.com/a/43392591/1281433)을 추가했습니다. 결과는 거의 즉시입니다. –