Avant-propos: Cet article a été écrit à l'origine par Nedgang puis complété par mes soins.

Parce-que je suis un noob et je le vis mal. Et puis le fait que ça puisse mener à tirer dans des cochons avec un pistolet à clous est très motivant. La grande majorité (si ce n'est la totalité) des informations sont retrouvables avec n'importe quel moteur de recherche. Le seul intérêt de ce doc est de les rassembler.

Sommaire

Concepts liés au cours de SdC

IRI, URI, URL

Identifiant décrivant une ressource sur le réseau. Il doit permettre d'identifier une ressource de manière permanente, même si la ressource est déplacée, supprimée ou présente dans une autre base de données.

Dans le monde réel, y'a l'ISBN pour les livres. Ben c'est pareil, mais sur le web.

Les adresses IRI (Internationalized Resource Identifier ou Référence URI RDF) incluent les adresses URI (Uniform Ressource Identifier) et les adresses URL (Uniform Ressource Locator).

Web sémantique

Le Web sémantique est un mouvement collaboratif mené par le World Wide Web Consortium (W3C) qui favorise des méthodes communes pour échanger des données.

Le Web sémantique est vise à rendre l'information lisible par les humains et par les machines. Cela permettra d'effectuer les travaux fastidieux et répétitifs dans le domaine de la recherche d'information par des machines tout en améliorant et consolidant l'information sur le Web.

Le Web sémantique, est un système qui permet aux machines de "comprendre" et de répondre aux demandes complexes de l'homme en fonction du sens de ces demandes. Une telle "compréhension" exige que les sources d'informations pertinentes aient été au préalable sémantiquement structurées.

Le Web sémantique propose des langages spécialement conçus pour les données : RDF (Resource Description Framework), OWL (Ontology Web Language), et XML (eXtensible Markup Language). Ces technologies sont combinées afin de fournir des descriptions qui complètent ou remplacent le contenu des documents Web.

Ontologies

Taxonomie avec des relations supplémentaires, des contraintes et des définitions formelles.

  • Représentation formelle d'une conceptualisation partagée;
  • Représentation des connaissances en décrivant les concepts par leur signification et leurs relations;
  • Généralement, c'est ce qui est implicite aux documents.

Principes liés à OWL (sous-ensemble logique de RDFS, voir dernier chapitre sur les systèmes d'implications):

  • Individus sont des instances de classes;
  • Propriétés sont relations binaires entre individus (transitivité, symétrie, etc.);
  • Classes sont des ensembles d'individus.

RDF : Resource Description Framework

C'est un modèle de graphe destiné à la description formelle des ressources Web et leurs métadonnées. Il est dédié à un traitement automatisé. Une des syntaxes de RDF est le format TURTLE utilisé ici, mais il existe aussi RDF/XML. Ce dernier est considéré comme un format d'échange entre bases de données et est rarement écrit ou lu par un humain.

Principes fondamentaux:

  • Document RDF = ensemble de triplets
  • Triplet RDF = (sujet, prédicat, objet)

Avec:

  • sujet : ressource à décrire (IRI ou noeud anonyme);
  • prédicat : propriété applicable à la ressource (obligatoirement un IRI);
  • objet : valeur de la propriété (IRI, noeud anonyme ou littéral).

Ex:

:glucose    rdf:type    :metabolite.

Un document RDF ainsi formé correspond à un multigraphe orienté étiqueté. Chaque triplet correspond alors à un arc orienté dont le label est le prédicat, le nœud source est le sujet et le nœud cible est l'objet.

La structure de RDF est extrêmement générique et sert de base à un certain nombre de schémas ou vocabulaires dédiés à des applications spécifiques comme les langages d'ontologie RDFS et OWL.

Langages de requête : SPARQL Protocol and RDF Query Language

Le language SPARQL est destiné à devenir le standard dans le domaine de l'interrogation de données stockées au format RDF.

Ex:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE
  { ?x foaf:name ?name.
    ?x foaf:mbox ?mbox }

Conventions

IRI absolus et relatifs:IRIs. Un préfixe inconnu ? => prefix.cc.

Variables: Les notations $abc et ?abc peuvent être utilisées indifféremment dans la même requête.

Motifs de triplets avec sujets communs : Le sujet peut être écrit 1 seule fois grâce au ;.

?x  foaf:name  ?name ;
    foaf:mbox  ?mbox .
# équivaut à:
?x  foaf:name  ?name .
?x  foaf:mbox  ?mbox .

Motifs de triplets avec sujet ET prédicat communs : Les objets sont alors séparés par une ,.

?x foaf:nick  "Alice" , "Alice_" .
# équivaut à:
?x foaf:nick  "Alice" .
?x foaf:nick  "Alice_" .

Combinaison des listes d'objets et des listes de prédicats ET d'objets :

?x foaf:name ?name ; foaf:nick  "Alice" , "Alice_" .
# équivaut à (foaf:name et foaf:nick ont le sujet ?x en commun,
# et Alice et Alice_ ont des sujet et prédicat identiques):
?x foaf:name ?name .
?x foaf:nick  "Alice" .
?x foaf:nick  "Alice_" .

Interrogation de littéraux

Littéral = Composant nommé dans le graphe RDF.

Exemple de graphe RDF avec 3 littéraux:

@prefix dt:   <http://example.org/datatype#> .
@prefix ns:   <http://example.org/ns#> .
# Préfixe par défaut:
@prefix :     <http://example.org/ns#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .

# forme lexicale "cat" + balise optionnelle de langue "en"
:x   ns:p     "cat"@en .
# typé ayant le type de données http://www.w3.org/2001/XMLSchema#integer
:y   ns:p     "42"^^xsd:integer .
# typé ayant le type de données http://example.org/datatype#specialDatatype
:z   ns:p     "abc"^^dt:specialDatatype .

Requêtes:

SELECT ?var WHERE { ?var ?pred "cat"@en }
SELECT ?var WHERE { ?var ?pred 42 }
# forme lexicale + type de données correspondantes => le littéral correspond
SELECT ?var WHERE { ?var ?pred "abc"^^<http://example.org/datatype#specialDatatype> }

Noeuds anonymes / blank nodes

Notés sous la forme _:. Une même étiquette dans un ensemble de résultat = noeud anonyme identique. (c.-à-d. qu'ils servent à relier plusieurs informations au même sujet ou même objet) Ils facilitent la représentation d'un document RDF (du moins sur le papier. Il est préférable de les remplacer par un IRI arbitraire. Voir Un graphe RDF).

Ex de graphe avec noeuds anonymes:

@prefix foaf:  <http://xmlns.com/foaf/0.1/> .

_:a  foaf:name   "Alice" .
_:b  foaf:name   "Bob" .

Interrogation :

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ?x ?name
WHERE  { ?x foaf:name ?name }

Résultat:

x     |   name
_:c   |  "Alice"
_:d   |  "Bob"

Note: c et d auraient pu être nommés différemment. L'essentiel est de savoir si les termes RDF sont identiques ou non. En général le label interne du noeud n'est pas accessible.

Formes d'interrogation

Technologie clé du web sémantique, adaptée à la structure spécifique des graphes RDF. Permet d'exprimer des requêtes interrogatives (SELECT) ou constructives (CONSTRUCT).

  • Requête SELECT: identifie les variables devant apparaître dans les résultats; extrait du graphe un sous-graphe vérifiant les conditions définies dans une clause WHERE. => retourne un tableau de résultats
  • Requête CONSTRUCT: retourne un nouveau graphe, que complète le sous-graphe du graphe interrogé. => retourne un graphe, basé sur un modèle dans la requête;

Chaque requête est un ensemble de triplets similaires aux triplets RDF où chaque sujet, prédicat, objet peut être une variable.

Exemple portant sur un graphe régulièrement utilisé comme exemple:

@prefix foaf:  <http://xmlns.com/foaf/0.1/> .
_:a  foaf:name   "Johnny Lee Outlaw" .
_:a  foaf:mbox   <mailto:jlow@example.com> .
_:b  foaf:name   "Peter Goodguy" .
_:b  foaf:mbox   <mailto:peter@example.org> .
_:c  foaf:mbox   <mailto:carol@example.org> .

Requête :

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
# On prend tout name et mbox dans le graphe
SELECT ?name ?mbox
# Où name et mbox sont associés au même sujet
WHERE
  { ?x foaf:name ?name .
    ?x foaf:mbox ?mbox }

Résultat :

name                | mbox
"Johnny Lee Outlaw" | <mailto:jlow@example.com>
"Peter Goodguy"     | <mailto:peter@example.org>

Nous avons 2 solutions avec 2 variables (name et mbox) associées à leurs termes RDF (binding variable + terme RDF). Chaque solution est une façon de lier les variables aux termes RDF pour faire correspondre le motif d'interrogation aux données.

Le cas particulier DESCRIBE

La forme DESCRIBE retourne un seul graphe RDF de résultat contenant des données RDF à propos de ressources. Le client ne connait pas la structure du RDF interrogé; C'est le service d'interrogation qui décrit les données selon sa configuration.

Requête sur le graphe précédent:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
DESCRIBE *
WHERE    { ?x foaf:mbox ?y . }

Résultat:

@prefix foaf:  <http://xmlns.com/foaf/0.1/> .

[ foaf:mbox  <mailto:jlow@example.com> ;
foaf:name  "Johnny Lee Outlaw" ] .

[ foaf:mbox  <mailto:peter@example.org> ;
foaf:name  "Peter Goodguy" ] .

[ foaf:mbox  <mailto:carol@example.org> ] .

Nous avons donc la liste de toutes les données du graphe avec leurs descriptions. Nous savons par exemple que nous pouvons rechercher des objets ayant pour prédicats foaf:mbox et foaf:name.

Exemple plus précis pour une seule variable:

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x
WHERE    { ?x foaf:mbox <mailto:jlow@example.com> . }

Résultat:

@prefix foaf:  <http://xmlns.com/foaf/0.1/> .

[ foaf:mbox  <mailto:jlow@example.com> ;
foaf:name  "Johnny Lee Outlaw" ] .

Alors qu'un simple SELECT aurait retourné le noeud anonyme dont on n'a rien à faire :

x
_:b0

Importer des graphs pour une requête FROM

  • FROM url: import d'un graphe dans le graphe par défaut (fusion de graphes individuels); Si une interrogation présente plusieurs clauses FROM, en fournissant plusieurs adresses IRI pour indiquer le graphe par défaut, alors le graphe par défaut est fondé sur la fusion RDF des graphes.&
  • FROM NAMED url: import d'un graphe nommé dans le jeu de données;
  • Les données sont lues depuis l'url.

Exemple:

SELECT *
# Import de <ds-dft.ttl> dans le graphe par défaut
FROM       <ds-dft.ttl>
# Import de 2 graphes nommés dans le jeu de données
FROM NAMED <ds-ng-1.ttl>
FROM NAMED <ds-ng-2.ttl>
WHERE {
    ?s ?p ?o .
    GRAPH ?g { ?s_g ?p_g ?o_g }
}

Cas d'utilisation: Un grapge par défaut contenant des métadonnées sur les graphes nommés importés.

Requêter sur un ou plusieurs jeux de données GRAPH

GRAPH uri { ... pattern ... }
  • Un modèle sera identifié sur le graphe dans le jeu de données, ayant l'uri donnée;
  • Si une variable inconnue est donnée, tous les graphes nommés (donc pas le graphe par défaut) seront interrogés.
  • GRAPH change le graphe actif pour le filtrage des motifs dans une section de la requête. En dehors, le graphe par défaut est filtré.

En général le graphe par défaut peut :

  • être la fusion de tous les graphes nommés
  • être un inventaire des graphes nommés (provenance, date, etc.)

Fusion de TOUS les graphes (nommés + def) :

PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
# Formatage de la sortie
PREFIX  :       <.>

SELECT *
{
    { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } }
}

Sélection dynamique d'un graphe nommé selon une information présente dans le graphe par défaut (date) :

PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
PREFIX  :       <.>

SELECT ?date ?title
{
    ?g dc:date ?date .
    FILTER (?date > "2005-08-01T00:00:00Z"^^xsd:dateTime ) .
    GRAPH ?g
        { ?b dc:title ?title }
}

Motifs

Filtrage

Les clauses FILTER restreignent les solutions à celles que l'expression de filtre évalue à true. Une contrainte exprimée par FILTER s'applique sur tout le motif de groupe ({}) des solutions dans lequel le filtre est placé (quelle-que-soit sa position).

Ex:

@prefix dc:   <http://purl.org/dc/elements/1.1/> .
@prefix :     <http://example.org/book/> .
@prefix ns:   <http://example.org/ns#> .

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .

Requête (1 motif de graphe de groupe + 1 motif de graphe élémentaire constitué de 2 motifs de triplet + 2 filtres):

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title ?price

# Début motif de graphe de groupe
# Ne pas oublier le . ici
WHERE   { ?x dc:title ?title .
          ?x ns:price ?price .
        # Filtrage casse indépendante sur ?title
        # Le 3ième paramètre de la clause `FILTER` est un flag
        # définissant la sensibilité à la casse du filtre.
        FILTER regex(?title, "^SPARQL", "i")
        # Filtrage valeurs numériques
        FILTER (?price > 40)
        # Filtrage par URI
        FILTER (?x = <http://my-graph.com#uri10>)
}

Résultat:

?title             | ?price
"SPARQL Tutorial"  | 42

Filtrage sur un agrégat

Regrouper les données et compter les occurences de chaque groupe: Le filtrage sur un agrégat, HAVING est très souvent utilisé en même temps que GROUP BY bien que ce ne soit pas obligatoire.

SELECT (COUNT(?book) AS ?total)
{ motif }
GROUP BY ?author
HAVING (COUNT(?book) >= 2)

Valeurs optionnelles

Utiles pour ne pas rejeter 1 solution à cause de parties du motif d'interrogation qui ne correspondent pas dans le graphe. Si la partie optionnelle ne correspond pas, elle ne crée aucune liaison et n'élimine pas la solution. (Cf plus bas)

Syntaxe:

motif OPTIONAL { motif }

Exemple sur le graphe du paragraphe précédent:

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title ?price

# Le . ici est facultatif
WHERE   { ?x dc:title ?title .
        # Filtrage optionnel sur les valeurs numériques
        OPTIONAL { ?x ns:price ?price .
                   FILTER (?price > 50)
        }
}

Résultat:

title               | price
"The Semantic Web"  |
"SPARQL Tutorial"   |

Aucune solution de prix n'est affichée car aucun motif du graphe optionnel ne conduit à 1 solution impliquant la variable price.

Le nombre de résultats ne change pas par rapport à une requête sans opérateur OPTIONAL. Pour cela il faut déplacer la condition hors du motif de groupe optionnel et s'assurer que la variable price n'y est plus liée :

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title ?price

# Le . ici est facultatif
WHERE   { ?x dc:title ?title .
        # Filtrage optionnel sur les valeurs numériques
        OPTIONAL { ?x ns:price ?price .}
        FILTER (!bound(?price) || ?price > 50)
}

Plusieurs OPTIONAL: Cf UNION ou OPTIONAL ?.

Union de motifs de graphes alternatifs

Combinaison de motifs de graphe de telle sorte que l'un des motifs alternatifs peut correspondre. Dans le cas où plusieurs matchs sont possibles, toutes les solutions possibles sont trouvées.

Exemple:

# Données enregistrées en utilisant 2 versions différentes de propriétés
@prefix dc10:  <http://purl.org/dc/elements/1.0/> .
@prefix dc11:  <http://purl.org/dc/elements/1.1/> .

_:a  dc10:title     "SPARQL Query Language Tutorial" .
_:a  dc10:creator   "Alice" .

_:b  dc11:title     "SPARQL Protocol Tutorial" .
_:b  dc11:creator   "Bob" .

_:c  dc10:title     "SPARQL" .
_:c  dc11:title     "SPARQL (updated)" .

Les alternatives de motifs sont indiquées par le mot-clé UNION:

PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

SELECT ?title
WHERE  { { ?book dc10:title  ?title } UNION { ?book dc11:title  ?title } }

Résultat :

title
"SPARQL Protocol Tutorial"
"SPARQL"
"SPARQL (updated)"
"SPARQL Query Language Tutorial"

Requête avec plusieurs motifs de triplet dans les motifs (remarquer les version 1.0 et 1.1 des propriétés Dublin Core :

PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

SELECT ?title ?author
WHERE {
        { ?book dc10:title ?title .
          ?book dc10:creator ?author }
        UNION
        { ?book dc11:title ?title .
          ?book dc11:creator ?author }
}

Résultat :

author   | title
"Bob"    | "SPARQL Protocol Tutorial"
"Alice"  | "SPARQL Query Language Tutorial"

Note : Ne marche pas si le titre et l'auteur ne sont pas créés simultanément avec la même version des propriétés. Note : Pour afficher la provenance des données, utiliser des variables ?author différentes.

Note : On pourrait aussi utiliser un FILTER (requête plus lente car devant tester tous les triplets correspondants et ensuite tester les prédicats):

PREFIX dc10:  <http://purl.org/dc/elements/1.0/>
PREFIX dc11:  <http://purl.org/dc/elements/1.1/>

SELECT ?title
WHERE {
    [] ?p ?title
    FILTER ( ?p = dc10:title || ?p = dc11:title )
}

UNION ou OPTIONAL ?

  • OPTIONAL est utile pour augmenter les solutions trouvées,
  • UNION est utile pour concaténer les solutions à partir de deux possibilités.

PS: Attention lors de l'usage d'un objet nommé de façon identique dans chaque OPTIONAL, il s'agit d'une requête dépendant de l'ordre. Si le premier champ trouve une solution, les valeurs prises par les variables seront testées par le 2ième champ.

Modificateurs

Les solutions générées par les motifs d'interrogation peuvent être traitées en tant que séquences et ordonnées.

Tri : ORDER BY

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT ?name
WHERE { ?x foaf:name ?name }
# Par défaut: ASC()
ORDER BY DESC(?name)
# ou condition de tri personnalisé
ORDER BY x:func(?x)

Voir priorités SPARQL W3C - 9.1 ORDER BY.

Limitations du nombre de solutions : OFFSET & LIMIT

À utiliser avec ORDER BY pour rendre prévisible l'ordre des solutions.

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>

SELECT  ?name
WHERE   { ?x foaf:name ?name }
# Tri
ORDER BY ?name
# Limite sup du nombre de solutions
LIMIT   5

Doublons : DISTINCT & REDUCED

DISTINCT élimine les solutions en double au niveau de l'affichage (chaque solution liant les mêmes variables aux mêmes termes RDF). REDUCED ne se limite pas au nettoyage de l'affichage et va comparer toutes les données liées à la variable affichée.

Ex:

@prefix  foaf:  <http://xmlns.com/foaf/0.1/> .

_:x    foaf:name   "Alice" .
_:x    foaf:mbox   <mailto:alice@example.com> .

_:y    foaf:name   "Alice" .
_:y    foaf:mbox   <mailto:asmith@example.com> .

_:z    foaf:name   "Alice" .
_:z    foaf:mbox   <mailto:alice.smith@example.com> .

Requête:

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?name WHERE { ?x foaf:name ?name }

Résultat:

name
"Alice"

Requêtes d'écriture

Suppression de triplets

La clause WITH permet de définir le graphe qui sera modifié et requêté. Si le nom du graphe n'est pas renseigné par WITH ou explicitement dans la clause WHERE, le graphe par défaut du triplestore sera utilisé.

WITH <g1> DELETE { a b c } INSERT { x y z } WHERE { ... }

# is considered equivalent to:

DELETE { GRAPH <g1> { a b c } } INSERT { GRAPH <g1> { x y z } } USING <g1> WHERE { ... }

Ex:

Supprimer tous les triplets mentionnant le nom "Fred" dans le graphe nommé . La clause WITH assure que le graphe est celui duquel les triplets seront à la fois recherchés par WHERE et retirés par DELETE.

WITH <urn:sparql:tests:delete:where>
DELETE { ?person ?property ?value }
WHERE { ?person ?property ?value ; <http://xmlns.com/foaf/0.1/givenName> "Fred" }

# PS: Souci avec Virtuoso 07.20.3217: WITH ne marche pas. Mieux vaut utiliser l'exemple suivant:

DELETE { GRAPH <urn:sparql:tests:delete:where> { ?person ?property ?value }}
WHERE { ?person ?property ?value ; <http://xmlns.com/foaf/0.1/givenName> "Fred" }

Système d'implication

Avec les triplestore, les données ne sont plus liées à des schémas statiques. Les schémas sont contenus directement au sein des données.

Le système d'implication permet:

  • des inférences : déduction d'une conclusion à partir d'assertions, énoncés, ou propositions affirmés comme vrais.
  • de détecter les implications incohérentes : les erreurs d'intégrité des données et requêtes (similaire aux mécanismes d'intégrité dans un SGBDr).

Un graphe RDF est bien formé si ses données respectent le système d'implication.

Implications RDF & RDFS

Exemple repris de wikiversity - SPARQL.

Données:

Un chien est un animal
Le chat1 est un chat
Les chats sont des animaux
Les zoos hébergent uniquement des animaux
Le zoo1 héberge le chat2

Graphe:

@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ex:   <http://example.org/> .
@prefix zoo:   <http://example.org/zoo/> .
ex:dog1    rdf:type         ex:animal .
ex:cat1    rdf:type         ex:cat .
ex:cat     rdfs:subClassOf  ex:animal .
zoo:host   rdfs:range       ex:animal .
ex:zoo1    zoo:host         ex:cat2 .

Requête:

PREFIX  ex: <http://example.org/>
SELECT ?animal
WHERE
{ ?animal a ex:animal . }

En toute logique:

  • ex:dog1 est une réponse à cause du triplet (1).
  • Intuitivement, on peut s'attendre à ce qu'ex:cat1 soit aussi une réponse parce qu'il est un chat (2) et tous les chats sont des animaux (3).
  • Même ex:cat2 est un animal parce qu'il est hébergé par un zoo (5) et tout ce qui est hébergé par un zoo est un animal (4).

Or sans système d'implication RDF / RDFS, voici le résultat:

animal
<http://example.org/dog1>

Il n'y a pas de raisonnement de la part du système.

Avec les implications RDF quelques inférences sont possibles:

Requête:

SELECT ?prop
WHERE { ?prop a rdf:Property }

Résultat:

prop
<http://example.org/zoo/host>

zoo:host est une propriété du type ex:zoo1

Avec les implications RDFS:

Résultat:

animal
<http://example.org/dog1>
<http://example.org/cat1>
<http://example.org/cat2>
  • ex:cat1 : le triplet 3 indique que les chats sont des animaux et le triplet 2 indique qu'ex:cat1 est un chat donc ex:cat1 est un animal
  • ex:cat2 : le triplet 4 indique que la propriété zoo:host attend uniquement des objets de type animal et le triplet 5 indique qu'ex:cat2 est une valeur de la propriété zoo:host donc, si le graphe est bien formé, qu'ex:cat2 est un animal.

Avec les implications OWL:

OWL est le sous-ensemble logique de RDFS. Le raisonneur est bien plus puissant (contraintes de domaines, cardinalités, transitivité).

TODO

Exemples

Les exemples 1 et 2 vont porter sur un graphe RDF fait en TP:

@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .
@prefix :   <http://local#> .

:glucose        :estConsommePar     :R1.
:eau            :estConsommePar     :R1.
:eau            :estConsommePar     :R2.
:eau            :estConsommePar     :R3.
:mannose        :estConsommePar     :R2.
:sulfate        :estConsommePar     :R3.

:R1             :produit            :D.
:R1             :produit            :E.
:R2             :produit            :E.
:R2             :produit            :F.
:R3             :produit            :F.
:R3             :produit            :H.

:glucose        rdf:type            :metabolite.
:mannose        rdf:type            :metabolite.
:sulfate        rdf:type            :metabolite.
:eau            rdf:type            :metabolite.

:R1             rdf:type            :reaction.
:R2             rdf:type            :reaction.
:R3             rdf:type            :reaction.

:glucose        :aStoechio          :R1glu.
:R1glu          :hasValue           "1"^^xsd:int.
:R1glu          :estConsommePar     :R1.

Ex 1

# On veut obtenir toutes les réactions qui consomment du glucose
# On prend chaque réaction du graphe, sans redondance
SELECT DISTINCT ?reaction
WHERE{
    :glucose :estConsommePar ?reaction .
}

Ex 2

# On veut obtenir toutes les réactions qui produisent du E.
SELECT DISTINCT ?reaction
WHERE{
    ?reaction :produit :E .
}

Ex 3 A partir d'ici, ce seront des exemples de requêtes sur le CHEBI, une base de données sur les petites molécules.

# IRI
PREFIX chebi: <http://purl.obolibrary.org/obo/CHEBI_>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>


# Pour obtenir tout les descendants du glucose (id chebi: 17234)
# On récupère les descendants, avec son label si il existe.
SELECT DISTINCT ?desc (str(?descLabel) as ?label)
WHERE{
    # Qui sont sous classes du glucose
    # Le + enlève l'ancêtre direct,
    # si on veut tout y compris les parents directs, mettre *
    ?desc rdfs:subClassOf+ chebi:17234.
    # si il existe un descLabel du descendant, il est retourné
    OPTIONAL {?desc rdfs:label ?descLabel.}
}

Ex 4

# Pour obtenir tout les ancetres du glucose:
SELECT DISTINCT ?anc (str(?ancLabel) as ?label)
WHERE {
    chebi:17234 rdfs:subClassOf+ ?anc .
    # élimination des noeuds anonymes
    ?anc rdf:type owl:Class .
    OPTIONAL { ?anc rdfs:label ?ancLabel .  }
}

Ex 5

# Ancêtres communs du glucose et myricoside
SELECT DISTINCT ?anc (str(?ancLabel) as ?label)
WHERE {
   ?molec rdfs:subClassOf+ ?anc .
   # élimination des noeuds anonymes
   ?anc rdf:type owl:Class .
   OPTIONAL { ?anc rdfs:label ?ancLabel .  }
   VALUES molec { (chebi:17234, chebi:7055) }
}

Références