Ce document présente les requêtes qui, pour un concept donné C, permettent de retrouver et d'ordonner l'ensemble des resources MICA qui y sont liées par une annotation (soit parcequ'elles sont directement annotées par le concept C, soit parcequ'elles sont annotées par un ou des sous concepts de C).
Tout au long de ce document, pour simplifier l'écriture des URIs désignant les resources, les prefixes suivants sont utilisés :
Par exemple
Pour expliquer et tester les différentes requêtes présentées dans ce document nous travaillons sur le jeu de données suivant :
Sept concepts sont définis de manière hiérarchique:
Cinq ressources de type MICASheet sont définies et annotées par les concepts précédents.
La figure qui suit présente le graphe RDF correspondant à ce jeu de données (seules les relations hiérarchiques entre concepts et les annotations des resources MICA sont représentées).
Ce jeu de données est défini (en notation Turtle) dans le fichier RankingTestData.ttl
@prefix micavocab: <https://w3id.org/mica/ontology/MicaOntology/> . @prefix skos: <http://www.w3.org/2004/02/skos/core#> . @prefix dcterms: <http://purl.org/dc/terms/> . @prefix micaresource: <https://w3id.org/mica/resource/> . @prefix micamodel: <https://w3id.org/mica/ontology/MicaModel#> . #Concepts micavocab:C1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1". micavocab:C1_1_1 a skos:Concept ; skos:broader micavocab:C1_1 ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1_1". micavocab:C1_1_2 a skos:Concept ; skos:broader micavocab:C1_1 ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1_2". micavocab:C1_1_1_1 a skos:Concept ; skos:broader micavocab:C1_1_1 ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1_1_1". micavocab:C1_1_1_2 a skos:Concept ; skos:broader micavocab:C1_1_1 ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1_1_2". micavocab:C1_1_1_3 a skos:Concept ; skos:broader micavocab:C1_1_1 ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1_1_3". micavocab:C1_1_1_2_1 a skos:Concept ; skos:broader micavocab:C1_1_1_2 ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C1_1_2_1". #Sheets micaresource:S1 a micamodel:MICASheet ; dcterms:title "S1" ; micamodel:hasDomainConcept micavocab:C1_1_1 . micaresource:S2 a micamodel:MICASheet ; dcterms:title "S2" ; micamodel:hasDomainConcept micavocab:C1_1_1_1,micavocab:C1_1_1_2_1 . micaresource:S3 a micamodel:MICASheet ; dcterms:title "S3" ; micamodel:hasDomainConcept micavocab:C1_1_1_3 . micaresource:S4 a micamodel:MICASheet ; dcterms:title "S4" ; micamodel:hasDomainConcept micavocab:C1_1_1_2,micavocab:C1_1_1_3 . micaresource:S5 a micamodel:MICASheet ; dcterms:title "S5" ; micamodel:hasDomainConcept micavocab:C1_1_2 .
Étant donné le fait qu’on a configuré les inferences sur les concepts, tous les concepts qui annotés une ressource, contiennnent le predicate hasMICAConcept. Ce qui implique le fait qu’on peut traiter tous les concepts de la même façon sans se soucier de leur ontologie respective.
Pour chercher un type de ressource donnée, on precise dans la requête le type.
Par exemple:
Pour les exemples suivants, on cherche les Sheets qui sont annotés par le concept C1_1_1_1 ou ses sous concepts.
Dans ce cas, on sélectionne les sheets par leur URI ?sheetURI et les concepts qui les annotés par leur URI ?conceptURI
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI ?conceptURI WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1_1 ; } order by ?sheetURI ?conceptURI
Le résultat de la requête
sheetURI | conceptURI |
micaresource:S1 | micavocab:C1_1 |
micaresource:S2 | micavocab:C1_1_1 |
micaresource:S2 | micavocab:C1_1_2_1 |
micaresource:S3 | micavocab:C1_1_3 |
micaresource:S4 | micavocab:C1_1_2 |
micaresource:S4 | micavocab:C1_1_3 |
Les différents cas qu’on peut avoir:
si un sheet est annoté par
Dans ce cas, on aura une seule fois sheetURI pour un sheet donné.
Dans ce cas, on aura plusieurs fois SheetURI pour un sheet donné. C’est pouquoi, il faut grouper les concepts via une deuxième sélection.
Pour avoir une fois, ?sheetURI par chaque sheet et l'ensemble de concepts sous forme d’un String, on utilise la fonction SPARQL group_concat et on sépare des concepts par une virgule.
La requête précédente devient :
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI (group_concat( ?conceptURI; separator =";" )AS ?conceptURIs) WHERE { SELECT ?sheetURI ?conceptURI WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1_1 ; } } GROUP BY ?sheetURI ?conceptURIs
Le résultat de la requête
sheetURI | conceptURIs |
micaresource:S3 | "micavocab:C1_1_3" |
micaresource:S4 | "micavocab:C1_1_3;micavocab:C1_1_2" |
micaresource:S1 | "micavocab:C1_1" |
micaresource:S2 | "micavocab:C1_1_1;micavocab:C1_1_2_1" |
Jusqu’ici, on vient de faire la recherche de sheets mais ils ne sont pas encore ordonné. pour ce faire, nous avons besoin de compter le nombre de parents de chaque concepts et ordonne le résultat par ce nombre.
La requête de l'étape 2 devient :
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI ?conceptURI (COUNT(distinct ?parentURI) as ?nbParentURI) WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1_1 ; skos:broaderTransitive ?parentURI. } GROUP BY ?sheetURI ?conceptURI ?nbParentURI ORDER BY ?nbParentURI ?sheetURI ?conceptURI
Dans ce cas, on a encore le même problème que pour l'étape 1 car un sheet peut être annoté par plusieurs concepts, On compte le nombre de parents pour chaque concept. il y aura plusieurs fois ?sheetURI pour un sheet donné.
Le résultat de la requête
sheetURI | conceptURI | nbParentURI |
micaresource:S1 | micavocab:C1_1 | "2"^^xsd:integer |
micaresource:S2 | micavocab:C1_1_1 | "3"^^xsd:integer |
micaresource:S3 | micavocab:C1_1_3 | "3"^^xsd:integer |
micaresource:S3 | micavocab:C1_1_2 | "3"^^xsd:integer |
micaresource:S4 | micavocab:C1_1_3 | "3"^^xsd:integer |
micaresource:S2 | micavocab:C1_1_2_1 | "4"^^xsd:integer |
Pour éviter la redondance de ?sheetURI,on calcule le nombre de parents pour le concept de référence qui est dans notre cas C1_1_1_1.
La requête de l'étape 3 devient :
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI (group_concat( ?conceptURI; separator =";" ) AS ?conceptURIs) (min(?nbParentURI-?nbParentRefURI) as ?rank) WHERE { SELECT ?sheetURI ?conceptURI (COUNT(distinct ?parentURI) as ?nbParentURI) (COUNT( distinct ?parentRefURI) as ?nbParentRefURI) WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1_1 ; skos:broaderTransitive ?parentURI. micavocab:C1_1 skos:broaderTransitive ?parentRefURI. } GROUP BY ?sheetURI ?conceptURI } GROUP BY ?sheetURI ORDER BY ?rank ?sheetURI ?conceptURIs
Tout d’abord, on cherche le nombre de parents de la réference ensuite,on cherche le nombre des parents de chaque concept.
Si il n' y a pas des exaequos, on n’a l’ordre des sheets avec le paramètre ?rank
Le résultat de la requête
sheetURI | conceptURIs | rank |
micaresource:S1 | "micavocab:C1_1" | "0"^^xsd:integer |
micaresource:S2 | "micavocab:C1_1_1;micavocab:C1_1_2_1" | "1"^^xsd:integer |
micaresource:S3 | "micavocab:C1_1_3" | "1"^^xsd:integer |
micaresource:S4 | "micavocab:C1_1_3;micavocab:C1_1_2_1" | "1"^^xsd:integer |
Si il y a des exaequos, c’est un peu complique.
L’algorithme suivant est proposé dans le cas où il y a des exaequos. Dans ce cas, on calcule la distance la plus éloigne. c’est à dire le sheet annoté par un concept le plus éloigne sera dernière.
La requête de l'étape 4 devient :
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI (group_concat( ?conceptURI; separator =";" )AS ?conceptURIs) (min(?nbParentURI-?nbParentRefURI) as ?rank) (max(?nbParentURI-?nbParentRefURI) as ?nbmax) WHERE { SELECT ?sheetURI ?conceptURI (COUNT(distinct ?parentURI) as ?nbParentURI) (COUNT( distinct ?parentRefURI) as ?nbParentRefURI) WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1_1 ; skos:broaderTransitive ?parentURI. micavocab:C1_1 skos:broaderTransitive ?parentRefURI. } GROUP BY ?sheetURI ?conceptURI } GROUP BY ?sheetURI ORDER BY ?rank ?nbmax ?sheetURI
Le résultat de la requête
sheetURI | conceptURIs | rank | ?nbmax |
micaresource:S1 | "micavocab:C1_1" | "0"^^xsd:integer | "0"^^xsd:integer |
micaresource:S4 | "micavocab:C1_1_3;micavocab:C1_1_2" | "1"^^xsd:integer | "1"^^xsd:integer |
micaresource:S2 | "micavocab:C1_1_1;micavocab:C1_1_2_1" | "1"^^xsd:integer | "2"^^xsd:integer |
micaresource:S3 | "micavocab:C1_1_3" | "1"^^xsd:integer | "1"^^xsd:integer |
Si les distances nbmax sont égaux aussi. On propose l'étape suivante.
Pour cet étape, le nombre de concepts qui annotent les sheets exaequos, permet les partager. Le sheet ayant un nombre inférieur de concepts annotés sera considéré comme le moins important. Alors que le sheet ayant un nombre supérieur sera considéré comme le plus important.
La requête del'étape 5 devient :
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI (group_concat( ?conceptURI; separator =";" )AS ?conceptURIs) (min(?nbParentURI-?nbParentRefURI) as ?rank) (max(?nbParentURI-?nbParentRefURI) as ?nbmax) (COUNT(distinct ?conceptURI) as ?nbConceptURIs) WHERE { SELECT ?sheetURI ?conceptURI (COUNT(distinct ?parentURI) as ?nbParentURI) (COUNT( distinct ?parentRefURI) as ?nbParentRefURI) WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1_1 ; skos:broaderTransitive ?parentURI. micavocab:C1_1 skos:broaderTransitive ?parentRefURI. } GROUP BY ?sheetURI ?conceptURI } GROUP BY ?sheetURI ORDER BY ?rank ?nbmax DESC(?nbConceptURIs) ?sheetURI
Le résultat de la requête
sheetURI | conceptURIs | rank | nbmax | nbConceptURIs |
micaresource:S1 | "micavocab:C1_1" | "0"^^xsd:integer | "0"^^xsd:integer | "1"^^xsd:integer |
micaresource:S4 | "micavocab:C1_1_3;micavocab:C1_1_2" | "1"^^xsd:integer | "1"^^xsd:integer | "2"^^xsd:integer |
micaresource:S2 | "micavocab:C1_1_1;micavocab:C1_1_2_1" | "1"^^xsd:integer | "2"^^xsd:integer | "2"^^xsd:integer |
micaresource:S3 | "micavocab:C1_1_3" | "1"^^xsd:integer | "1"^^xsd:integer | "1"^^xsd:integer |
Pour expliquer et tester l'algorithme nous allons travailler sur le jeu de données suivant :
les concepts sont définis de manière hiérarchique:
Les ressources de type MICASheet sont définies et annotées par les concepts précédents.
La figure qui suit présente le graphe RDF correspondant à ce jeu de données (seules les relations hiérarchiques entre concepts et les annotations des resources MICA sont représentées).
Ce jeu de données est défini (en notation Turtle) dans le fichier RankingTestData2.ttl
@prefix micavocab: <https://w3id.org/mica/ontology/MicaOntology/> . @prefix skos: <http://www.w3.org/2004/02/skos/core#> . @prefix dcterms: <http://purl.org/dc/terms/> . @prefix micaresource: <https://w3id.org/mica/resource/> . @prefix micamodel: <https://w3id.org/mica/ontology/MicaModel#> . #Concepts micavocab:C0 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:prefLabel "C0". micavocab:C1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C0 ; skos:prefLabel "C1". micavocab:C1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C1 ; skos:prefLabel "C1_1". micavocab:C1_2 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C1 ; skos:prefLabel "C1_2". micavocab:C1_1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C1_1 ; skos:prefLabel "C1_1_1". micavocab:C1_2_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C1_2 ; skos:prefLabel "C1_2_1". micavocab:C2 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C0 ; skos:prefLabel "C2". micavocab:C2_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C2 ; skos:prefLabel "C2_1". micavocab:C2_2 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C2 ; skos:prefLabel "C2_2". micavocab:C2_1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C2_1 ; skos:prefLabel "C2_1_1". micavocab:C2_2_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C2_2 ; skos:prefLabel "C2_2_1". micavocab:C3 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C0 ; skos:prefLabel "C3". micavocab:C3_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C3 ; skos:prefLabel "C3_1". micavocab:C3_2 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C3 ; skos:prefLabel "C3_2". micavocab:C3_1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C3_1 ; skos:prefLabel "C3_1_1". micavocab:C3_2_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C3_2 ; skos:prefLabel "C3_2_1". micavocab:C4 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C0 ; skos:prefLabel "C4". micavocab:C4_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C4 ; skos:prefLabel "C4_1". micavocab:C4_2 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C4 ; skos:prefLabel "C4_2". micavocab:C4_1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C4_1 ; skos:prefLabel "C4_1_1". micavocab:C4_2_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C4_2 ; skos:prefLabel "C4_2_1". micavocab:C5 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C0 ; skos:prefLabel "C5". micavocab:C5_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C5 ; skos:prefLabel "C5_1". micavocab:C5_2 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C5 ; skos:prefLabel "C5_2". micavocab:C5_1_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C5_1 ; skos:prefLabel "C5_1_1". micavocab:C5_2_1 a skos:Concept ; skos:inScheme micavocab:DomainScheme ; skos:broader micavocab:C5_2 ; skos:prefLabel "C5_2_1". #Sheets micaresource:S1 a micamodel:MICASheet ; dcterms:title "S1" ; micamodel:hasDomainConcept micavocab:C1,micavocab:C2, micavocab:C3,micavocab:C4 . micaresource:S2 a micamodel:MICASheet ; dcterms:title "S2" ; micamodel:hasDomainConcept micavocab:C1,micavocab:C2, micavocab:C3 . micaresource:S3 a micamodel:MICASheet ; dcterms:title "S3" ; micamodel:hasDomainConcept micavocab:C1 . micaresource:S4 a micamodel:MICASheet ; dcterms:title "S4" ; micamodel:hasDomainConcept micavocab:C1_1,micavocab:C2 . micaresource:S5 a micamodel:MICASheet ; dcterms:title "S5" ; micamodel:hasDomainConcept micavocab:C1_2,micavocab:C2_2, micavocab:C3_1,micavocab:C4 . micaresource:S6 a micamodel:MICASheet ; dcterms:title "S6" ; micamodel:hasDomainConcept micavocab:C4_2 . micaresource:S7 a micamodel:MICASheet ; dcterms:title "S7" ; micamodel:hasDomainConcept micavocab:C1_2,micavocab:C2_1_1. micaresource:S8 a micamodel:MICASheet ; dcterms:title "S8" ; micamodel:hasDomainConcept micavocab:C1_1_1. micaresource:S9 a micamodel:MICASheet ; dcterms:title "S9" ; micamodel:hasDomainConcept micavocab:C2_2_1,micavocab:C3_1_1,micavocab:C4_1. micaresource:S10 a micamodel:MICASheet ; dcterms:title "S10" ; micamodel:hasDomainConcept micavocab:C3_2_1,micavocab:C4_2_1. micaresource:S11 a micamodel:MICASheet ; dcterms:title "S11" ; micamodel:hasDomainConcept micavocab:C5.
pour cet exemple, nous allons chercher à classer les ressources annotées par micavocab:C1,micavocab:C2, micavocab:C3,micavocab:C4
pour ce faire, on cherche d'abord les ressources annotées par chaque concept ou sous concepts. en utilisant, la requête suivante:
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX micavocab: <https://w3id.org/mica/ontology/MicaOntology/> PREFIX model: <https://w3id.org/mica/ontology/MicaModel#> PREFIX micaresource: <https://w3id.org/mica/resource/> SELECT ?sheetURI (group_concat( ?conceptURI; separator =";" )AS ?conceptURIs) (min(?nbParentURI-?nbParentRefURI) as ?rank) (max(?nbParentURI-?nbParentRefURI) as ?nbmax) (COUNT(distinct ?conceptURI) as ?nbConceptURIs) WHERE { SELECT ?sheetURI ?conceptURI (COUNT(distinct ?parentURI) as ?nbParentURI) (COUNT( distinct ?parentRefURI) as ?nbParentRefURI) WHERE { ?sheetURI a model:Sheet; model:hasMicaConcept ?conceptURI. ?conceptURI skos:broaderTransitive micavocab:C1 ; skos:broaderTransitive ?parentURI. micavocab:C1 skos:broaderTransitive ?parentRefURI. } GROUP BY ?sheetURI ?conceptURI } GROUP BY ?sheetURI ORDER BY ?rank ?nbmax DESC(?nbConceptURIs) ?sheetURI
On remplace micavocab:C1 par l'URI du concept cherché: les résultats de cette requête permet de créer un candidate ressource avec un score
le diagramme UML suivant illustre le fonctionnement de candidate Ressource
Voici l'algorithme est le suivant:
pour chaque ressource annotée, on cherche le score ensuite on ajoute le score et le candidat dans la liste des candidats et puis on calcule le nombre d'appartion d'un candidate dans les differents requêtes
on classe par l'ordre decroissante de ce nombre, plus une ressource est apparu dans plusieurs recherches, plus la ressource est bien classée. si deux ressources sont égaux on va les classer en fonction de leurs scores , ce qui implique le calcul pour chaque candidat des paramètres suivants:
une fois ces trois paramètres calcules
on ordonne les classement par rankTotal l'ordre croissante
si il y a des exaequos, on ordonne par le nbMaxTotal l'ordre croissante
si il y a des exaequos, on ordonne par le nbConceptsURITotal