Modèle, Présentateur et valeur

Cela fait un moment maintenant que je travaille sur les valeurs polymorphiques, leur stockage et leur consultation. Cela se passe autant sur le convertisseur de données Comitards vers Folkopedia que sur l’API de consultation des données et son administration frontend. Ce que vous ne voyez pas, et de ce fait moi non plus avant de longues heures de boulot, c’est cette quantité d’efforts à fournir avant de faire un seul test. Et même si la théorie est sexy, sa mise en place est plutôt difficile car répartie ci et là. Voici donc un mot à ce sujet.

Vocabulaire

Une première chose est qu’il faut bien comprendre quelques notions définies.

EntitéEst un ensemble, une structure, d’attributs (prédicat) et de leur valeurs (objet). (une personne, un objet, un truc, …)
PrédicatEst un attribut représentant une partie de l’entité (un prénom d’une personne)
TypePrédicat d’une entité permettant de connaître la nature de celle-ci
ModèleEntité représentant la composition maximum d’une structure. Une personne peut avoir un prénom, un nom et une date de naissance (différent de l’instance de ce modèle qui peut n’être que partiel)
PrésentateurIllustre une partie d’une entité via une sélection de prédicats souhaités et/ou à exclure. C’est une couche de présentation.
ValeurContenu de l’objet d’un prédicat pour une entité. Si on encode votre prénom, la valeur est le prénom, qu’importe la structure porteuse autour.

Entité et modèle

Un modèle est une entité indépendante qui contient la trinité nom/description/type (qui sera « modèle »), ainsi que d’autres prédicats selon la nature de l’entité à modéliser : une personne, un groupe, un chant, … Le modèle a pour vocation de pouvoir typer des entités et offrir un cadre définit lors des futurs encodage via formulaire généré sur base de ce modèle.

Une entité pourra être du type de ce modèle pour devenir alors une instance de ce modèle, ainsi on a le modèle représentant les possibles attributs que l’on peut encoder et des instances avec les infos que l’on a vraiment pour X (une personne, un groupe, un chant, …).

Ce qu’il faut retenir c’est la différence entre un modèle représentant une chose, et les instances de ce modèle, qui sont cette chose décrite unitairement. Ainsi on peut identifier une personne d’une autre mais comprendre que ces 2 entités sont des semblable par leur type.

Présentateur

Le présentateur est une représentation, un extrait d’une instance d’une entité sur base d’une liste de prédicats à afficher ou exclure. D’abord en se basant sur le modèle qui représente l’ensemble complet de prédicats disponibles, et ensuite sur ce que l’instance a réellement d’encodé.

Si vous avez une personne ayant un prénom, un nom, une date de naissance et d’autres informations, que le présentateur limite au nom et prénom, le résultat ne contiendra qu’au maximum le nom et prénom. Au maximum car si la personne n’a pas de nom mais qu’un prénom et d’autres informations, seul le prénom ressortira.

Le présentateur est composé de 2 prédicats majeurs, permettant d’appliquer un comportement, d’inclusion et/ou d’exclusion. On veut inclure quelques prédicats du modèle (tous si on ne précise pas ce prédicat), et/ou on veut exclure des prédicats basé sur ce qui aura finalement été retenu. Par cette mécanique on peut utiliser un même présentateur pour 2 modèles similaire mais potentiellement différents.

Le fait d’avoir regroupé sous 2 prédicats (inclusion/exclusion) les prédicats que l’on souhaite voir ou non, permet de soustraire la trinité dont on a parlé plus haut, à savoir nom/description/type qui font partie de l’identité d’une entité quelconque, hors une entité (instance) n’a pas forcément cette partie système encodée, si on les sélectionne avec le reste comme avant on se retrouve avec un tas de données parasites vides non désirées. Cette séparation montre bien la notion technique et métier.

Il faut bien comprendre qu’un présentateur limite les prédicats exposés (couche de présentation de l’information) et n’est pas un modèle qui, lui, contient tous les possibles encodables.

Valeur

Cela pourrait sembler trivial, de dire que la valeur c’est la valeur du prédicat, donc le contenu de la 3ème colonne du SPO, mais évidemment ce n’est pas aussi simple. Une valeur peut être complexe et contenir des métadonnées (ordre de l’information, date de modification, …), ce qui se traduit par une encapsulation de cette valeur au sein d’une nouvelle entité. Si on prend l’objet (3ème colonne) on aura un identifiant d’entité et non plus la valeur telle quelle, il faut refaire un tour et inspecter cette entité en cherchant le prédicat de contenu pour enfin avoir la valeur souhaitée. Et ce n’est pas tout, si la valeur a été modifiée, il faudra trouver la bonne valeur parmi une liste (basé sur la date par exemple).

Une valeur est donc un objet complexe, que je défini comme polymorphique. Celui qui fourni l’information finale doit déduire et transmettre un résultat utilisable. Ce qui concerne également l’encodage et dans mon cas actuel : le convertisseur (la moulinette).

On peut également ajouter le fait que certaines valeurs ne sont pas disponible dans l’ontologie telle quelle mais doivent être stockées en dehors pour des raisons de taille, format, nature, … Ce qui demande une interprétation additionnelle.

Encodage et présentation

Encodage

Afin d’illustrer les théories en vigueur actuellement, voici un cheminement pour une information, actuellement je me base sur les types de groupe folklorique.

Un groupe folklorique est une représentation simpliste du type de groupe pour les qualifier. Ceux-ci sont représentés par un nom et des initiales, par exemple « Comité de Baptême » aura les initiales « C.B. », agrémenté d’un id en base de donnée vous avez ainsi la structure à porter vers l’ontologie.

La première chose que notre ontologie a besoin avant de pouvoir encoder les données est de connaitre la structure, nous allons donc encoder un modèle de ce « type de groupe », je vous passe les dépendances techniques nécessaires. Ce modèle est donc une entité ayant des prédicats spécifiques pour représenter les initiales et le nom du type de groupe, l’id, quant à lui, ne sera pas porté et fera place à un nouvel identifiant propre à la nouvelle structure technique, cependant il sera conservé pendant le traitement de conversion total dans un store afin de faire la correspondance entre ancien et nouveau système.

On a donc un modèle, qui est une entité composée de prédicats structurels (la trinité) nom/description/type, nous indiquant qu’il s’agit du modèle type de groupe avec une description similaire à son nom (aspect technique auto généré) et un type qui sera « modèle », car si on veut encoder des entités du type « type de groupe », cette même description est un modèle en soit. À cela s’ajoute les prédicats propre au modèle : initiales et nom (le nom repris en base de l’entité (trinité) et le nom du type de groupe sont 2 prédicats distinct (actuellement car la structure pourrait être amenée à évoluer)).

Tant qu’on est dans la préparation technique, et maintenant que le modèle existe, nous pouvons penser à la présentation des instances du type « type de groupe ». Là encore nous allons créer une entité avec sa trinité nom/description/type, nous indiquant qu’il est un présentateur pour un type de groupe, et à cela nous allons lui indiquer les prédicats que l’on souhaite conserver lors d’échange de données (pensez à ce que l’on souhaite partager ou afficher). Ces prédicats souhaités vont se retrouvé dans notre cas dans le prédicat d’inclusion, c’est à dire que l’on précise les 2 prédicats que l’on souhaite conserver par rapport au modèle, ici : initiales et nom du type de groupe. Il est à noter que ces prédicats inclus sont ordonnés

Il faut faire connaitre au modèle « type de groupe » qu’il y a un présentateur consacré et donc nous allons ajouter un prédicat au modèle de type présentateur, référençant le sujet du présentateur. En gros, on les lie en partant du modèle.

Maintenant que nous avons cette partie technique nous pouvons convertir nos données originales vers l’ontologie une à une. En très résumé :

  • on chope un type de groupe,
  • on reprend ses données,
  • on crée une nouvelle entité typé du modèle « type de groupe » que l’on va nommer selon les données reprises, avec une description similaire,
  • Pour chaque champs spécifique, on l’ajoute à cette nouvelle entité,
  • On sauve et c’est fini, on passe au suivant

Jusque là c’est assez simple, nous voilà avec un modèle, un présentateur et des instances de données représentant des types de groupe.

Présentation

Maintenant on nous demande d’envoyer ces données vers le front (le site qui va afficher les données à l’écran). Et non, ce n’est pas simplement d’envoyer les instances créées ^^.

Dans mon cas, on demande d’envoyer toutes les instances d’un modèle, dans ce cas-ci, les types de groupe. Pour ce faire il faut 2 choses : les données et leur structure, mais attention, uniquement ce que l’on veut afficher.

Rappelez-vous que ne pas tout envoyer allège la communication et protège les données qui ne devraient pas transiter.

Il n’y a pas vraiment d’ordre ici, c’est exécuté en 2 appels distincts, du coup je vais vous parler de la structure puis des données.

Structure

On nous demande la structure filtrée pour une entité, du coup d’abord on va faire des vérifications d’usages : est-ce que l’entité ciblée existe et est-ce qu’elle a un présentateur sinon son père ou son père avant lui jusqu’à remonter tout en haut.

Dans notre cas on a un présentateur donc il faut le résoudre :

  • prendre la définition du présentateur (on part ici du principe qu’il n’en a qu’un, je vous vois venir à raison).
  • est-ce qu’il y a des prédicats à inclure ? Si « non » alors on va chercher le modèle et on prend tout, et si « oui » alors on a notre liste de départ directement.
  • est-ce qu’il y a des prédicats à exclure ? On aurait pu prendre tout du modèle et exclure la trinité, dans notre cas il n’y a rien à exclure.
  • renvoyer la liste finale

Ça a l’air simple hein oui ?

Notez que les prédicats peuvent avoir des indications de type de donnée (texte, date, valeur financière, e-mail), on peut agrémenter la structure de ces infos afin d’améliorer l’affichage (ce qui n’est pas encore le cas mais prévu).

Données

On va demander au système de nous donner toutes les entités du type du modèle cherché. Vu notre structure de données on se limite au prédicat type pour n’avoir qu’un seul résultat par entité et permettre de le filtrer directement (aspect technique pratique).

On pourrait dire qu’il suffit alors de boucler sur chaque résultat, chercher les données de chaque et tout envoyer. Et c’est vrai que ça fonctionne car le front génère un tableau sur base de la structure reçues et seul les champs autorisés sont affichés si existant. Sauf que, envoyer tout n’est pas la meilleure chose à faire; et que vous oubliez la notion de valeur de ces champs.

Les données stockées peuvent être une référence vers une autre entité (prédicat ou valeur) ou être la valeur finale. Ce « ou » est le problème à résoudre avant envoie. Le front s’en moque, il veut une donnée exploitable (et il a raison). Il nous faudra déterminer la nature de la donnée que l’on a en objet et si ça a l’air d’être une référence à une autre entité alors c’est parti pour la grosse mécanique.

Il nous faudra chercher si cette référence existe, de quelle nature elle est pour l’interpréter, car on ne gère pas un prédicat comme on gère une valeur par exemple. Puis si on peut fournir assez d’infos pour que le front puisse mieux se démerder c’est encore mieux (exemple d’avoir un label sans sa référence nous empêche de construire un lien vers elle).

Ici je résume fort, sinon je vais devoir vous expliquer les dizaines de lignes de codes pour y parvenir ^^. Rappelez-vous juste que chaque question à l’ontologie est une requête ^^, et dans le cas d’une résolution de valeur il y en aura jusqu’à 2 par prédicat à afficher, bref ça nous donne un : n · (2 + [0,2]). Vivement améliorer ça ahah.

Nous ne sommes pas encore dans une solution optimisée, c’est encore de la recherche et développement, comme souvent dans mes articles et surtout sur le sujet de cette ontologie.

Supplément front

Évidemment les données ne s’affichent pas par magie, wooop, mais bien par un traitement. On va déjà passer la structure json actuellement nécessaire mais en passe de changer pour intégrer l’ordre dont on parlait plus haut concernant la structure.

Quand on souhaite afficher notre donnée, il faut également savoir de quelle nature elle est, car si c’est une référence on peut créer un lien et permettre d’aller vers cette entité ciblée, promenons-nous ! Et si c’est du texte l’afficher et, plus tard, tenir compte du format selon le prédicat.

Pour créer le lien j’ai mis à jour un code de 2022 concernant les composants de cellule en Angular, mis à jour à la sauce Signal, c’est top !

Mot de la fin

Et voilà c’est « déjà » fini ! :p Merci d’avoir joué les canards en plastique pour cette « rédaction documentaire d’un instant T en plein développement prise de tête pas terminé ».

De la représentation d’un SPO

Voulant écrire un nouvel article au sujet de l’ontologie et des valeurs, j’ai souhaité mieux transposer mes propos en les illustrant. De prime à bord je partais sur un graph, tel que :

SPO d’un livre ayant pour Titre « Titre du livre »

Où le Sujet S représente un livre, ayant un Prédicat P « Titre » et ayant pour Objet O une valeur texte « Titre du livre ».

Mais ceci contient un souci de représentation, bien que l’on comprenne aisément la relation d’un Sujet et de l’Objet via un Prédicat, cela nous empêche de comprendre le Prédicat lui-même. Car oui le Prédicat peut être développé lui aussi.

Vue du Prédicat

Avant ça, poussons le bouchon plus loin en transformant l’Objet O en un nouveau S :

SPO d’un livre dont la valeur du Titre contient des métadonnées

L’Objet valeur devient un Sujet à son tour qui a des Prédicats eux-mêmes pointant vers des valeurs finies (primitives) ou des Sujets. Mais on a cette intuition que le Prédicat n’est qu’un lien, un mot sur une liaison, alors qu’ils sont bien plus que ça.

Illustration de la complexité des liaisons des Prédicats

Le Prédicat est à la fois l’attribut liant le Sujet à l’Objet mais également un Sujet à part entière ayant ses propres liaisons vers des Objets au travers de Prédicats, parfois les mêmes, et ainsi de suite. Et encore ici nous n’avons pas illustré l’usage multiple, ça deviendrait illisible. Imaginez plusieurs « Livre » passant par le Prédicat « Prédicat#Titre » et allant vers un Objet distinct chacun.

Illustration de l’usage multiple de la référence d’un Prédicat pour plusieurs Sujets et Objets

Vous en conviendrez c’est un beau bordel. Et encore j’ai mis des couleurs pour votre lecture. Car sinon on pourrait dire qu’un livre a plusieurs Titre, ce qui est tout à fait admissible par le modèle SPO.

Proposition de représentation

Cette représentation n’est donc pas idéale, mais quid alors ? Je vous propose une transformation en objet et une vue en tables.

Comme vous pouvez le voir j’ai gardé les codes couleur des exemples précédents, à savoir le noir pour les Sujets et le bleu pour les Objet à valeur de type primitive. Considérez « Type », « Titre » et « Type#Livre » tel que « Livre », à savoir un Sujet, je n’ai pas illustré la table dessous chacun pour éviter la surcharge graphique.

On a donc le Sujet « Livre » ayant un Prédicat « Type » d’Objet « Type#Livre », qui donc est lui-même un Sujet, et un Prédicat « Titre » d’Objet de valeur texte « Titre du livre ». Ça c’est dans le cas simple illustré en début d’article. J’ai juste ajouté le Prédicat « Type » pour illustrer 2 types d’Objet.

Si maintenant nous avons des métadonnées sur la valeur « Titre du livre », cet Objet devient un Sujet, c’est-à-dire que l’on va encapsuler dans un nouveau Sujet, la valeur initiale et tout autre attribut venant des métadonnées de cette valeur. Dans notre exemple, j’ajoute l’ordre et la date de création. Et évidemment comme nous créons un nouveau sujet, nous le typons, et c’est là que vous voyez la réutilisation du Prédicat « Type » de manière distincte.

Autre point d’intérêt, le Sujet « Type#Contenu », qui est, à la fois valeur d’un Objet pour le Prédicat « Type », et à la fois Prédicat, pour la valeur « Titre du livre ». Ce qui est tout à fait correcte et illustre parfaitement ce dont nous parlions plus tôt. Ici nous pouvons « voir », l’implication des Sujets, leur connexions et les valeurs primitives associées.

Mais quant est-il dans le cas où nous avons plusieurs valeurs pour un même Prédicat ? Une solution, illustrée ci-avant, serait de partir du Prédicat et d’aller vers nos 2 Sujets en Objet. Et on peut débattre de la représentation, à savoir tel que représenté ci-avant, 1 devient N. Ou comme ci-dessous, ou nous créons 3 associations.

Je pense que les 2 devraient se combiner, la première permet une économie de représentation tout en restant compréhensible- et la seconde permet de bien illustrer les valeurs et leur Prédicat. Même si on pourrait simplifier peut-être tel que :

Le tout étant de rester lisible à la première lecture et sans ambiguïté. Je pense du coup que l’objectif est atteint et que l’on va pouvoir passer aux articles suivants avec un système de représentation plus accessible.

Sujet, Prédicat, Object : valeurs, audit et historisation

Cet article est une réflexion faisant suite à l’article concernant l’explication de mon approche ontologique et de la structure des données du projet Folkopedia avec un retour d’expériences.

Initialement nous avons notre ligne ontologique telle que :

S, P, O, V, Qui, Quand, Visibilité, Ordre

Avec pour lecture :

  • Sujet
  • Prédicat
  • Objet au sens pointeur vers un sujet
  • Valeur primitive de l’objet (c’est valeur ou objet mais pas les 2 en même temps)
  • Qui a créé ou éditer la ligne en dernier
  • Quand est-ce que ça été créé ou édité en dernier
  • Visibilité au sens de qui peut consulter cette valeur
  • Ordre au sens de l’ordonnancement des prédicats et valeurs

Les problèmes rencontrés

  1. D’abord un truc gênant concernant l’ordre, celui-ci n’est pas toujours nécessaire et c’est donc une colonne qui n’a pas toujours de sens.
  2. Dans le cas où un prédicat a plusieurs valeurs, celle-ci ne sont pas ordonnées, excepté par l’ordre d’insertion.
  3. La valeur elle-même peut avoir une historisation comme discuté ce qui demande un Sujet, du coup quid de la valeur primitive ?
  4. Comment être SPO sans avoir 2 colonnes pour respecter les théories SGBD ? Comment gérer les 2 en 1 et différencier au bon moment ?
  5. L’audit Qui et Quand n’est pas historisé, ce qui est un manque à l’objectif, pareil pour Visibilité et Ordre.

Solutions ?

Déjà reprenons le point n° 2. Elles peuvent être ordonnée si on utilise la colonne Ordre. Là où elle ne le sont pas, c’est dans le système actuel, où le fait d’avoir un objet ayant pour clef le prédicat et les valeurs simplifiées en tableau perdent cette notion. De plus la requête actuelle ne l’extrait pas.

Ceci mis à part, le constat est que les colonnes Qui, Quand, Visibilité et Ordre ne sont pas correcte, supprimons les et regardons comment respecter l’énoncée de départ.

S, P, O, V

Si on projette un exemple, nous aurons :

SujetPrédicatObjetValeur
#entity1SurnomnullKillan

Là on a une Valeur primitive pour un Prédicat d’un Sujet. Mais si on veut rajouter les 4 colonnes retirées, en suivant le modèle ontologique, nous allons devoir faire ainsi :

SujetPrédicatObjetValeur
#entity1Surnom#entity2null
#entity2AuditQui#entity1null
#entity2AuditQuandnull2025-02-13 21:08…
#entity2Visibilité#entity39null
#entity2Ordrenull1

Visibilité pourrait même être défini au niveau du Prédicat, par défaut, et supplanté par l’utilisateur potentiellement. La valeur disparait au profit d’une nouvelle entité contenant les informations relatives, mais la valeur a disparu, on la rajoute :

SujetPrédicatObjetValeur
#entity2ValeurnullKillan

Dès lors nous avons tout à nouveau, on est complet et il n’y a plus qu’à faire une requête pour chaque prédicat, simple… POUR CHAQUE PRÉDICAT ! Déjà que la console du système n’est pas triste avec le peu qu’on a fait jusque là, mais si en plus on double… Et en plus il faudra potentiellement trier les lignes reçues pour les identifier d’une certaine manière par les prédicats.

Réflexions sur la valeur

Si on observe le résultat, dans ce cas-ci, Objet est utilisé 50% du temps et Valeur 50%, équilibré en soit, mais plus largement ça sera surtout la colonne Objet qui sera attribuée. La valeur primitive est largement moins sollicitée.

De plus, si nous avons comme contenu l’historique complet d’un groupe folklorique, qui plus est formatté par exemple, nous allons avoir une quantité folle de données dans ce champs de manière anecdotique et là je me dis qu’on passe à côté de quelque chose.

On est d’accord qu’on n’enregistre pas un document ou une image dans ce champs, du coup, les contenus potentiellement massif, ou identifiés comme tels, ne devraient pas y être non plus. Cela n’a pas d’intérêt ontologique ou structurel.

Nous avions imaginé qu’une image serait parsemée de légendes, de tags, et de commentaires, ce qui à la fois contient des informations larges et d’autres courtes. Le tout pouvant faire l’objet d’une recherche. On peut partir dans tous les sens alors car il faut indexer du contenu pour chercher dedans. Pour ce faire, ce n’est pas à l’ontologie de s’en occuper, elle ne garanti que le lien entre les informations et la structure générale par ses définitions.

On peut imaginer un système annexe comme une table de contenus, ou un système comme un Elasticsearch. Le système de recherche ferait une demande à ces systèmes qui permettrait de relier un (ou plusieurs) Sujet(s) de l’ontologie. Ça semble cohérent.

Si on extrait les contenus large comme des documents et des images, il va falloir penser à une technique pour les relier dans l’ontologie. Comment écrire que la Valeur ou l’Objet fait référence à une structure externe ?

subject UUID not null,
predicate UUID not null,
object UUID,
o_value TEXT,

Petit extrait de notre table ontology pour vous montrer que les colonnes sont fortement typées. On ne peut pas indiquer n’importe quoi dans object. Et o_value, sur base de ce que l’on vient de dire, devrait devenir un varchar dont la longueur X est encore à définir, en soit si inférieur à X alors valeur courte et si supérieur à X alors contenu large externalisé.

Soit on garde la théorie SGBD avec notre clé secondaire (FK) pointant vers une clé primaire (PK), en dur dans le marbre bien respectueux et on garde une colonne Valeur en tant que varchar. Soit on transforme les 2 en une seule, de type JSON ou varchar. L’avantage du varchar est l’indexation pour définir un index et/ou une PK globale, permettant de valider l’unicité du Triplet. Avantages et inconvénients de chaque approche.

On peut également partir sur le principe de diviser la table en 2-3 pour séparer les colonne du fait de l’exclusivité mutuelle. Une table SPO et une table SPV, voire une table SP de référence centrale. C’est le code qui doit alors rassembler les morceaux. (Clin d’œil à Julian pour le rappel)

Là où ça se corse, quelque soit la solution, c’est l’identification extérieure. Comment interpréter Valeur ? On pourrait préfixer le contenu, tel que :

  • doc:refdoc#1
  • img:refimg#1
  • txt:reftxtlarge#1
  • v:Killan

Le symbole « deux points » ( : ) nous permettant, telle une sérialisation, de faire la part des choses, sans empêcher l’usage dudit caractère dans sa partie droite, à vérifier bien sur ou a encapsuler dans des guillemets (  »  » ). Attention tout de même de ne pas devenir une usine pour peu d’intérêts. Les images, textes et documents font partie du cœur de l’objectif, donc jusque là pas de soucis, on en prend soin.

On peut imaginer que la partie ref (refdoc#1, refimg#1, reftxtlarge#1) pointe sur une table autre que ontology avec comme valeur un chemin vers le fichier avec peut-être des propriétés système de ce fichier (nom, taille, format) dont l’intérêt ne sera pas ontologique et plutôt commun au système de référence.

Dans le cas d’une valeur primitive ( v: ou v: » … « ), là on interprète la valeur directement. J’en rajoute une couche avec la traduction ? Doit-on traduire la valeur en elle-même ou est-ce que le prédicat sera démultiplier avec un attribut supplémentaire pour contenir cette différenciation, ça demandera pas mal de requêtes, mais ça fonctionnerait.

SujetPrédicatObjetValeur
#entity3Titre#entity4null
#entity4AuditQui#entity1null
#entity4AuditQuandnullv: »2025-02-13 21:45:27 … »
#entity4Visibilité#entity39null
#entity4Ordrenullv: »1″
#entity4Valeurnullv: »Un titre un peu long qi pourrait poser un certain soucis quelque part »
#entity4Langnullv: »fr_be »
#entity3Titre#entity5null
#entity5
#entity5Valeurnullv: »A somewhat long title which could cause some problems somewhere »
#entity5Langnullv: »en_en »

Mais philosophiquement, n’est pas la même entité qui est traduite ? Serait-ce alors plusieurs clefs Valeur avec un code de langue du texte ?

SujetPrédicatObjetValeur
#entity4
#entity4Valeurnullv:fr_fr: »Un titre un peu long qi pourrait poser un certain soucis quelque part »
#entity4Valeurnullv:en_en: »A somewhat long title which could cause some problems somewhere »

Le principe ontologique est respecté, un prédicat et plusieurs valeurs, mais notre colonne valeur demande toute une interprétation. Ou alors, on pousse le bouchon encore plus loin et quelque soit la valeur devient un Sujet.

SujetPrédicatObjetValeur
#entity4
#entity4Valeur#entity7null
#entity7Type#entity46null
#entity7ContenunullUn titre un peu long qi pourrait poser un certain soucis quelque part
#entity7Langnullfr_fr
#entity4Valeur#entity8null
#entity8Type#entity46null
#entity8ContenunullA somewhat long title which could cause some problems somewhere
#entity8Langnullen_en

Et là c’est top côté ontologie, il nous faut :

  • 1 requête pour avoir la référence du Sujet
  • 1 requête pour avoir tous les prédicats du Sujet
  • 1 requête par Prédicat pour déterminer sa nature (peut-être à conditionner selon que la colonne Objet ou Valeur est utilisée)
  • 1 requête par Prédicat ayant une valeur sous forme de Sujet

À savoir un minimum de 6 requêtes, au lieu de 1 en début d’article (1 pour trouver le Sujet puis 1 pour avoir ses Prédicats, ou les 2 d’un coup si on a déjà la première info).

D’où l’importance des choix avant même de penser aux optimisations techniques.

Historisation

Nous ne sommes pas revenu sur l’historisation et là il y a 2 possibilités. Soit on part de la valeur que l’on encapsule virtuellement par répétition du prédicat, il faudra trouver la valeur la plus récente :

SujetPrédicatObjetValeur
#entity3Titre#entity4null
#entity4AuditQuandnull/date1/
#entity3Titre#entity5null
#entity5AuditQuandnull/date2/
Solution de plusieurs valeurs pour l’historisation

Soit par ligne individuelle, ce qui nous demandera de faire un travail différenciel pour recomposer le cheminement de l’information dans le temps, mais au final on en revient à la structure précédent Qui, Quand, Valeur. On pourrait imaginer un chainage, modifier la valeur entraine un nouveau bloc Valeur qui chaine en s’intercalant, comme en C avec les listes chaînée.

SujetPrédicatObjetValeur
#entity3Titre#entity5null
#entity5HistPrécédant#entity4null
#entity4
Chaînage de l’historique

La valeur

Revenons maintenant sur la valeur (Objet, Valeur). Ils sont mutuellement exclusif et comme dit plus tôt, il y a plusieurs solutions.

  • Soit diviser la table ontology en 2-3, ce qui, pour moi, ne correspond pas à l’idée de l’ontologie.
  • Soit fusionner la colonne Objet et Valeur en une seul de type varchar dont le contenu peut être déterminé comme vu précédemment.

Si on considère la seconde option, il faut parler du Prédicat qui nous donne déjà des informations de Type, donc en soit le type de valeur n’est à faire que dans le cadre d’un Prédicat Valeur. J’y vois déjà une arborescence de Types de Valeurs et de Prédicats relatifs. Le but est de toujours savoir comment interpréter la valeur.

Transposer les solutions

Si on essaye de tout regrouper pour voir si ça fonctionne virtuellement, prenons l’exemple de mon surnom.

SujetPrédicatObjet (valeur)Explication
#entity1Surnom#entity8
#entity8Type#entity3Entité de type Valeur
#entity8Qui#entity1
#entity8Quand/date1/Quand est de type date
#entity8Visibilité#entity4
#entity8Ordre1Ordre est de type nombre
#entity8ValeurContenu#entity7Entité de type contenu/valeur
#entity7Type#entity6
#entity7Langfr_be
#entity7ContenuKillan
#entity8HistPrec#entity2
#entity2Type#entity3Ancienne capsule pour la valeur
#entity2Qui#entity1
#entity2Quand/date2/
#entity2Visibilité#entity4
#entity2Ordre1
#entity2ValeurContenu#entity5
#entity5Type#entity6Ancienne valeur
#entity5Langfr_fr
#entity5ContenuKilan

Traduisons tout cela :

  • On a un Sujet me représentant #entity1 avec un Prédicat Surnom qui a une valeur #entity8,
  • #entity8 est pourvu des Prédicats permettant d’auditer la valeur et d’obtenir la valeur #entity7,
  • #entity7 est un Sujet ayant la valeur finale pour une langue initiale,
  • #entity8 à une valeur précédente en #entity2 pour corriger une typo (ça aurait pu être un changement de visibilité ou d’ordre),
  • #entity2 est pourvu des Prédicats permettant d’auditer la valeur et d’obtenir la valeur #entity5 également, et ici elle n’a pas de valeur précédente,

Attention aux noms des Types : Surnom, Valeur, Contenu et ContenuValeur; il va falloir y prêter attention pour ne pas se perdre en chemin. Peut-être est-ce toute une chaîne typée héritée de types respectifs plus macro comme les modèles.

En gros on a fait x10 à notre ligne initiale, et on corrige nos soucis d’historisation, de stockage de valeur et de typage. C’est le programme qui va se perdre en requêtes et recomposition d’un information intelligible pour traitement. Dans un sens comme dans l’autre. :/

2 requêtes pour la valeur d’un Prédicat qui a déjà demandé 1-2 requête(s). Et l’historique, ainsi que l’audit, à la demande dans des requêtes annexes par 2n.

Optimisation

Comme vous l’aurez compris ça va coûter cher en requêtes et temps de processus. On a une table déjà énorme en prévision, si en plus on a l’historisation aussi verticale ça va devenir longuet. Vient une idée (merci Adrien), de sortir la partie historique de la table ontology, de ne garder que l’instant courant dans celle-ci et de sortir le reste en dehors, vu que son taux de consultation sera bien bien moindre. On aurait donc une table historique contenant une structure légère afin de pointer le Sujet adéquat dans l’ontologie, voire même un Prédicat, à voir, et à stocker sa valeur précédente. En gros une capture de l’objet et descendants directement liés et stocker sous format JSON.

Dans l’exemple précédent on aurait alors #entity2 et #entity5 de sorti dans ce format JSON et stocké en historique, pointant #entity1:Surnom. Le reste serait une ordonnancement par date par exemple.

Validation de contenu

De part la volonté communautaire du projet et d’autogestion/autorégulation par la communauté, une valeur doit être approuvée, toute ou partiellement selon le type d’information. Cette nouvelle structure nous permet d’ajouter des Prédicats de contrôles.

SujetPrédicatObjet (valeur)
#entity17Validation#entity1

Le Prédicat pouvant être multiple, on peut avoir plusieurs validateur et la validation peut être à son tour un objet déterminant un commentaire et une valeur d’approbation et date. Cela peut être un refus commenté par exemple. C’est au système ensuite de considérer ou non la valeur. Dans le cas d’un correctif refusé, le système doit aller chercher la valeur initiale si approuvée. Je vous laisse imaginer le bazar futur.

Conclusion

Nous voilà revenu à notre structure la plus pure et théorique :

S, P, O

Dont O est un V encapsulé et dont il faudra définir l’entité avec soin.

subject UUID not null,
predicate UUID not null,
object VARCHAR(X) not null,

Adieu facilité ! Bonjour complexité et flexibilité…

Il ne me reste plus qu’à réécrire la moulinette de conversion, créer les nouvelles structures d’entités et créer les outils nécessaires pour gérer ça plus facilement, et évidemment revoir le lien front OntologyMyAdmin en profondeur du coup.

Rien que ça… ^^

Folk·o·pedia – une histoire de techniques au fil du temps

Si on regarde Folk·o·pedia, même si Comitards date de 2006, on pourrait penser que le sujet ne date que d’il y a 7 ans, quand j’ai parlé de Comitards v3. Et là encore, vous me direz que c’est déjà pas mal. Mais que nenni, il y a une histoire plus ancienne qui prend forme aujourd’hui, dont je ne me suis rendu compte qu’il y a peu. Du coup, c’est parti pour un petit partage.

Folkipedia, juillet 2007 avec le FJDB (Fonds Jean-Denys Boussart), sans suite.
Reprise du projet en personnel, juin 2008.

Nous sommes d’accord que Folk·o·pedia repose sur une ontologie, une base de connaissances, structurée en triplet (Sujet, Prédicat, Objet), ça ok, mais saviez vous que tout début 2000, un de mes sites, MiZaMis, utilisait déjà une base de données structurée différemment ? Suivant le principe de la base de registre de Windows, en un peu plus simple, chaque utilisateur avait sa propre table, organisée dans l’équivalent du prédicat – valeur (objet). Bien sur, à l’époque, cela a valu son lot de railleries, mais ce système a montré ses avantages et inconvénients et a pu durer toute la vie du site.

Structure de la table d’un utilisateur et exemple de contenu.
MiZaMis, division de MesDocuments, successeur de LaToile, ~2005-2008.

Plus tard, suite à mon second graduat en Techniques Infographiques (2008), j’ai proposé un mémoire sur « Recherche, étude et mise en œuvre d’un générateur de formulaire extensible, configurable et exploitable dans divers contextes« , qui, en résumé, avait pour but de générer des formulaires sur base d’une description, avec contrôles et différentes sorties générées possibles (web, PDF, rtf, Word, …), évidemment c’est la version web avec JQuery qui était le plus poussé, même si générer du PDF en code natif était un beau défi en soi.

Mais, n’est-ce pas également le but des modèles ontologique que renferme Folk·o·pedia ? Une description d’entité dont les prédicats sont eux-mêmes décrit et peuvent indiquer des contrôles ? En effet, le but d’un modèle est de pouvoir proposer un formulaire généré via la description de son modèle ! Évidemment on ne vas pas réutiliser la solution du mémoire ^^ elle est légèrement dépassée, mais l’idée, le concept, lui, reste valable.

Dump YML des données générées par l’éditeur.
Résultat généré sur base des données précédente en XSL et d’un transformateur XSLT.
Le même résultat avec une couche de CSS et de JS.

Dans une autre mesure, il y a eu aussi le projet FGPI (Folk Groups and People Involved vocabulary) en 2015, dont le but était de créer un ensemble de règles descriptives afin d’ajouter au site Comitards.eu une couche metadata suivant certains principes, mais, malheureusement, cela s’est avéré infructueux. Cela étant dit, une ontologie, donne exactement une suite à ce projet, décrire des objets et les liens entre eux, des gens et des groupes folkloriques, ce qu’ils ont fait, porté et vécu.

Et enfin, durant mon mémoire de 2022, dont le sujet, en français, était : « Comprendre les exigences d’utilisation des citoyens concernant les fonctionnalités de visualisation de données libres sur les portails du gouvernement« , on traite de la visualisation de données dont on ignore comment les représenter de manière lisible par le premier venu. Folk·o·pedia aura également ce soucis, l’ontologie ne donne pas ces informations en premier plan, il faut prévoir un tel système, le fournir et le traduire, et c’est génial car c’est encore tout un défi ! On peut partir sur un dictionnaire des prédicats par exemple, d’ailleurs celui-ci est déjà nécessaire en l’état du développement courant.

Affichage des données sous format d'un graphique à barres et d'une tarte.

Vous avez là trois histoires qui se passent sur ~24 ans. Trois bout d’un problème qui se déroule en ce moment même. Je ne l’ai même pas vu venir, mais quelle surprise lors du constat ! D’où ce petit partage pour vous en faire part. 😉

Passer dans les backups et archives, pour vous trouver ces contenus, ravivent de beaux souvenirs. C’est toute une aventure, toute une partie de ma vie, de développeur web et de projets perso. Il y a tant à dire et à montrer pour saisir ce que cela peut représenter à mes yeux :).

Et en avant première, une partie des coulisses actuelle, l’état sans censure du développement de Folk·o·pedia, son outil de contrôle : l’explorateur d’entités. À l’image d’un autre outils qui m’a aidé toutes ces années : PHPMyAdmin.

OntologyMyAdmin WIP janvier 2025