2017-04-12 4 views
2

étant donné un ID IMDb, je veux obtenir une liste des réalisateurs et des acteurs pour ce film de Wikidata. Le problème est, je veux UNION à la fois le directeur et l'acteur requête dans une seule colonne tout en fournissant une nouvelle colonne avec le rôle de directeur ou d'acteur.SPARQL BIND dans UNION est trop lent

assez facile requête globale: d'abord je reçois l'entité de film de l'ID IMDb, puis je reçois tous les réalisateurs de ce film suivi par obtenir tous les acteurs de ce film et les assembler en remplissant une nouvelle colonne (? Rôle) avec le rôle.

ce que j'ai:

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 

cela fonctionne et donne le résultat que je veux, problème, il faut environ 10secs. si je supprime les BINDs sa vitesse instantanée, mais je ne reçois pas une colonne avec les rôles.

Y at-il quelque chose qui me manque? merci d'avance.

Répondre

2

J'écrirait cela en utilisant les valeurs au lieu de lier et union. L'idée est que vous dites quand les propriétés sont une chose, alors le rôle est une chose, et quand les propriétés sont différentes, le rôle en est une autre. La façon facile de le faire avec des valeurs est quelque chose comme:

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

Dans votre cas, ce serait:

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 

Quand je lance ceci à query.wikidata.org, il produit 35 results presque instantanément.

2

Je suppose que BIND conduit à certains problèmes avec l'optimiseur de requête. Vous pouvez essayer comme une alternative à lier le rôle en dehors de la clause UNION, à savoir

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 

(Si vous ne faites pas la variable ?ref, vous pouvez omettre les motifs triple pour récupérer le ?cast dans les clauses UNION.)

+0

Vous n'avez même pas besoin de l'union ici. Utilisez juste 'values ​​(? P? Role) {(p: P57" directeur ") (p: P161" acteur ")}', etc. –

+0

A droite, c'est beaucoup plus élégant. Si je comprends bien, vous vouliez remplacer toute la partie UNION par 'values ​​(? P? Role) {(p: P57" directeur ") (p: P161" acteur ")} ? Movie? P? Cast. droite? Malheureusement, cela conduit à un délai d'attente (au moins au moment de l'écriture). Je suppose que c'est similaire au problème de performance avec BIND. Je ne sais pas comment Blazegraph est optimisé plus, à première vue cela ressemble à une simple requête. – AKSW

+0

AKSW, je me suis trompé dans ce que j'ai écrit. OP utilise deux propriétés dans chacun des côtés d'union (par exemple, p: P171 et ps: P161). Ce devrait être 'values ​​(? P? Ps? Rôle) ...'. J'ai ajouté [une réponse] (http://stackoverflow.com/a/43392591/1281433). Les résultats sont presque instantanés. –