Nouveautés de SPARQL 1.1

Julien Plu

La nouvelle version de SPARQL amènera un très grand nombre de nouveautés ; dont voici un aperçu. Commentez ici cet article Commentez

- Titre : Nouveautés de SPARQL 1.1

- Auteur : Julien Plu

- Parution : 20 février 2012

- Mise à jour : 11 janvier 2016

- Public visé :

- Licence : Copyright ® 2012-2016 Julien Plu. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Les projections

- III. Les négations

- IV. L'agrégation

- V. Les chemins

- VI. Les requêtes imbriquées

- VII. Une bibliothèque de fonctions

- VIII. Mise à jour du langage et du protocole

- IX. Les descriptions de services

- X. Inférence sur les données

- XI. Les requêtes distribuées

- XII. Référence

- XIII. Remerciements

I - Introduction

La nouvelle version de SPARQL amènera un très grand nombre de nouveautés. Nous étudierons certaines de ces nouveautés en les illustrant par des exemples simples.

II - Les projections

Il s'agit d'assignations et de créations de nouvelles valeurs aussi utilisables avec les agrégats, les fonctions mathématiques et la bibliothèque de fonctions.

Exemple :

le prix de tous les articles en ajoutant la TVA

SELECT (?prix * (19.6/100) AS ?prixTVA)
WHERE {
?article :prix ?prix
}

Il faut bien faire attention à ne pas utiliser la même variable des deux côtés de AS. Par exemple il est impossible d'écrire ?prix * (19.6/100) AS ?prix.

III - Les négations

Précédemment pour faire une négation en SPARQL, on utilisait FILTER et BOUND. Avec ces mots clefs, le nom de toutes les personnes qui n'ont pas de date d'anniversaire s'obtenait ainsi :

SELECT ?name
WHERE {
?x foaf:givenName ?name .
OPTIONAL { ?x foaf:birthday ?date } .
FILTER (!bound(?date))
}

Maintenant, avec SPARQL 1.1, on dispose de deux nouveaux mots clefs : MINUS et NOT EXISTS.
NOT EXISTS a été défini pour deux raisons : simplifier la négation en SPARQL 1.1 et identifier les patrons de requête non existants. Voici un exemple simple d'utilisation :

SELECT ?name
WHERE {
?x foaf:givenName ?name .
FILTER NOT EXISTS {
?x dc:date ?date
}
}

MINUS a aussi été défini pour deux raisons : simplifier la négation en SPARQL 1.1 et supprimer certaines valeurs des résultats (évaluer le MINUS et le soustraire des résultats). On peut l'utiliser dans le même exemple :

SELECT ?name
WHERE {
?x foaf:givenName ?name .
MINUS {
?x dc:date ?date
}
}

Quelle est la différence entre les deux ? Tout d'abord, le nommage des variables. Avec le triplet suivant :

:a :b :c .

la requête :

SELECT * {
?s ?p ?o .
FILTER NOT EXISTS {
?x ?y ?z
}
}

évalue un jeu de résultats sans solution, car {?x ?y ?z} ne correspond à aucune donnée de ?s ?p ?o, donc NOT EXISTS {? x? y? z} élimine toutes les solutions. Il n'y a donc aucun résultat, tandis qu'avec MINUS, il n'y a pas de variable partagée entre la première partie (?s ?p ?o) et la seconde (?x ?y ?z). Aucune liaison n'est éliminée, et cela donne comme résultat a b c. La requête s'écrit :

SELECT * {
?s ?p ?o .
MINUS {
?x ?y ?z
}
}

IV - L'agrégation

Avec SPARQL1.0 on devait utiliser un script externe pour les fonctions agrégats « classiques » et disponibles en SQL ; comme compter un nombre de résultats, trouver une valeur ou moyenne, ou même prendre une valeur aléatoire. Maintenant, avec SPARQL 1.1, quelques agrégats sont fournis par défaut. Ces agrégats sont COUNT, SUM, MIN, MAX, AVG, SAMPLE, GROUP_CONCAT, ainsi qu'une fonctionnalité de groupage GROUP BY et une fonction de filtrage des groupes HAVING. Tous ces agrégats sont compatibles avec les projections. Dans le détail :

- COUNT : nombre d'éléments associés à une expression ;

- SUM : somme des valeurs associées à une expression ;

- MIN : élément ayant la plus petite valeur dans l'ensemble des éléments associés à une expression ;

- MAX : élément ayant la plus grande valeur dans l'ensemble des éléments associés à une expression ;

- AVG : moyenne de l'ensemble des éléments associés à une expression ;

- SAMPLE : valeur aléatoire dans un jeu de données ;

- GROUP_CONCAT : concaténer les résultats d'une agrégation ;

- GROUP BY : afin de calculer les valeurs agrégées pour une solution, celle-ci est d'abord divisée en un ou plusieurs groupes, et la valeur globale est calculée pour chaque groupe ;

- HAVING : agit sur des ensembles de solutions groupées, de la même manière que FILTER agit sur des solutions non groupées.

Exemple avec SUM, GROUP BY et HAVING :

Le total de tous les éléments et le prix de chaque groupe d'éléments ne doit pas dépasser 10 euros

SELECT (SUM(?prix AS ?prix_total))
WHERE {
?element :prix ?prix .
}
GROUP BY ?element
HAVING (SUM(?prix) &gt; 10)

Les autres agrégats COUNT, MIN, MAX, AVG, SAMPLE et GROUP_CONCAT s'utilisent de la même façon.

V - Les chemins

Un chemin est une voie possible entre deux nœuds dans un graphe. Ce système est basé sur les expressions régulières. Celui-ci peut par exemple être utilisé pour identifier les amis d'un ami et les amis de leurs amis, aussi loin qu'on le veut, et quelle que soit la distance. Ou encore pour identifier les sous-catégories d'un terme dans une source de données, et ceci peu importe la profondeur à laquelle il se trouve. Ou même encore pour identifier si deux ressources sont liées par des liens, tout en excluant ceux qui ne sont pas intéressants. Voici les éléments que ce système propose :

- iri : une IRI ou un nom préfixé, un chemin de longueur unitaire ;

- ^elt : chemin inverse (de l'objet au sujet) ;

- !iri ou !(iri1| ...|irin) : négation d'un ensemble de propriétés. Une IRI qui n'est pas une des irin. !iri est un raccourci pour !(iri) ;

- !^iri ou !(iri1| ...|irij|^irij+1| ...|^irin)) : négation d'un ensemble de propriétés avec certaines propriétés inverses. Une IRI qui n'est pas une des irin, ni l'une des irij+1...irin des chemins inverses. !^iri est un raccourci pour !(^iri) ;

- (elt) : un groupe de chemin elt, des crochets de contrôle prioritaire ;

- elt1 / elt2 : une séquence de chemin de elt1, suivie par elt2 ;

- elt1 | elt2 : une autre voie possible de elt1 ou elt2 (toutes les possibilités sont essayées) ;

- elt* : un chemin de zéro ou plusieurs occurrences de elt ;

- elt+ : un chemin d'une ou plusieurs occurrences de elt ;

- elt? : un chemin de zéro ou un elt ;

- elt{n,m} : un chemin entre n et m occurrences de elt ;

- elt{n} : exactement n occurrences de elt ;

- elt{n,} : n occurrences ou plus de elt ;

- elt{,n} : entre 0 et n occurrences de elt.

Comment peut-on utiliser ces syntaxes ?

Une ou deux possibilités

{ :book1 dc:title|rdfs:label ?displayString }

Trouver le nom de toutes les personnes que connaît Alice.

{
?x foaf:mbox <mailto:alice@example> .
?x foaf:knows/foaf:name ?name .
}

Trouver le nom des personnes qui connaissent les personnes que connaît Alice

{
?x foaf:mbox <mailto:alice@example> .
?x foaf:knows/foaf:knows/foaf:name ?name .
}

D'une autre façon :

{
?x foaf:mbox <mailto:alice@example> .
?x foaf:knows{2}/foaf:name ?name .
}

Ces deux dernières requêtes sont les mêmes : la seconde est simplement l'inversion du sens de la propriété qui échange les rôles de sujet et objet.

{ ?x foaf:mbox <mailto:alice@example> }
{ <mailto:alice@example> ^foaf:mbox ?x }

Trouver toutes les personnes qui connaissent quelqu'un qui connaît ?X

{
?x foaf:knows/^foaf:knows ?y .
FILTER(?x != ?y)
}

Trouver les noms de toutes les personnes qui peuvent être atteintes en partant de Alice par le biais de foaf:knows

{
?x foaf:mbox &lt;mailto:alice@example&gt; .
?x foaf:knows+/foaf:name ?name .
}

Certaines formes d'inférence limitée sont aussi possibles.

Trouver tous les types et supertypes d'une ressource

{ &lt;http://example/thing&gt; rdf:type/rdfs:subClassOf* ?type }

VI - Les requêtes imbriquées

Ce type de requête nécessitait de passer par un langage externe à SPARQL. Il est maintenant possible d'imbriquer les requêtes les unes dans les autres. Néanmoins, il faut faire très attention à la portée des variables. Petit exemple :

Tous les articles et le nom des auteurs triés par ordre alphabétique

SELECT ?article ?name
WHERE {
?article :author ?author .
{
SELECT ?name WHERE {
?author foaf:name ?name
} ORDER BY ?name
}
}

Le modificateur ORDER BY trie les éléments donnés en paramètre suivant l'opérateur « < ». On peut lui dire si l'on veut un ordre croissant ou décroissant avec les fonctions ASC() et DESC().

VII - Une bibliothèque de fonctions

Ces fonctions étaient souvent implémentées par certains points d'accès SPARQL, mais pas standardisées, ce qui provoquait la création de requêtes non standard. Ainsi une longue liste d'opérateurs et de fonctions ont été ajoutés dans SPARQL 1.1. On peut en trouver la liste complète dans le standard.

VIII - Mise à jour du langage et du protocole

L'ajout le plus important est la possibilité de modifier les graphes. Jusqu'à présent, les données étaient seulement accessibles en lecture et ne pouvaient pas être mises à jour ; cela nécessitait de passer par des langages externes. Deux types d'opérations ont été définis : les opérations sur les graphes (graph management) et les opérations sur les données au sein de graphes (graph update). Les opérations possibles sur les graphes sont :

- créer et supprimer des graphes : CREATE et DROP ;

- ajout/suppression de triplets : LOAD et CLEAR.

Pour les données et les triplets :

- insertion de données sans variables : INSERT DATA ;

- suppression de données sans variables : DELETE DATA ;

- insertion de triplets dans un graphe : INSERT ;

- suppression de triplets dans un graphe : DELETE.

Il va de soi que le protocole a aussi été modifié en conséquence via HTTP RDF Update (RESTful).

IX - Les descriptions de services

Ainsi un point d'accès SPARQL pourra fournir des informations à son sujet. Avec une simple requête, il sera donc possible de connaître :

- les fonctions disponibles ;

- la quantité de données ;

- les vocabulaires utilisés ;

- les informations techniques concernant ce point d'accès…

Tout ceci sera bien entendu représenté par un vocabulaire spécifique.

X - Inférence sur les données

SPARQL sera associé avec les inférences de langages pouvant définir des vocabulaires ou des règles tels que RDFS, OWL2 ou RIF.

Par exemple, on sait que le rang de la propriété foaf:knows est la classe foaf:Person. On admet que la personne :julien connaisse une personne :thibaut. Soit la requête suivante :

SELECT ?x
WHERE {
?x a foaf:Person .
}

Avec SPARQL 1.0, seul :julien ferait partie du résultat. Avec l'inférence, ici de RDFS, SPARQL 1.1 donnera en sortie :julien et :thibaut.

XI - Les requêtes distribuées

Avant on utilisait FROM et FROM NAMED pour interroger des graphes distants. Avec SPARQL 1.1, il devient possible d'interroger des points d'accès SPARQL distants. Le mot clef SERVICE est utilisé pour interroger les points d'accès distants et il est possible de combiner ces services. Par exemple :

SELECT ?person
WHERE {
SERVICE &lt;http://dbpedia.org/sparql&gt; {?s a foaferson .}
SERVICE &lt;http://example.org/sparql&gt; {?s a foaferson .}
}

Le mot clef BINDINGS propage des contraintes sur différents points d'accès, ce qui simplifie le FILTER. Par exemple, si on veut toutes les personnes portant le nom « julien » dans deux jeux de données (points d'accès SPARQL) différents :

SELECT ?person WHERE {
SERVICE <http://dbpedia.org/sparql> {
?p a foaf:Person ;
foaf:givenName ?name
}
SERVICE <http://example.org/sparql> {
?p a foaf:Person ;
foaf:givenName ?name
}
}
BINDINGS ?name { ("julien") }

XII - Référence

Si vous voulez avoir plus de détails sur ces nouveautés, consultez le standard.

XIII - Remerciements

Merci à dourouc05, à Erielle, à bifconsult et à Claude Leloup pour leur correction orthographique.