Bases de Données / Databases

Site Web de l'équipe BD du LIP6 / LIP6 DB Web Site

Outils pour utilisateurs

Outils du site


site:enseignement:master:bdle:tmes:algebrespark

[TME II-2] Algèbre Spark: Dataset

Ce TME aborde le traitement de requêtes Sparql dans la plateforme Spark.

  • Formulation des requêtes dans le langage Scala avec les API de Spark RDD et Dataset.
  • Exécution des requêtes.

Préparation

Récupérer les jeux de données de Freebase et Yago

mkdir -p /tmp/BDLE/dataset
cd /tmp/BDLE/dataset
tar zxvf /Infos/bd/spark/dataset/freebase/freebase_snippet_surls.tgz
tar zxvf /Infos/bd/spark/dataset/yago/yagoFacts5M.tgz
cp  /Infos/bd/spark/dataset/yago/yagoMiniSample.txt /tmp/BDLE/dataset

TODO (oct 2017): page MPI pour sparql endpoint sur Yago

Aller dans votre répertoire de travail et lancer le spark-shell avec l'option –driver-memory 10G

  cd <votre répertoire> 
  spark-shell --driver-memory 10G
  sc.setLogLevel("ERROR")

Rappel de Sparql

Une requête Sparql sélectionne des nœuds dans un graphe RDF qui vérifient certaines conditions. La syntaxe d’une telle requête comporte une clause select qui permet de spécifier les nœuds à retourner et une clause where qui exprime la condition devant être vérifiée. Un motif élémentaire Sparql prend l’une des formes suivantes :

  1. ( ?x p v) où le sujet est l’inconnu
  2. (v p ?y) où l’objet est l’inconnu
  3. ( ?x p ?y) où le sujet et l’objet sont les inconnus

Ici ?x et ?y sont deux variables devant être substituées par des valeurs de sujet et d’objet pour que le motif soit satisfait. L’évaluation d’un motif de graphe consiste donc à trouver liaison entre des sujets ou des objets et des variables. Exemple, soient les trois triplets suivants :

(james joue guitare) (marie joue piano) (james ami_de marie) (marie  ami_de james)

le motif ( ?x joue piano) retourne la liaison ?x→marie le motif ( ?x joue ?y) retourne les liaisons ?x→james, ?y→ guitare d’une part et ?x→maire, ?y→piano d’autre part. Il est également possible d’exprimer des motifs complexes tels que ( james ami_de ?x) ( ?x joue ?y) qui permet de trouver l’ami de james qui joue un instrument. Vous remarquerez que pour évaluer ce motif, une jointure est nécessaire pour mettre en correspondance l’objet du triplet (james ami_de marie) avec le sujet du triplet (marie joue piano). Ce type de motif est appelé objet-sujet. Les autres formes possibles sont : sujet-sujet et sujet-objet. Pour formuler une requête Sparql, il suffit de spécifier dans sa clause select les variables à retourner (projection). Par exemple, select ?x where {?x joue ?y } retourne les liaisons ?x→james et ?x→marie. Ici, on ne retourne pas la variable ?y.

Exercice 1: Requêtes simples sur les données de Yago

Lire un exemple de données

more /Infos/bd/spark/dataset/yago/yagoMiniSample.txt 

Lire la liste des propriétés

more /Infos/bd/spark/dataset/yago/yagoFacts5M_properties.txt

Charger le dataset YAGO

case class Triple(sujet: String, prop: String, objet: String)

val yagoFile = "/tmp/BDLE/dataset/yagoFacts5M.txt"

val yago = sc.textFile(yagoFile).
  map(ligne => ligne.split("\\t")).coalesce(8).
  map(tab => Triple(tab(0), tab(1), tab(2))).toDS()

yago.persist
yago.count

R1: Les régions dont la capitale (régionale) est Nantes

 ?x <hasCapital> <Nantes> 

La requête s'écrit ainsi avec une opération de sélection where, un renommage withColumnRenamed et une projection select :

val r1 = yago.where("prop = '<hasCapital>' and objet = '<Nantes>'").
    withColumnRenamed("sujet","x").
    select("x")
r1.show(5)

Le résultat de la requête est:

|        x          |
+-------------------+
|<Duchy_of_Brittany>|
| <Pays_de_la_Loire>|
+-------------------+

R2: La fiche de Barack Obama

Afficher toutes les paires (propriété,objet) au sujet de <Barack_Obama>

REPONSE

   val t1 = yago.where("sujet = '<Barack_Obama>'").
     withColumnRenamed("prop","p").
     withColumnRenamed("objet","o").
     select("p", "o")
   t1.show(20)

Le résultat doit être :

|        p       |         o          |
+----------------+--------------------+
| <graduatedFrom>|<Columbia_University|
| <graduatedFrom>|<Harvard_Law_School>|
|     <hasGender>|              <male>|
|   <hasWonPrize>|      <Grammy_Award>|
|   <hasWonPrize>| <Nobel_Peace_Prize>|
|<isAffiliatedTo>|<Democratic_Party>  |
|   <isCitizenOf>|           <Germany>|
|   <isCitizenOf>|             <Wales>|
|   <isCitizenOf>|     <United_States>|
|   <isCitizenOf>|          <Scotland>|
|   <isCitizenOf>|             <Kenya>|
|   <isCitizenOf>|            <Israel>|
|<isPoliticianOf>|     <United_States>|
|       <livesIn>|          <Illinois>|
|       <livesIn>|           <Chicago>|
|     <wasBornIn>|          <Honolulu>|
+----------------+--------------------+

R3: Les leaders parisiens

La requête est une étoile formée de deux triplets

    ?x <livesIn> <Paris> .
    ?x <isLeaderOf> ?z

REPONSE

val t1 = yago.where("prop = '<livesIn>' and objet = '<Paris>'").
    withColumnRenamed("sujet","x").
    select("x")
 
val t2 = yago.where("prop = '<isLeaderOf>' ").
    withColumnRenamed("sujet","x").
    withColumnRenamed("objet","z").
    select("x","z")
 
val t1t2 = t1.join(t2, "x")
t1t2.show(5)
 

Le résultat doit être:

|         x          |          z         |
+--------------------+--------------------+
|       <Louis_Blanc>|<Republican_Union...|
|<Stefano_Zacchiroli>| <Software_Heritage>|
+--------------------+--------------------+

R4: Les joueurs du royaume uni.

La requête est un chemin formé de deux triplets

      ?x <playsFor> ?y .
                    ?y <isLocatedIn> <United_Kingdom>

REPONSE

val t1 = yago.where("prop = '<playsFor>'").
    withColumnRenamed("sujet","x").
    withColumnRenamed("objet","y").
    select("x","y")
 
val t2 = yago.where("prop = '<isLocatedIn>' and objet = '<United_Kingdom>'").
    withColumnRenamed("sujet","y").
    select("y")
 
val t1t2 = t1.join(t2, "y")
t1t2.show(5)
 

Les 5 premiers éléments du résultat sont :

|         y          |       x            |
+--------------------+--------------------+
|   <Royal_Air_Force>|      <George_Ayres>|
|   <Royal_Air_Force>|<Jack_Jones_(foot...|
|   <Royal_Air_Force>|<John_Hinton_(foo...|
|<University_of_Ed...|<James_Craigen_(f...|
|<University_of_Ed...|    <Ronald_Brebner>|
+--------------------+--------------------+

R5: Les acteurs qui influencent des créateurs

La requête est un flocon (ou snowflake) formé de 5 triplets :

   ?x <isCitizenOf> ?y .
   ?x <actedIn> ?z .
   ?x <influences> ?t .
                   ?t <livesIn> ?u .
                   ?t <created> ?v

REPONSE

val t1 = yago.where("prop = '<isCitizenOf>'").
    withColumnRenamed("sujet","x").
    withColumnRenamed("objet","y").
    select("x","y")
 
val t2 = yago.where("prop = '<actedIn>'").
    withColumnRenamed("sujet","x").
    withColumnRenamed("objet","z").
    select("x","z")
 
val t3 = yago.where("prop = '<influences>'").
    withColumnRenamed("sujet","x").
    withColumnRenamed("objet","t").
    select("x", "t")
 
val t4 = yago.where("prop = '<livesIn>'").
    withColumnRenamed("sujet","t").
    withColumnRenamed("objet","u").
    select("t","u")
 
val t5 = yago.where("prop = '<created>'").
    withColumnRenamed("sujet","t").
    withColumnRenamed("objet","v").
    select("t", "v")
 
val r = t1.join(t2, "x").join(t3,"x").join(t4,"t").join(t5,"t")
r.show(10)
 

Le résultat, limité à 10 lignes, doit être:

+--------------+----------+---------+-----------------+--------------------+----------------+
|             t|         x|        y|                z|                   u|               v|
+--------------+----------+---------+-----------------+--------------------+----------------+
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|       <Cry-Baby>|            <Dublin>|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|       <Cry-Baby>|<Republic_of_Irel...|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|    <Suck_(film)>|            <Dublin>|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|    <Suck_(film)>|<Republic_of_Irel...|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|<Hardware_(film)>|            <Dublin>|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|<Hardware_(film)>|<Republic_of_Irel...|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|       <Dead_Man>|            <Dublin>|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|       <Dead_Man>|<Republic_of_Irel...|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|   <Gimme_Danger>|            <Dublin>|<Dockers_(film)>|
|<Irvine_Welsh>|<Iggy_Pop>|<Germany>|   <Gimme_Danger>|<Republic_of_Irel...|<Dockers_(film)>|
+--------------+----------+---------+-----------------+--------------------+----------------+

R6: Les paires de personnes mariées et nées dans le même pays

R7: Les personnes influencées par un prix nobel

R8: L'acteur ayant joué dans le plus grand nombre de films

Exercice subsidiaire : Requêtes sur Freebase

L’objectif de cet exercice est d’exprimer en Scala les différents types de motifs complexes.

  • Dans un premier temps, considérer que l’accès aux données se fait via une variable appelée TRIPLES. Caractériser puis exprimer les requêtes Sparql suivantes en Scala.
  • Dans un second temps tester les requêtes formulées en questions 1 sur l'extrait Freebase accessible en consultant la page Jeux de données

Q1 : requête avec une seule variable de jointure

SELECT ?b WHERE 
{?b <book.book.characters>     ?c   .
?b <book.book.genre>               ?x .
?b <book.book.editions>          ?y. }

Q2: requête avec un filtre

SELECT ?c WHERE {
?c <people.person.education> ?e .
?c <people.person.date_of_birth> ?x .
?c <people.person.nationality>  ?y .
FILTER( ?x CONTAINS '1990')
 }

Q3 : requête avec 2 variables de jointure

SELECT ?ar  WHERE {
?ar <music.artist.album> ?al .
?ar <music.artist.genre> ?g .
?ar <music.artist.home_page> ?h.
 
?al <music.album.release_date> ?d .
?al <music.album.contributor> ?c.
?al <music.album.featured_artists> ?f
}

Q4: requête formant un chemin

SELECT * WHERE
{
?m <music.recording.artist>        ?ar    .
?ar <music.artist.supporting_artists>  ?sar .
?sar <music.artist.album>       ?al
}

Q5

SELECT ?ar ?al ?t WHERE
{
?ar <music.artist.genre> ?g .
?ar <music.artist.origin> ?o .
?ar <music.artist.album> ?al .
?ar <music.artist.label> ?l .
?ar <music.artist.track> ?t
}

Exercice subsidiaire

a) A partir de Q4 proposer une requête formant un chemin de longueur 4 puis 5 (avec des propriétés différentes de celles de Q4).

b) A partir de Q3, proposer une requête dont une partie du motif est optionnelle.

c) Proposer une requête qui est l'union de deux motifs

d) Proposer une requête avec 3 motifs de triplets et 3 variables de jointures (i.e., motif formant un triangle).

e) Lister les 10 propriétés les plus fréquentes. Lister les 10 sujets les plus fréquents.

f) Etant donné un sujet S0, lister toutes les propriétés pour lesquelles il existe un triplet ayant le sujet S0.

site/enseignement/master/bdle/tmes/algebrespark.txt · Dernière modification: 09/10/2018 14:12 par amine