#Débutant

0 Abonnés · 31 Publications

La balise Débutant regroupe des articles et des questions destinés à ceux qui débutent avec la plateforme de données InterSystems.

Article Guillaume Rongier · Oct 15, 2025 9m read

Vous êtes familier avec les bases de données SQL, mais vous ne connaissez pas IRIS ? Alors lisez la suite...

Il y a environ un an, j'ai rejoint InterSystems, et c'est ainsi que j'ai découvert IRIS.  J'utilise des bases de données depuis plus de 40 ans, la plupart du temps pour des fournisseurs de bases de données, et je pensais qu'IRIS serait similaire aux autres bases de données connues.  Cependant, j'ai été surpris de constater qu'IRIS est très différente par rapport aux autres bases de données, et souvent bien meilleure.  Avec mon premier article dans la communauté Dev, je vais présenter IRIS de manière générale aux personnes qui connaissent déjà d'autres bases de données telles qu'Oracle, SQL Server, Snowflake, PostgeSQL, etc.   J'espère vous rendre les choses plus claires et plus simples et vous faire gagner du temps pour vous lancer.

Tout d'abord, IRIS prend en charge les commandes et la syntaxe SQL de la norme ANSI. Il dispose de tables, de colonnes, de types de données, de procédures stockées, de fonctions...   bref, tout ce qui concerne les relations.  Et vous pouvez utiliser ODBC, JDBC, DBeaver ou tout autre navigateur de base de données que vous préférez.  Donc, oui, la plupart des connaissances et des opérations que vous maîtrisez avec d'autres bases de données fonctionneront très bien avec IRIS.  Youpi!  

Mais qu'en est-il de ces différences que j'ai mentionnées?  Bien, attachez vos ceintures:

Multi-Model: IRIS est une base de données relationnelle, mais c'est aussi une base de données orientée objet, un magasin de documents, et elle prend en charge les vecteurs, les cubes/MDX, et... vous comprenez où je veux en venir.  Ce qui est incroyable, c'est que vous pouvez profiter de tous ces modèles... dans la même instruction SQL!  Et bien souvent, les données peuvent être stockées sous plusieurs de ces structures de données — sans avoir à les sauvegarder à deux reprises — ni à utiliser plusieurs types de bases de données!  Lorsque vous accédez à des données identiques comme s'il s'agissait de modèles différents, InterSystems parle de CDP (Common Data Plane, ou plan de données commun).  C'est pour le moins rare, voire unique, dans le secteur des bases de données.  Personne ne s'intéressait vraiment au CDP jusqu'à ce que la révolution de l'IA rende tout à coup indispensable la prise en charge du multimodèle. Il ne s'agit pas d'une fonctionnalité que d'autres bases de données sont susceptibles d'implémenter, car elle est intégrée au cœur même du noyau.  IRIS facilite l'utilisation des modèles multiples ainsi que des technologies NoSQL et NewSQL pour les utilisateurs SQL:

Pour la base de données Object, vous extrayez une clé-valeur de l'arborescence JSON, qui correspond simplement à la valeur d'une table classique. 

-- exemple de requête dans une base de données ObjectSELECT JSON_OBJECT('product':Product,'sizes':PopularSizes) FROM Sample.Clothing

-- Cela renvoie une liste de paires clé-valeur. Si une paire manque, -- IRIS crée par défaut une paire avec une valeur nulle.

En ce qui concerne Vector, considérez-le simplement comme un autre type de données, mais avec certaines fonctions spéciales qui ne fonctionnent qu'avec le type de données en question 

-- exemple de création d'une table avec une colonne vectorielleCREATETABLE Sample.CustEventV1 (
  CustID INTEGER,
  EventDt DATE,
  Vtest VECTOR(integer,4),
  EventValue NUMERIC(12,2),  
  EventCD VARCHAR(8)) 

-- Vous pouvez utiliser des fonctions telles que VECTOR_DOT_PRODUCT ou VECTOR_COSINE sur Vtest

Taxonomie:  les différents fournisseurs de bases de données n'utilisent pas tels termes comme base de données, schéma, déploiement, instance, etc. exactement de la même manière. 

  • Instance: lorsque vous installez le logiciel de base de données, généralement appelé 'instance' par les éditeurs de bases de données. J'entends parfois ce terme chez InterSystems, mais plus souvent, j'entends le terme 'déploiement'.  Cela s'explique probablement par le fait que le terme 'instance' est déjà utilisé dans le monde orienté objet.  Quel que soit le terme utilisé, la hiérarchie pour les autres bases de données est généralement la suivante:
    • instance/déploiement
      • base de deonnées
        • schéma
          • tables, vues, etc.

            .. ou bien:

  • instance/déploiement (il *s'agit* de la base de données)
    • schéma
      • tables, vues, etc.

            .. mais IRIS est un peu différent dans la mesure où il comporte une couche supplémentaire appelée 'espace de nom':

  • instance/déploiement
    • espace de nom
      • base de données
        • schéma
          • tables, viues, etc.

Un espace de noms est une entité logique qui contient des bases de données. Cependant, plusieurs espaces de noms peuvent contenir la même base de données, il ne s'agit donc peut-être pas d'une hiérarchie.  Il est principalement utilisé pour le contrôle d'accès. Et il peut contenir des bases de données provenant d'autres instances/déploiements!

HA: La haute disponibilité (High Availability) est obtenue grâce à une technique appelée mise en miroir ( mirroring ).  Il s'agit d'un type de réplication où l'intégralité de la base de données est répliquée, y compris le code.  Vous pensez peut-être que vous ne souhaitez pas répliquer l'intégralité de la base de données.  Mais grâce aux espaces de noms, vous pouvez considérer une base de données comme une sorte de schéma et diviser vos données de manière à ce que celles que vous souhaitez mettre en miroir et celles que vous ne souhaitez pas mettre en miroir se trouvent dans des bases de données distinctes. 

Stockage du code: Oui, vous avez parfaitement compris: lorsque vous mettez une base de données en miroir, le code est également transféré!  Il s'agit d'une fonctionnalité très récente pour certaines bases de données à la mode, mais IRIS l'offre depuis toujours. Vous pouvez stocker à la fois le code et les données dans la même base de données, mais le plus souvent, les utilisateurs préfèrent les séparer.

ECP: Bien; c'est le protocole Enterprise Cache Protocol qui rend IRIS vraiment intéressant.  Je ne savais même pas que cela était possible, mais j'ai récemment découvert qu'il existe quelques bases de données NoSQL peu connues qui le permettent.  Avec le protocole ECP vous pouvez configurer le système de manière à ce que différents déploiements puissent partager leurs caches!  Oui, je veux bien dire leurs caches memory réels.. et non pas le partage des données des tables. Pour ce faire, le cache d'un déploiement est automatiquement synchronisé avec celui d'un autre déploiement.  C'est ce qu'on appelle être synchronisé!  C'est très facile à configurer, même si cela doit être compliqué en coulisses. Il s'agit d'un tout autre type de mise à l'échelle horizontale qui peut rendre les applications ultra-rapides.

Translytique: Ce terme, translytique, est utilisé pour décrire une base de données qui est à la fois OLTP et OLAP. Il peut également être appelé HTAP ou HOAP. Parfois, on emploie le terme hybride mais ce terme est trop utilisé dans le monde technologique, je vais donc m'en tenir au terme commençant par T.  Au début, toutes les bases de données étaient translytiques.  Mais avec l'avènement des structures en colonnes et d'autres structures, ainsi que de nouveaux types de stockage (par exemple le stockage en blocs par opposition au stockage en blobs) elles ont été séparées en OLTP et OLAP. Aujourd'hui, les fournisseurs tentent de les réunir à nouveau.   Il est beaucoup plus facile d'ajouter OLAP à un noyau OLTP que de faire l'inverse. Bien sûr, les fournisseurs de solutions DW peuvent ajouter quelques indexations pour les recherches sur une seule ligne, mais je doute qu'ils ajoutent rapidement la prise en charge de fonctionnalités complexes telles que les déclencheurs et les insertions/mises à jour rapides. Le fait est que l'OLTP rapide est plus compliqué à construire que l'OLAP... c'est une technologie beaucoup plus mature. IRIS est une excellente base de données translytique (voir les évaluations des analystes pour comprendre pourquoi). Par exemple, certaines bases de données prennent en charge à la fois le stockage en lignes et en colonnes, mais dans des tables différentes.  IRIS peut disposer de colonnes de stockage en lignes dans la même table que les colonnes de stockage en colonnes.

/* Exemple de combinaison entre stockage en lignes et stockage en colonnes. 
   Toutes les colonnes sont stockées en lignes (par défaut), à l'exception de EventValue.
   EventValue est explicitement définie comme stockage en colonnes. 
   Si vous interrogiez la valeur moyenne de EventValue pour l'ensemble de la table, la réponse serait RAPIDE! */CREATETABLE Sample.CustEvent (
  CustID INTEGER,
  EventDt DATE,
  EventValue NUMERIC(12,2) WITH STORAGETYPE = COLUMNAR,
  EventCD VARCHAR(8))

Installation: Avec d'autres bases de données, vous devez généralement les installer quelque part (sur site ou dans le cloud), comme vous le faites avec Postgres ou SQL Server, ou bien recourir à un SAAS cloud tel que RedShift ou Snowflake. Avec IRIS, cela dépend. Il y a trois moyens d'obtenir IRIS : via une licence, via un service géré ou via Cloud SQL. 

  1. Grâce à une licence, vous pouvez l'installer, le configurer et le maintenir de manière indépendante. Cela peut se faire sur site ou sur le cloud de votre choix. J'ai surtout entendu parler de son utilisation sur AWS, Azure, GCP et TenCent.
  2. Grâce à un service géré, InterSystems installe, configure et assure la maintenance d'IRIS pour vous via un cloud public. 
  3. Grâce à Cloud SQL, il est possible de bénéficier d'un service SAAS (ou devrais-je dire PAAS ? DBAAS ?).  Vous n'avez rien à installer.  Il est conçu pour s'intégrer dans des systèmes plus vastes en tant que module composable, n'offrant qu'un sous-ensemble des fonctionnalités IRIS, telles que SQL et les fonctions d'apprentissage automatique (ML).  La suite de cet article concerne IRIS sous licence ou IRIS géré, et ne concerne pas Cloud SQL.

Langages intégrés: Outre SQL, IRIS a toujours pris en charge un langage orienté objet appelé ObjectScript, qui est un dérivé du langage médical MUMPS. Il s'agit d'un langage très puissant, mais peu connu. Ne vous inquiétez pas, IRIS prend également en charge Python intégré. 

Documentation: Comme IRIS a toujours été étroitement lié à ObjectScript, la documentation a tendance à utiliser une terminologie orientée objet.  Vous trouverez donc des termes simples tels que tables désignés par 'classes persistentes'.  Mais cela semble disparaître de la documentation au fil du temps, et vous pouvez tout simplement ignorer ces termes, sauf si vous souhaitez devenir programmeur IRIS.

IRIS prend donc en charge le langage SQL que vous connaissez et appréciez, ainsi que Python, il est translytique, fonctionne sur site ou dans le cloud, est multimodèle et dispose de fonctionnalités futuristes telles que l'ECP.  Il y a bien d'autres choses encore mais ce sont celles-ci qui m'ont paru les plus importantes et interessantes.  Je pense qu'elles pourraient être utiles à d'autres développeurs SQL et administrateurs de bases de données provenant d'autres produits.   Si c'est votre cas et que vous essayez IRIS, je souhaiterais connaître votre avis sur votre expérience.

0
0 27
Article Iryna Mykhailova · Oct 2, 2025 25m read

Table des matières

  1. Objectif de l'article
  2. Les conteneurs : définition et pertinence dans le cadre d'IRIS
     2.1 Les conteneurs et les images en quelques mots
     2.2 Avantages des conteneurs pour les développeurs
     2.3 Pourquoi IRIS fonctionne bien avec Docker
  3. Conditions préalables
  4. Installation de l'image InterSystems IRIS
     4.1 Utilisation de Docker Hub
     4.2 Extraction de l'image
  5. Exécution de l'image InterSystems IRIS
     5.1 Démarrage d'un conteneur IRIS
     5.2 Vérification de l'état des conteneurs
     5.3 Exécution de code dans le terminal conteneur
     5.4 Accès au portail de gestion IRIS
     5.5 Connexion du conteneur à VS Code
     5.6 Arrêt ou suppression du conteneur
     5.7 Configuration d'un mot de passe spécifique avec un montage de type bind
     5.8 Utilisation de volumes %SYS durables
      5.8.1 Contenu stocké sous %SYS durable
      5.8.2 Comment activer %SYS durable
  6. Utilisation de Docker Compose
     6.1 Exemple d'utilisation de l'outil Docker Compose
     6.2 Exécution de Docker Compose
  7. Utilisation d'un fichier Dockerfile pour l'exécution d'un code source personnalisé
     7.1 Exemple de fichier Dockerfile
     7.2 Exemple de Docker Compose
     7.3 Compréhension des couches, du balisage des images et de la différence entre le temps de compilation et le temps d'exécution
     7.4 Code source et script d'initialisation
     7.5 Création de l'image avec le fichier Dockerfile
     7.6 Exécution d'instructions dans le terminal IRIS conteneurisé
  8. Conclusion et suite


1. Objectif de l'article

La communauté de développeurs InterSystems propose déjà de nombreux articles intéressants qui expliquent le fonctionnement de Docker, les commandes les plus importantes et plusieurs cas d'utilisation d'InterSystems IRIS dans un environnement conteneurisé.

Les articles de cette série ont un objectif quelque peu différent. Je suis un grand fan des guides étape par étape, c'est pourquoi je souhaite créer un guide complet sur la configuration et l'utilisation de Docker avec InterSystems IRIS, en commençant par les bases pour ensuite passer progressivement à des scénarios plus avancés tels que les instances à espaces de noms multiples, les conteneurs interconnectés, les intégrations avec des systèmes externes et les applications comprenant une interface utilisateur.

2. Les conteneurs : définition et pertinence dans le cadre d'IRIS

2.1 Les conteneurs et les images en quelques mots

Traditionnellement, pour exécuter une application, il fallait faire correspondre sa version à celle de votre système d'exploitation et la packager pour cette cible spécifique. Dans le même temps, chaque application doit être conçue pour fonctionner spécifiquement avec un système cible. Si vous vouliez qu'une application fonctionne sous macOS et Windows, vous deviez modifier sa conception et la packager pour ces différents systèmes. Les images et conteneurs Docker constituent des technologies de déploiement d'applications qui résolvent ces problèmes en permettant aux développeurs de packager un logiciel une seule fois et de l'exécuter n'importe où. 

Docker est une plateforme logicielle qui regroupe des logiciels dans des conteneurs. Une image Docker, ou image de conteneur, est un fichier exécutable autonome contenant toutes les instructions (bibliothèques, dépendances et fichiers) nécessaires pour créer et exécuter un conteneur. Une image Docker est partageable et portable, ce qui vous permet de déployer la même image à plusieurs endroits à la fois. Un conteneur Docker est un environnement d'exécution qui contient tous les composants nécessaires pour exécuter le code de l'application sans utiliser les dépendances de la machine hôte.  

Contrairement aux machines virtuelles, les conteneurs sont légers. Ils n'ont pas besoin d'un système d'exploitation complet et fonctionnent directement sur le système d'exploitation hôte via le moteur Docker Engine en utilisant uniquement les binaires et les bibliothèques nécessaires à l'application spécifique, ce qui les rend plus efficaces. Plusieurs conteneurs isolés peuvent être lancés en même temps sur la même machine sans interférer les uns avec les autres.

2.2 Avantages des conteneurs pour les développeurs

  • Isolation: exécution dans un environnement propre et reproductible sans affecter le système hôte.
  • Reproductibilité: assurance que la configuration fonctionne de la même manière sur différentes machines.
  • Configuration facile: lancement d'une instance IRIS en quelques secondes à l'aide d'une seule commande, sans installation manuelle.

2.3 Pourquoi IRIS fonctionne bien avec Docker

L'exécution d'InterSystems IRIS dans Docker présente plusieurs avantages:

  • L'application peut être exécutée et testée dans des conteneurs isolés,
  • Il est possible d'utiliser des systèmes de contrôle de version partagés (tels que Git) au lieu de travailler directement sur le serveur
  • L'environnement conteneurisé peut être répliqué à n'importe quelle étape, ce qui garantit la cohérence tout au long du cycle de vie du logiciel.
  • Votre application peut facilement être exécutée sur n'importe quel ordinateur.

3. Conditions préalables

Pour exécuter InterSystems IRIS dans un conteneur Docker, il faut que vous ayez:

4. Installation de l'image InterSystems IRIS

4.1 Utilisation de Docker Hub

Docker Hub est le registre central des images Docker. Il fournit une vaste bibliothèque d'images pré-construites que vous pouvez utiliser comme point de départ. InterSystems y publie les images officielles IRIS Community Edition que vous pouvez télécharger pour exécuter IRIS localement dans votre conteneur. Vous pouvez également utiliser Docker Hub pour pousser vos propres images personnalisées afin de les partager au sein de votre équipe ou de les distribuer à la communauté. Docker Hub est disponible en ligne et intégré à Docker Desktop.

4.2 Extraction de l'image

Voici quelques commandes courantes pour les images Docker :

CommandeDescription
docker pull <image>Téléchargement d'une image depuis Docker Hub
docker imagesRépertoire de toutes les images locales
docker rmi <image>Suppression d'une ou plusieurs images

Vous trouverez la commande pull exacte directement sur la page Docker Hub de l'image:

Pour l'image InterSystems IRIS, la commande est comme suit:

docker pull intersystems/iris-community:latest-cd

Vous pouvez également rechercher iris-community dans la barre de recherche de Docker Desktop et cliquer sur Pull:

Une fois l'installation terminée, l'image InterSystems IRIS devrait apparaître dans la liste de vos images locales:

5. Exécution de l'image InterSystems IRIS

Une fois l'image InterSystems IRIS extraite de Docker Hub, vous pouvez l'exécuter dans un conteneur. 

Voici les principales commandes pour les conteneurs Docker:

CommandeDescription
docker run -d <image>Exécution en mode détaché : démarrer le conteneur en arrière-plan et renvoyer immédiatement le contrôle au terminal.
docker run -p <host>:<container> <img>Mappage du port hôte vers le port du conteneur
docker psListe des conteneurs en cours d'exécution
docker ps -aListe de tous les conteneurs (y compris les conteneurs arrêtés)
docker exec -it <container> bashExécution d'une commande dans un conteneur en cours d'exécution
docker logs <container>Affichage des journaux d'un conteneur
docker stop <container>Arret d'un conteneur en cours d'exécution
docker start <container>Démarrage d'un conteneur arrêté
docker restart <container>Redémarrage d'un conteneur
docker rm <container>Suppression d'un conteneur

5.1 Démarrage d'un conteneur IRIS

Vous pouvez démarrer un conteneur InterSystems IRIS Community Edition nommé "my-iris" via l'interface utilisateur Docker Desktop en cliquant simplement sur le bouton Run de l'image que vous souhaitez exécuter dans le panneau Images. Pour l'image InterSystems, il est possible de spécifier quelques paramètres facultatifs, tels que les ports à exposer sur votre machine hôte pour communiquer avec les services exécutés dans le conteneur.

Cela peut être fait via le menu ci-dessus, en considérant que:

  • côté gauche → port sur la machine hôte
  • côté droit → port à l'intérieur du conteneur

Ports IRIS courants (à l'intérieur du conteneur)

  • 1972 → Port Superserver : utilisé par IRIS pour les protocoles réseau (ObjectScript, JDBC, etc.).
  • 52773 → Port du serveur Web : utilisé par IRIS pour le portail de gestion (interface Web).

Si vous ne mappez pas explicitement les ports, Docker attribuera des ports aléatoires sur l'hôte.

Vous pouvez également exécuter le conteneur à l'aide du terminal:

docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 intersystems/iris-community:latest-cd

Dans cet exemple:

  • 9091 sur l'hôte est mappé à 1972à l'intérieur du conteneur (Superserver).
  • 9092 sur l'hôte est mappé à 52773 à l'intérieur du conteneur (Portail de gestion).

5.2 Vérification de l'état des conteneurs

Après avoir exécuté cette commande, exécutez docker ps pour vérifier si le conteneur fonctionne correctement.

> docker ps
CONTAINER ID   IMAGE                                   COMMAND                 CREATED         STATUS                            PORTS                                                                                        NAMES
907d4c2b4ab5   intersystems/iris-community:latest-cd   "/tini -- /iris-main"   3 seconds ago   Up 2 seconds (health: starting)   0.0.0.0:9091->1972/tcp, [::]:9091->1972/tcp, 0.0.0.0:9092->52773/tcp, [::]:9092->52773/tcp   my-iris

Les conteneurs en cours d'exécution sont également répertoriés dans le panneau Containers de Docker Desktop:

L'état des images associées sera "In Use" (En cours d'utilisation), comme indiqué dans le panneau Images :

5.3 Exécution de code dans le terminal conteneur

Une fois que le statut du conteneur indique Running (exécution), tout fonctionne correctement. 

Vous pouvez le tester en ouvrant le terminal du conteneur (cliquez sur le nom du conteneur dans le panneau de conteneurs (Containers) de Docker Desktop et accédez à Exec) et en saisissant:

iris session IRIS

Cela ouvre un terminal IRIS à l'intérieur du conteneur Docker, où vous pouvez utiliser la syntaxe ObjectScript standard pour exécuter des commandes et des scripts.

5.4 Accès au portail de gestion IRIS de l'instance conteneurisée

Ensuite, ouvrez votre navigateur et accédez à:

http://localhost:9092/csp/sys/UtilHome.csp

Par défaut, les conteneurs IRIS se servent de l'utilisateur _SYSTEM avec le mot de passe SYS. Il est nécessaire de changer le mot de passe après la connexion.

Cela vous donne un accès complet au portail de gestion IRISvous permettant de gérer les espaces de noms, les bases de données et d'autres fonctionnalités IRIS directement depuis l'interface web.

5.5 Connexion du conteneur VSCode

Vous pouvez connecter votre IDE préféré (tel que VS Code ou Studio) au conteneur IRIS à l'aide du port Superserver mappé (par défaut 1972 à l'intérieur du conteneur, par exemple, 9091 sur l'hôte) et du port du serveur Web (par défaut 52773 à l'intérieur du conteneur, par exemple, 9092 sur l'hôte). Cela vous permet de développer et de tester du code ObjectScript directement sur le conteneur en cours d'exécution.

Pour connecter le conteneur à VSCode:

  • Installez la solution InterSystems ObjectScript Extension Pack
  • Ouvrez l'extension InterSystems Server
  • Cliquez sur les trois points et sélectionnez "Edit server" (Modifier le serveur)
  •  
  • Cliquez sur "Modifier dans settings.json"
  • Ajoutez cet élément au fichier json "intersystems.servers":
"docker_iris": {
    "webServer": {
         "scheme": "http",
         "host": "localhost",
         "port": 9092
    },
    "description": "Connection to Docker container."
}
  • Maintenant le serveur est connecté. Vous pouvez vous connecter avec l'utilisateur _SYSTEM.
  • Comme vous pouvez le constater, l'espace de noms USER (UTILISATEUR) est le seul disponible:

5.6 Arrêt ou suppression du conteneur

Pour arrêter un conteneur en cours d'exécution, utilisez la commande:

docker stop my-iris

Redémarrage du conteneur

Pour redémarrer le conteneur, utilisez la commande

docker start my-iris

Suppression (effacement) du conteneur

Pour supprimer l'instance du conteneur, mais pas l'image, utilisez la commande: 

docker rm my-iris

La totalité des données contenues dans le conteneur sera perdue, sauf si vous avez monté des volumes (nous en parlerons dans les paragraphes suivants).

5.7 Configuration d'un mot de passe spécifique avec un montage de type bind

Il est possible de configurer un mot de passe personnalisé lors du démarrage d'un conteneur à l'aide d'un fichier de mots de passe. Le fichier sera enregistré sur notre hôte et copié dans le conteneur à l'aide du mécanisme bind mount .

Lorsque vous utilisez un bind mount, un fichier ou un répertoire sur la machine hôte est monté depuis l'hôte dans un conteneur, ce qui permet de partager le code source ou les artefacts de compilation entre un environnement de développement sur l'hôte Docker et un conteneur. 

  • Créez un fichier nommé password.txt contenant uniquement votre mot de passe sous forme de chaîne (attention! Notez votre mot de passe, vous en aurez besoin plus tard). 
  • Copiez le chemin d'accès, dans cet exemple ce sera C:\InterSystems\DockerTest\password\password.txt
  • Exécutez la commande suivante:
docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 --volume "C:\InterSystems\DockerTest:/durable" intersystems/iris-community:latest-cd --password-file /durable/password/password.txt 

Une fois le conteneur lancé, vous pouvez vous connecter avec l'utilisateur _SYSTEM et le mot de passe que vous avez enregistré dans votre fichier de mots de passe. 

À l'intérieur du conteneur Docker, vous verrez un fichier password.txt.done . Le même fichier se trouvera dans votre dossier hôte.

L'extension du fichier est remplacée par .done afin d'éviter la présence du mot de passe dans le texte brut. Il s'agit du comportement standard d'InterSystems IRIS avec les fichiers de mots de passe. Par conséquent, une fois le mot de passe lu à partir du fichier password.txt et l'utilisateur IRIS par défaut (_SYSTEM) mis à jour avec ce mot de passe, le fichier est mis à jour en ajoutant .done et en supprimant le mot de passe pour des raisons de sécurité.

Vous pouvez vous connecter au Portail de gestion à l'aide de votre mot de passe personnalisé (je vous avais dit de le noter :D). InterSystems IRIS ne vous obligera pas à changer le mot de passe après votre connexion.

Veuillez noter que si le conteneur est supprimé puis redémarré sans aucun volume durable monté (pour plus d'informations, voir le paragraphe suivant), le mot de passe ne sera pas relu à partir du fichier password.txt , car il a été remplacé par le fichier password.txt.done. Dans ce cas, le mot de passe standard "SYS" sera utilisé. 

5.8 Démarrage du conteneur avec un volume durable spécifique. Utilisation de volumes %SYS durables

Par défaut, tout ce que vous enregistrez dans un conteneur Docker en cours d'exécution disparaît lorsque vous le supprimez à l'aide de la commande docker rm <container's name> . 

Pour éviter de perdre vos données, InterSystems IRIS fournit la fonctionnalité durable %SYS. Cette fonctionnalité permet à l'instance de stocker tous les fichiers importants sur votre machine hôte, afin qu'ils survivent aux redémarrages du conteneur et de l'instance.

5.8.1 Contenu stocké sous %SYS durable

Voici quelques exemples:

  • Fichiers de configuration (iris.cpf, httpd.conf)
  • Configurations et journaux de la passerelle Web (/csp)
  • Bases de données système (IRIS, USER, IRISSECURITY, IRISTEMP, etc.)
  • Journaux, fichiers image d'écriture (WIJ) et fichiers temporaires
  • Fichiers journaux (messages.log, SystemMonitor.log, etc.)
  • Clé de licence (iris.key)
  • Toute autre base de données que vous avez créée

5.8.2 Comment activer %SYS durable

La première chose à faire est de choisir un dossier sur votre hôte, tel que C:\InterSystems\DockerTest

  • Sous Linux, assurez-vous qu'IRIS peut y écrire en créant l'utilisateur irisowner et en lui attribuant la propriété du répertoire:
adduser irisowner
chown -R irisowner:irisowner /InterSystems/DockerTest
  • Sous Windows, vous pouvez ignorer cette étape, car Docker Desktop will montera le dossier avec vos autorisations utilisateur Windows actuelles.

Ensuite, montez votre dossier hôte et indiquez à IRIS où écrire ses données durables à l'aide de la variable ISC_DATA_DIRECTORY:

  --volume "C:\InterSystems\DockerTest:/durable" --env ISC_DATA_DIRECTORY=/durable/iris

L'instruction complète à exécuter sur le terminal est la suivante:

docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 --volume "C:\InterSystems\DockerTest:/durable" --env ISC_DATA_DIRECTORY=/durable/iris intersystems/iris-community:latest-cd --password-file /durable/password/password.txt

À ce stade, vous pouvez inspecter votre conteneur et observer qu'un dossier durable est monté et contient les répertoires iris/ (pour le %SYS durable) et password/. Sur votre hôte, vous pouvez également voir les deux répertoires:

Si le conteneur est arrêté et supprimé, lorsque vous recréez le conteneur avec la même commande de Docker Compose IRIS restaurera son état précédent (utilisateurs, configuration, journaux, bases de données, etc.) à l'aide des données du dossier iris/, de sorte que rien ne soit perdu. Vous pouvez tester cette méthode en créant une application web, en arrêtant et en supprimant le conteneur, puis en le recréant une deuxième fois. Sans utiliser la fonctionnalité durable %SYS, toutes les modifications apportées à %SYS sont perdues lorsque le conteneur est supprimé et l'instance est lancée à chaque fois comme une nouvelle instance. 

Veuillez noter que si vous supprimez le dossier iris/, la prochaine fois que vous lancerez le conteneur IRIS, il sera initialisé comme lors d'une nouvelle installation, car il ne trouvera pas les données %SYS précédentes. Un tout nouveau dossier iris/ sera créé.

6. Utilisation de Docker Compose 

Jusqu'à présent, vous avez démarré InterSystems IRIS à l'aide d'une seule commande longue docker run. Cela fonctionne, mais il devient rapidement difficile de tout gérer avec des commandes shell simples.

Docker Compose est un fichier de configuration YAML qui permet de définir comment exécuter un ou plusieurs conteneurs. Cela simplifie le contrôle de l'ensemble de votre pile d'applications, facilitant la gestion des services, des réseaux et des volumes. Une seule commande vous permet de créer et de démarrer tous les services à partir de votre fichier de configuration.

Voici les commandes courantes pour Docker Compose:

CommandeDescription
docker compose up -dDémarrer tous les services définis dans docker-compose.yml en mode détaché (par défaut, utiliser le fichier docker-compose.yml du dossier courant).
docker compose -f ./path/to/docker-compose.yml up -dDémarrer les services à partir d'un fichier de composition dans un autre répertoire.
docker compose downArrêter et supprimer tous les conteneurs, réseaux et volumes créés par docker compose up.
docker compose psRépertorier les conteneurs gérés par Compose.
docker compose logsAfficher les journaux de tous les services définis dans le fichier Compose.
docker compose logs <service>Afficher les journaux d'un service spécifique (par exemple, iris).
docker compose exec <service> bashOuvrez un shell dans un conteneur en cours d'exécution géré par Compose.
docker compose stopArrêtez les conteneurs en cours d'exécution, mais ne les supprimez pas.
docker compose startDémarrer les conteneurs précédemment arrêtés.
docker compose restartRedémarrer tous les conteneurs définis dans le fichier Compose.
docker compose buildConstruire ou reconstruire les services définis par un fichier Dockerfile.
docker compose pullTélécharger la ou les dernières images pour les services.
docker compose configValider et afficher la configuration fusionnée à partir du fichier Compose.

6.1 Exemple d'utilisation de l'outil Docker Compose

Pour utiliser Docker Compose, il est nécessaire de créer un fichier docker-compose.yml contenant toutes les configurations du conteneur que l'on souhaite créer et démarrer.

Ainsi la commande suivante:

docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 --volume "C:\InterSystems\DockerTest:/durable" --env ISC_DATA_DIRECTORY=/durable/iris intersystems/iris-community:latest-cd --password-file /durable/password/password.txt

peut être remplacé par la suivante docker-compose.yml:

# docker-compose.yml     
services:
  iris:
    container_name: my-iris
    image: intersystems/iris-community:latest-cd
    init: true
    volumes:
      # Données système/persistantes (installation IRIS, bases de données, etc.)# Sous Windows, vous pouvez utiliser les deux options: "C:\\InterSystems\\DockerTest:/durable"
      - C:/InterSystems/DockerTest:/durable
      ports:
      - "9092:52773"# Portail de gestion / API REST
      - "9091:1972"# Port SuperServer
      environment:
      - ISC_DATA_DIRECTORY=/durable/iris
      # Utilisation du fichier de mots de passe pour se connecter au conteneur
      command: --password-file /durable/password/password.txt

6.2 Exécution de Docker Compose 

Ouvrez un terminal dans le répertoire où le fichier Docker Compose est enregistré (ou utilisez l'option -f) et exécutez la commande suivante:

docker compose up -d

Votre conteneur IRIS démarrera dans la configuration exacte spécifiée dans le fichier Docker Compose

Dans Docker Desktop, vous pouvez désormais voir qu'une pile composée appelée "dockertest" (elle prend le nom du dossier dans lequel Docker Compose est enregistré) a été créée et associée au conteneur "my-iris":

7. Utilisation d'un fichier Dockerfile pour l'exécution d'un code source personnalisé

Jusqu'à présent, vous avez exécuté InterSystems IRIS directement à partir de l'image Docker officielle. Cependant, nous aurons peut-être besoin de télécharger automatiquement des classes ObjectScript ou d'autres codes personnalisés dans l'image lors de sa création. 

Un fichier Dockerfileest un fichier texte contenant des instructions pour créer une image à partir d'une image de base (comme intersystems/iris-community:latest-cd). Grâce à un fichier Dockerfile, nous pouvons ajouter du code source personnalisé dans le conteneur et exécuter des commandes personnalisées lors de la création de l'image. 

7.1 Exemple de fichier Dockerfile

Le prochain exemple fournit un fichier Dockerfile qui effectue les opérations suivantes:

  • Démarrez l' image à partir de l'image officielle InterSystems IRIS.
  • Copiez le code de votre application depuis le dossier src/ vers le conteneur.
  • Exécutez un script pour importer les classes et initialiser l'application conteneurisée, puis enregistrez les journaux dans un fichier journal.
  • Exposez les ports InterSystems IRIS par défaut.

7.2 Exemple d'utilisation de l'outil Docker Compose

Vous devez également modifier Docker Compose afin de spécifier la création de l'image à partir du fichier Dockerfile situé dans le dossier courant:

# docker-compose.yml     
services:
  iris:
    container_name: my-iris
    build: # Cela indique à Docker de créer une nouvelle image basée sur celle spécifiée dans le fichier Dockerfile
      context: .        # Construction de l'image à partir du fichier Dockerfile local
      dockerfile: Dockerfile
    image: my-modified-iris-image:latest   # attribution d'une nouvelle balise à la nouvelle image afin d'éviter de remplacer l'image de base
    init: true
    volumes:
      # Données système/persistantes (installation IRIS, bases de données, etc.)# Sous Windows, vous pouvez utiliser les deux options: "C:\\InterSystems\\DockerTest:/durable"
      - C:/InterSystems/DockerTest:/durable
ports:
      - "9092:52773"# Portail de gestion / API REST
      - "9091:1972"# Port SuperServer
environment:
      - ISC_DATA_DIRECTORY=/durable/iris
    # Utilisation du fichier de mots de passe pour se connecter au conteneur
    command: --password-file /durable/password/password.txt

7.3 Compréhension des couches, du balisage des images et de la différence entre le temps de compilation et le temps d'exécution

Dans Docker, comme expliqué ici: Qu'est-ce qu'une image?, il y a deux principes importants à garder à l'esprit:

  1. Les images sont immuables: une fois qu'une image est créée, elle ne peut plus être modifiée. Vous pouvez uniquement créer une nouvelle image ou y ajouter des modifications.
  2. Les images de conteneur sont composées de couches: chaque couche représente un ensemble de modifications du système de fichiers qui ajoutent, suppriment ou modifient des fichiers.

De nouvelles couches sont ajoutées à une image lorsque les instructions spécifiées dans un fichier Dockerfile sont exécutées. Ces couches apparaîtront également dans les informations relatives à l'image.

Dans cette optique, il est très important de distinguer ce que fait Docker au temps de compilation (lorsqu'il crée une image à partir d'un fichier Dockerfile) et au temps d' exécution (lorsqu'il démarre un conteneur à partir de cette image).

Chacune de ces instructions Dockerfile est exécutée au temps de compilation

  • COPY: les fichiers sont copiés dans l'image
  • RUN: exécute des commandes et enregistre les résultats sous forme de nouvelles couches d'image
  • ENTRYPOINT: ne modifie pas le système de fichiers, mais définit le processus par défaut qui sera lancé au moment de l'exécution
  • EXPOSE: définit les métadonnées relatives aux ports que l'image prévoit d'utiliser

Au temps d'exécution, Docker ne reconstruit pas l'image, mais ajoute une couche de conteneur par-dessus. Toutes les modifications apportées pendant l'exécution du conteneur (comme les nouveaux fichiers, les modifications, les journaux) sont enregistrées dans cette couche temporaire.

D'après le dernier exemple fourni par Docker Compose:

build: # cela indique à Docker de créer une nouvelle image basée sur celle spécifiée dans le fichier Dockerfile
context: .        # Construction de l'image à partir du fichier Dockerfile local
dockerfile: Dockerfile
image: my-modified-iris-image:latest   # attribution d'une nouvelle balise à la nouvelle image afin d'éviter de remplacer l'image de base

Ces instructions indiquent à Docker de créer une nouvelle image appelée "my-modified-iris-image:latest" (ceci s'appelle un tag) en récupérant l'image de base et en la modifiant comme décrit dans le fichier Dockerfile. Il est très important de marquer la nouvelle image avec un nom distinct. Si nous évitons d'apposer une balise sur l'image nouvellement créée, l'image de base sera remplacée par la nouvelle. L'image officielle sera toujours disponible sur Docker Hub, mais cette version locale la masquera et tous les projets faisant référence à cette balise utiliseront désormais, sans le savoir, l'image personnalisée, contenant plusieurs nouvelles couches.

Pour éviter cela, utilisez toujours une balise distincte pour créer une nouvelle image distincte tout en conservant l'image de base officielle propre et réutilisable. 

7.4 Code source et script d'initialisation

À ce stade, nous devons créer au moins une classe et la placer dans le src/ dossier. La classe sera copiée dans le conteneur et importée via le iris.script fichier, qui contient toutes les instructions nécessaires pour importer les classes et initialiser l'application lors de la création de l'image.

Créez un nouveau répertoire appelé src/DockerStepByStep dans le dossier de votre projet et créez le fichier de classe suivant:

Class DockerStepByStep.cheers Extends%RegisteredObject
{

ClassMethod sayHi() As%Status { Set sc = $$$OKw"Hi mom!",! Return sc }

}

Dans la racine de votre projet, créez un fichier portant le nom iris.script:

// Non-expiration des mots de passe pour le mode devzn"%SYS"Do##class(Security.Users).UnExpireUserPasswords("*")

// Téléchargement des cours à partir d'une source fiablezn"USER"// Les classes à importerset importPath = "/opt/irisapp/src"write"Loading classes at '", importPath, "' ...", ! set errors = ""do$System.OBJ.Import(importPath,"cuk",,.errors) if errors = 0 { write"Classes loaded successfully", ! } else { write errors, " errors occurred while loading classes!", ! }

halt

7.5 Création de l'image avec le fichier Dockerfile

Pour la première exécution, vous pouvez utiliser la commande suivante pour créer l'image à partir du fichier Dockerfile (le drapeau --build force Docker à recréer l'image à partir de votre fichier Dockerfile):

docker-compose up --build

Pour les autres exécutions, si le fichier Dockerfile n'a pas été modifié, vous pouvez simplement exécuter ce qui suit: 

docker-compose up -d

Une fois la création de l'image lancée, vous verrez apparaître les journaux suivants dans le terminal:

PS C:\InterSystems\DockerTest> docker-compose up --build
[+] Building 21.5s (13/13) FINISHED
 => [internal] load local bake definitions                                                                     0.0s
 => => reading from stdin 530B                                                                                 0.0s
 => [internal] load build definition from Dockerfile                                                           0.0s
 => => transferring dockerfile: 1.73kB                                                                         0.0s
 => [internal] load metadata for docker.io/intersystems/iris-community:latest-cd                              10.0s
 => [internal] load .dockerignore                                                                              0.0s
 => => transferring context: 2B                                                                                0.0s
 => [1/6] FROM docker.io/intersystems/iris-community:latest-cd@sha256:93488df381f5868649e7bfc33a9083a3e86a22d  0.9s
 => => resolve docker.io/intersystems/iris-community:latest-cd@sha256:93488df381f5868649e7bfc33a9083a3e86a22d  0.0s
 => [internal] load build context                                                                              0.0s
 => => transferring context: 147B                                                                              0.0s
 => [2/6] WORKDIR /opt/irisapp                                                                                 0.0s
 => [3/6] COPY src src                                                                                         0.1s
 => [4/6] COPY iris.script .                                                                                   0.1s
 => [5/6] RUN mkdir -p /opt/irisapp/logs                                                                       0.3s
 => [6/6] RUN iris start IRIS &&     iris session IRIS < iris.script > /opt/irisapp/logs/build.log 2>&1 &&     4.5s
 => exporting to image                                                                                         4.5s
 => => exporting layers                                                                                        3.3s
 => => exporting manifest sha256:3ce316cefa21a3707251c4287005a15b02e6dc0151b24baf2a82f76064792250              0.0s
 => => exporting config sha256:00238e19edef86b29149d2eb89ff75f4d1465ba0d9a2ac4494a14d3bd3746a94                0.0s
 => => exporting attestation manifest sha256:3579cab5c8accc7958090276deb60bd7dbbc2ecbf13af8e7fa8c4ff2dfe91028  0.0s
 => => exporting manifest list sha256:17b969c340f57d611cc7603287cc6db50cffd696258a72b5648ece0a919676ac         0.0s
 => => naming to docker.io/intersystems/iris-community:latest-cd                                               0.0s
 => => unpacking to docker.io/intersystems/iris-community:latest-cd                                            0.9s
 => resolving provenance for metadata file                                                                     0.0s
[+] Running 3/3
 ✔ intersystems/iris-community:latest-cd  Built                                                                0.0s
 ✔ Network dockertest_default             Created                                                              0.1s
 ✔ Container my-iris                      Created                                                              0.2s 

À l'étape 6/6, le fichier iris.script est exécuté dans l'instance IRIS conteneurisée et les journaux sont enregistrés dans le chemin /opt/irisapp/logs/build.log.

Pour afficher les journaux, vous pouvez exécuter l'instruction suivante:

docker exec -it my-iris cat /opt/irisapp/logs/build.log

Vous devriez voir les enregistrements suivants qui vous informent du résultat de la compilation de la classe:

Node: buildkitsandbox, Instance: IRIS

USER>

USER>

%SYS>

%SYS>

%SYS>

%SYS>

USER>

USER>

USER>

USER> Loading classes at '/opt/irisapp/src' ...

USER>

USER>

Load of directory started on 09/16/202507:46:28 Loading file /opt/irisapp/src/DockerStepByStep/cheers.cls as udl

Compilation started on 09/16/202507:46:28 with qualifiers 'cuk' Class DockerStepByStep.cheers is up-to-date. Compilation finished successfully in 0.005s.

Load finished successfully.

USER> Classes loaded successfully

USER>

USER>

Sur Docker Desktop, vous pouvez voir qu'une nouvelle image appelée "my-modified-iris-image" a été créée et s'exécute parallèlement à l'image officielle de base.

Si vous examinez les images, vous constaterez que la version personnalisée est composée de 31 couches, contre 25 couches pour l'originale. Les nouvelles couches correspondent aux instructions exécutées au moment de la compilation par le fichier Dockerfile:

7.6 Exécution d'instructions dans le terminal IRIS conteneurisé

Pour tester les classes, vous pouvez activer le terminal Iris dans l'instance IRIS conteneurisée. Pour ce faire, exécutez l'instruction suivante:

docker exec -it my-iris iris session IRIS

À ce stade, vous pouvez invoquer la méthode de classe à partir de l'espace de noms USER à l'aide de la commande suivante:

do##class(DockerStepByStep.cheers).sayHi()

Finalement, vous devriez obtenir le résultat suivant:

PS C:\InterSystems\DockerTest> docker exec -it my-iris iris session IRIS

Node: 41c3c7a9f2e4, Instance: IRIS

USER>do##class(DockerStepByStep.cheers).sayHi() Hi mom!

8. Conclusion et suite

Nous avons parcouru l'ensemble du cycle de mise en œuvre d'InterSystems IRIS dans Docker:

  • extraction de l'image
  • démarrage et configuration des conteneurs
  • persistance des données avec %SYS durable
  • création d'images personnalisées avec votre propre code et vos propres scripts

Cela suffit pour commencer à expérimenter IRIS dans un environnement conteneurisé et l'utiliser pour le développement.

Un référentiel GitHub contenant tous les fichiers mentionnés dans la dernière partie (Docker Compose, Dockerfile, iris.script, etc.) est disponible.

Ne manquez pas le prochain article!

1
0 24
Article Iryna Mykhailova · Sept 17, 2025 3m read

Salut tout le monde! Ayant récemment rejoint InterSystems, je me suis rendu compte que, même en ayant la version communautaire de la Community Edition totalement gratuite et géniale, la manière d'y accéder n'était pas très claire. J'ai donc décidé de rédiger un guide présentant toutes les différentes façons d'accéder à la version communautaire de la Community Edition d'InterSystems IRIS:

Obtention de la Community Edition d'InterSystems IRIS sous forme de conteneur

L'utilisation d'une instance conteneurisée de la Community Edition est l'approche recommandée pour les personnes qui découvrent le développement sur InterSystems IRIS. À mon avis, c'est aussi la plus simple. La Community Edition d'InterSystems IRIS est disponible sur DockerHub; si vous avez un compte SSO InterSystems, vous pouvez également la trouver dans le registre de conteneurscan also find it in the InterSystems Container Registry.

Quel que soit le cas, vous devrez extraire l'image de votre choix à l'aide de l'interface CLI Docker:

docker pull intersystems/iris-community:latest-em
// or
docker pull containers.intersystems.com/intersystems/iris-community:latest-em

Ensuite, vous devrez démarrer le conteneur: Afin d'interagir avec IRIS en dehors du conteneur (par exemple, pour utiliser le portail de gestion), vous devrez publier certains ports. La commande suivante exécutera le conteneur IRIS Community Edition avec les ports du superserveur et du serveur web publiés ; notez que vous ne pouvez rien avoir d'autre en cours d'exécution qui dépende des ports 1972 ou 52773!

docker run --name iris -d --publish 1972:1972 --publish 52773:52773 intersystems/iris-community:latest-em

Obtention de la Community Edition d'InterSystems IRIS dans le Cloud

Vous souhaitez peut-être éviter complètement le problème d'avoir à gérer une installation locale; et si tel est le cas, vous pouvez vous lancer avec un déploiement cloud de la Community Edition d'InterSystems IRIS. Tous les principaux fournisseurs de cloud sont pris en charge. Consultez notre page Cloud Partners page pour plus d'information. Dans cet exemple, nous allons nous concentrer sur le déploiement sur AWS.

Commencez par rechercher la Community Edition d'InterSystems IRIS sur AWS Marketplace:

Vous pouvez cliquer sur "View purchase options" (Afficher les options d'achat) et vous connecter à votre compte pour afficher la page d'abonnement:

 

En faisant défiler vers le bas, vous pouvez cliquer sur “Subscribe” (s'abonner), remplir l'information requise, puis cliquer sur “Deploy” (déployer) pour déployer la Community Edition d'InterSystems IRIS en tant que nœud cloud! Consultez notre documentation ici déploiement d'InterSystems IRIS dans le cloud pour plus de d'information.

Obtention de la Community Edition d'InterSystems IRIS sous forme de kit d'installation

Si vous préférez travailler avec InterSystems IRIS installé directement sur votre machine et que vous ne souhaitez pas utiliser de conteneurs, vous pouvez télécharger un kit d'installation pour votre système à partir du service InterSystems Evaluation Service. Pour télécharger un kit d'installation, vous devez avoir un identifiant SSO InterSystems. Bonne nouvelle: si vous avez un compte sur la Communauté de développeurs, vous en avez déjà un! Sinon, vous pouvez cliquer sur "Créer un nouveau compte" et suivre les étapes indiquées:

 Une fois connecté, la page suivante devrait s'afficher. Cliquez sur "Télécharger la version Community Edition" pour commencer le téléchargement du kit d'installation:

 

Vous serez invité à fournir certaines information concernant la version exacte d'InterSystems IRIS dont vous avez besoin et la plate-forme sur laquelle vous allez l'installer:

 

Dans la plupart des cas, vous devrez sélectionner « InterSystems IRIS Community » et la version la plus récente disponible pour votre plateforme. Suivez les instructions d'installation fournies dans la documentation spécifique à votre plateforme, et le tour est joué!

0
0 25
Article Iryna Mykhailova · Août 18, 2025 4m read

Récompense d’août pour les articles sur Global Masters a retenu mon attention, et l'un des sujets proposés m'a semblé très intéressant quant à son utilisation future dans mon enseignement. Voici donc ce que j'aimerais dire à mes étudiants à propos des tables dans IRIS et de leur corrélation avec le modèle objet.

Tout d'abord, InterSystems IRIS dispose d'un modèle de données unifié. Cela signifie que lorsque vous travaillez avec des données, vous n'êtes pas enfermé dans un paradigme unique. Les mêmes données sont accessibles et manipulables comme une table SQL traditionnelle, comme un objet natif, ou même comme un tableau multidimensionnel (global). Cela signifie que lorsque vous créez une table SQL, IRIS crée automatiquement une classe d'objet correspondante. Lorsque vous définissez une classe d'objet, IRIS la rend automatiquement disponible sous forme de table SQL. Les données elles-mêmes ne sont stockées qu'une seule fois dans le moteur de stockage multidimensionnel performant d'IRIS. Le moteur SQL et le moteur objet sont simplement des « optiques » différentes pour visualiser et travailler avec les mêmes données.

Commençons par examiner la corrélation entre le modèle relationnel et le modèle objet :

Relationnel Objet
Table Classe
Colonne Propriété
Ligne Objet
Clé primaire Identifiant d'objet

La corrélation n'est pas toujours exacte, car plusieurs tables peuvent représenter une même classe, par exemple. Mais c'est une règle générale.

0
0 23
Article Lorenzo Scalese · Juin 18, 2025 5m read

Le bon vieux temps

La classe %Library.DynamicObject existe dans IRIS depuis bien avant que IRIS ne devienne IRIS. Si vous l'utilisez depuis l'époque de Cache, vous souhaiterez peut-être vous familiariser avec certaines de ses modifications.

Dans Cache 2018, la méthode %Get n'avait qu'un seul argument. Il s'agissait de la clé permettant de récupérer les données dans le JSON. Ainsi, si votre objet JSON s'appelait myObj, cela ressemblerait à ceci:

{
    “mybool”:true,
    “mynum”:1234,
    “mystring”:”Hello World!”
}

L'exploitation de myObj.%Get(“mybool”) renverrait 1, myObj.%Get(“mynum”) renverrait 1234 et myObj.%Get("mystring") renverrait la chaîne "Hello World!" 

La définition de ces paramètres, en revanche, nécessitait un peu plus de travail. Par exemple, l'attribution d'une propriété JSON à 0 pouvait signifier le nombre 0, une valeur booléenne signifiant faux ou une chaîne littérale "0". C'est pourquoi la méthode %Set avait toujours un troisième argument facultatif. Pour créer l'objet JSON mentionné ci-dessus, nous pouvions utiliser le code suivant:

set myObj = ##class(%Library.DynamicObject).%New()
do myObj.%Set(“mybool”,1,”boolean”)
do myObj.%Set(“mynum”,1234,”number”)
do myObj.%Set(“mystring”,”Hello World!”,”string”)

Cependant, dans ce cas, nous pourrions également omettre le troisième argument des deux derniers. Ainsi, 1234 serait reconnu comme un nombre, car il n'est pas entre guillemets, tandis que "Hello World!" serait identifié comme une chaîne, car il est entre guillemets. Si nous voulions ajouter la valeur 1234 à l'objet en tant que chaîne, nous pourrions changer la chaîne en nombre. Nous pourrions également spécifier le type "null". Dans ce cas, la valeur doit être "". En pratique, cependant, nous ajoutons souvent ces valeurs à partir de variables dans notre code ObjectScript. Pour cette raison, il peut être préférable de spécifier cet argument, juste au cas où la variable serait une chaîne ou un nombre, afin de garantir que notre JSON arrive à destination correctement encodé.

Comment j'ai appris à ne plus m'inquiéter à propos de <MAXSTRING> et aimer JSON

Comme l'a dit un jour le sage Billy Joel, ""Le bon vieux temps n'était pas toujours bon, demain n'est pas aussi mauvais qu'il n'y paraît." La liste des types pour %Set s'est allongée, et la méthode %Get a acquis deux nouveaux arguments. Ce qui est crucial, c'est qu'elles prennent toutes deux en charge le type "stream". Si vous avez déjà traité de grandes quantités de données JSON, vous avez probablement déjà rencontré une erreur lorsque les données contenues dans le JSON dépassaient la longueur maximale autorisée pour une chaîne dans IRIS. La nouvelle méthode %Get vous permet de spécifier deux arguments supplémentaires, une valeur par défaut et un type. Votre ancien code continue toutefois de fonctionner, car ces deux arguments sont facultatifs et, s'ils sont omis, les méthodes fonctionnent exactement comme en 2018. Si rien n'est trouvé pour la clé donnée, la valeur par défaut est renvoyée. La fonction type fonctionne de manière similaire à l'argument type de la méthode %Set. Vous pouvez également spécifier le type de données que vous récupérez. Prenons l'exemple suivant du bloc try/catch:

try{
    Set mydata = myObj.%Get(“mydata”,”N/A”)
}
catch ex{
    if ex.Name = “<MAXSTRING>”{
        set mydata = myObj.%Get(“mydata”,,”stream”)
    }
}

Il tentera de définir mydata à la valeur située à l'intérieur de "mydata" dans l'objet JSON. Si cet élément n'existe pas, il renverra "N/A" à la place. Si cet élément est trop long pour une chaîne, le système lèvera une exception vers le bloc catch. Nous devons vérifier le nom de cette exception, car si une exception différente s'est produite, il ne serait pas logique d'essayer d'obtenir les données sous forme de flux. Vous pouvez en savoir plus sur la gestion des exceptions ici. Si la valeur est , nous spécifions que nous voulons récupérer mydata sous forme de flux. La récupération des données sous forme de flux renvoie un objet de la classe %Stream.DynamicCharacter. Cela ne déclenche jamais d'exception , mais peut générer une exception si la limite de mémoire du processus est dépassée.

Si vous suivez l'approche décrite ci-dessus, vous ne saurez pas si mydata dans le code est une chaîne ou un flux. Cela signifie que vous devrez suivre le code similaire à celui ci-dessous:

if$ISOBJECT(mydata){
    //Traitement des flux ici
}
else{
    //Traitement des chaînes ici
}

Vous pouvez également utiliser l'option stream chaque fois afin de vous assurer que vous avez toujours un flux à votre disposition. Cependant, cela entraînerait une utilisation inutile des ressources et alourdirait votre code.

Une autre option consiste à ajouter un flux à un objet dynamique à l'aide de %Set. Consultez l'exemple suivant:

set mystream = ##class(%Stream.FileBinary).%New()
do mystream.LinkToFile(“/path/to/your/file”)
do myObj.%Set(“mydata”,mystream,”stream”)

Les données de votre fichier seront désormais enregistrées dans le champ mydata de votre objet dynamique.

%Set et %Get encodent et décodent également les chaînes à l'aide de l'encodage Base64. 

Gardez toujours à l'esprit que l'encodage Base64 est un encodage et non un cryptage ! Il n'y a pas de clés secrètes ni de mots de passe pour décoder votre message, et il est facilement réversible. Par conséquent, vous devez toujours utiliser un protocole crypté, tel que TLS ou HTTPS, pour la transmission ! Base64 est utilisé pour transmettre des caractères non ASCII de manière à ce que les systèmes ASCII puissent les recevoir et les transmettre.

Maintenant que cette remarque importante est faite, nous pouvons enfin voir comment cela fonctionne. Si nous apportons une petite modification à l'exemple de code précédent, le contenu du flux de fichiers sera encodé en Base64.

set mystream = ##class(%Stream.FileBinary).%New()
do mystream.LinkToFile(“/path/to/your/file”)
do myObj.%Set(“mydata”,mystream,”stream>base64”)

D'autre part, si les données du fichier étaient déjà encodées en Base64 et que nous voulions les convertir en données décodées, il suffirait de changer un seul caractère.

set mystream = ##class(%Stream.FileBinary).%New()
do mystream.LinkToFile(“/path/to/your/file”)
do myObj.%Set(“mydata”,mystream,”stream<base64”)

Les signes " supérieur à" ou "inférieur à" indiquent toujours la direction dans laquelle la conversion a lieu. Si nous convertissons un flux non codé en une chaîne Base64, le signe pointera vers Base64. Si nous convertissons un flux codé en Base64 en un flux non codé, le signe pointera de Base64 vers le flux. La même fonctionnalité existe pour les chaînes lorsque string>base64 et string

set something = myObj.%Get(“something”,”NA”,”string>base64”)

Si l'élément "quelque chose" existe, il sera renvoyé sous sa forme encodée en Base64. Cependant, s'il n'existe pas, "NA" sera renvoyé sans être encodé.

Il existe une restriction concernant l'option d'encodage Base64. Seuls les caractères dont le code est compris entre 0 et 255 peuvent être encodés en Base64. Les codes de caractères supérieurs à 255 entraîneront une exception <WIDE CHAR>. FPar exemple, la ligne suivante provoquera une telle exception:

set mychar = $C(256)
do myobj.%Set(“mychar”,mychar,”string>base64”)

Alors, j'ai entendu dire que vous aimiez JSON . . .

Parfois, il y a du JSON à l'intérieur de votre JSON. La manière par défaut de gérer cette situation est généralement celle que vous choisiriez. Cependant, une autre option a été ajoutée à l'argument de type pour traiter un cas d'utilisation différent. Il s'agit du type "json". Regardez l'objet JSON suivant:

{
    “mystring”:”Hello World!”,
    “mynumber”:1234,
    “myjson”:{
        “subitem1”:”Hello Mars!”,
        “subitem2”:”Hello Stars!”
    }
}

En règle générale, lorsque vous rencontrez ce problème, vous devez utiliser la méthode %Get avec la clé « myjson » pour obtenir un objet dynamique. Voici un exemple:

set myjson = myobj.%Get(“myjson”)
write myjson.%Get(“subitem1”)

La ligne ci-dessus écrirait "Hello Mars!". C'est le cas le plus courant dans cette situation. Cependant, dans certains cas, vous préférerez peut-être obtenir le JSON réel contenu dans cet élément sous forme de chaîne. Dans ce cas, vous pouvez procéder comme suit:

set myjson = myobj.%Get(“myjson”,,”json”)
write myjson

La chaîne JSON sera écrite exactement telle qu'elle est:

{“subitem1”:”Hello Mars!”,”subitem2”:”Hello Stars!”}

Cela peut s'avérer utile dans les cas où nous voulons transmettre le JSON tel quel à un autre processus. Notez que, contrairement à tous les autres types nouveaux, celui-ci n'est pris en charge que pour la méthode %Get, et non pour la méthode %Set.

Hourra, hourra, les massives!

Jusqu'à présent, nous avons discuté de ces nouveaux objets dans le contexte de la classe %Library.DynamicObject, mais ils sont également pris en charge pour la classe %Library.DynamicArray. Dans cette classe, %Set et %Get prennent en charge les mêmes arguments de type que dans la classe %Library.DynamicObject. La classe de tableaux dynamiques dispose toutefois d'une méthode %Push supplémentaire. Elle prend en charge les mêmes types que %Set, à l'exception du type JSON.

Sans plus attendre, c'est probablement le bon moment pour revoir vos anciens codes et implémenter ces changements à votre avantage!

0
0 35
Article Sylvain Guilbaud · Mai 19, 2025 3m read

Bonjour à la communauté,

Vous cherchez un moyen d'intégrer InterSystems IRIS® for Health à votre équipe ? Exploitez tout le potentiel de cette plateforme grâce à ces ressources de formation InterSystems. Grâce à une combinaison de formations en ligne et en présentiel, vous pouvez accompagner différents rôles au sein de votre organisation et préparer votre équipe à la réussite.

Ressources d'intégration pour chaque rôle

Développeurs

0
1 52
Article Sylvain Guilbaud · Mai 19, 2025 3m read

Bonjour à la communauté,

Exploitez tout le potentiel d'InterSystems IRIS et accompagnez votre équipe dans son intégration grâce à la gamme complète de ressources de formation InterSystems, disponibles en ligne et en présentiel, adaptées à chaque rôle de votre organisation. Les développeurs, administrateurs système, analystes de données et intégrateurs peuvent rapidement se familiariser avec la solution.

Ressources d'intégration pour chaque rôle

Développeurs

0
0 54
Article Lorenzo Scalese · Mars 24, 2025 7m read

Je vais vous montrer comment vous pouvez installer très rapidement sur votre ordinateur un cluster de nœuds InterSystems IRIS en sharding. Dans cet article, mon objectif n'est pas de parler du sharding en détail, ni de définir une architecture de déploiement pour un cas réel, mais de vous montrer comment vous pouvez rapidement installer sur votre machine un cluster d'instances d'IRIS en sharding avec lequel vous pouvez jouer et faire des tests. Si vous souhaitez en savoir plus sur le sharding dans IRIS, vous pouvez consulter la documentation en cliquant ici: clicking here.  

Disons dès le départ que la technologie de sharding d'IRIS va nous permettre de faire deux choses:

  • Définir, charger et consulter des tables fragmentées ou des shards, dont les données seront réparties de manière transparente entre les nœuds du cluster
  • Définir  des tables fédérées, qui offrent une vue globale et composite des données appartenant à des tables différentes et qui, physiquement, sont stockées sur différents nœuds distribués

Donc, comme je l'ai dit, nous laissons le sujet du jeu avec des shards ou des tableaux fédérés pour d'autres articles, et nous nous concentrons maintenant sur l'étape précédente, c'est-à-dire sur la mise en place du cluster de nœuds en sharding.

Pour notre exemple, nous allons utiliser Docker Desktop (for Windows or MacOS) et nous appuyer sur la fonctionnalité d'IRIS: CPF Merge; ou fusion de fichier de configuration; qui nous permet d'utiliser un fichier texte brut dans lequel nous inclurons les sections et propriétés de configuration d'IRIS que nous voulons appliquer pour modifier la configuration actuelle de l'instance d'IRIS. Cette fichier se superpose au fichier  iris.cpf  qui définit la configuration par défaut de l'instance.

Ce merge est automatiquement « activé » lors de l'ajout de la variable d'environnement: ISC_CPF_MERGE_FILE à laquelle  nous devons avoir attribué un chemin valide vers un fichier contenant les sections du fichier cpf que nous voulons modifier. Au démarrage, IRIS vérifie si on lui a demandé de faire une fusion (merge) (en gros, si cette variable d'environnement existe et pointe vers un fichier valide). Si c'est le cas, vous pouvez procéder à la fusion et démarrer.

Je ne fais pas plus de détours et je vous inclus le fichier docker-compose.yml qui fera la magie:

 
docker-compose.yml
services:
  # iris container
  irisnode1:
    init: true 
    hostname: irishost1
    image: shardnode:latest 
    container_name: irisnode1
    build: 
      context: ./cluster
      dockerfile: Dockerfile
    ports:
    - "9991:1972"
    environment: 
    - ISC_DATA_DIRECTORY=/durable/irishost1
    - ISC_CPF_MERGE_FILE=/iris-shared/merge_first_data-node.cpf
    command: 
       --check-caps false --ISCAgent false --key /iris-shared/iris.key -a /iris-shared/configure_first_data-node.sh
    volumes:
    - ./cluster/iris-instance:/iris-shared:delegated
    - ./DDBBs:/durable:delegated

irisnode2: init: true hostname: irishost2 image: shardnode:latest container_name: irisnode2 build: context: ./cluster dockerfile: Dockerfile ports: - "9992:1972" environment: - ISC_DATA_DIRECTORY=/durable/irishost2 - ISC_CPF_MERGE_FILE=/iris-shared/merge_data-node.cpf command: --check-caps false --ISCAgent false --key /iris-shared/iris.key -a /iris-shared/configure_data-node.sh volumes: - ./cluster/iris-instance:/iris-shared - ./DDBBs:/durable depends_on: irisnode1: condition: service_healthy

# conteneur de passerelle web webgateway: image: containers.intersystems.com/intersystems/webgateway:latest-em init: true container_name: webgateway hostname: webgateway ports: - 7772:80 - 7773:443 environment: - ISC_CSP_CONF_FILE=/webgateway-shared/CSP.conf - ISC_CSP_INI_FILE=/webgateway-shared/CSP.ini volumes: - ./webgateway/CSP.conf:/webgateway-shared/CSP.conf - ./webgateway/CSP.ini:/webgateway-shared/CSP.ini

Dans ce cas, nous créons 3 services:

  • irisnode1 - Premier nœud du cluster, qui a un rôle spécial, et c'est pourquoi nous l'appelons spécifiquement node1
  • irisnode2 - Nœud de données supplémentaire du cluster, dont le rôle est data (nous pouvons en avoir autant que nous le voulons)
  • webgateway - Serveur web préconfiguré pour accéder aux instances IRIS (Apache + Webgateway)

Pour créer l'image shardnode:latest, j'ai utilisé le dockerfile suivant:

 
Dockerfile
FROM containers.intersystems.com/intersystems/irishealth:2024.3#FROM containers.intersystems.com/intersystems/iris-community:latest-em#FROM containers.intersystems.com/intersystems/irishealth-arm64:2024.3USER root
WORKDIR /opt/irisapp
RUN chown -R irisowner:irisowner /opt/irisapp
USER irisowner
WORKDIR /opt/irisapp
COPY --chown=irisowner:irisowner src src
COPY --chown=irisowner:irisowner iris.script iris.script
RUN iris start IRIS \
    && iris session IRIS < iris.script \
    && iris stop IRIS quietly

 

Les fichiers utilisés pour effectuer la fusion (merge) pour nodo1 et d'autre cluster IRIS  data nodes sont les suivants:

 
merge_first_data-node.cpf
 
merge_data-node.cpf
# Noeud de données supplémentaires
# 2 GB 8k / 204 MB gmpheap / 64 nodos max
[config]
globals=0,0,2048,0,0,0
gmheap=204800
MaxServerConn=64
MaxServers=64
# Définition d'un nœud de données et son ajout au cluster. Création d'un point de terminaison REST de test (optionnel)
[Actions]
ConfigShardedCluster:ClusterURL=IRIS://irishost1:1972/IRISCLUSTER,Role=data
# CreateApplication:Name=/rest/testapp,MatchRoles=:%ALL,NameSpace=USER,DispatchClass=Test.RESTserver,AutheEnabled=64

 

On pourrait avoir plus de nœuds de type data dans le cluster en ajoutant simplement plus de services avec la même définition que l' irisnode2 (en changeant le nom bien sûr)

D'autre part, pour que l'acheminement fonctionne correctement sur notre serveur web et que nous puissions accéder aux portails d'administration de chacune des instances, nous devons modifier le paramètre CSPConfigName dans chacune d'entre elles, et nous le faisons avec les fichiers: configure_first_data-node.sh y configure_data-node.sh; qui sont identiques dans cet exemple, mais que j'ai laissés différents car, à un moment donné, nous pourrions vouloir effectuer des actions différentes au démarrage de chaque instance d'IRIS, selon qu'il s'agit du node1 ou d'un nœud de type data du cluster.

 
configure_data-node.sh

Je pense que c'est à peu près tout.

Les nœuds pourraient être définis à l'aide de l'API disponible dans la classe %SYSTEM.Cluster  mais la possibilité d'introduire des actions conjointement avec la fonctionnalité CPF Merge simplifie grandement la tâche. Je vous recommande de consulter ce lien, en particulier la section relative à la rubrique the section [Actions].

Pour construire les images et déployer le cluster, nous pourrions construire notre image sharnode:latest et lancer le docker-compose from depuis VS Code. Alternativement, nous pourrions le faire dans notre ligne de commande, à partir du dossier dans lequel nous avons le fichier: docker-compose.yml, en exécutant ces commandes:

docker compose build
docker compose up

Cela prendra un peu de temps la première fois car l'instance marquée comme node1 doit être instanciée avant que tout autre nœud de type data du cluster ne démarre pour la première fois. Mais tout devrait fonctionner et être prêt en une minute ou moins.

Si tout s'est bien passé, vous devriez pouvoir accéder aux portail de gestion de chaque instance avec les URL ci-dessous:

Portail de gestion du nœud de cluster 1 node1http://localhost:7772/irishost1/csp/sys/UtilHome.csp
Portail de gestion du nœud de données datahttp://localhost:7772/irishost2/csp/sys/UtilHome.csp
Accès à la passerelle WebGateway: http://localhost:7772/csp/bin/Systems/Module.cxw

Et voilà! À partir de là, la limite en termes de volume de stockage de bases de données et de taille de tables est déjà fixée par votre hardware. Vous auriez un cluster de nœuds IRIS prêt à définir des tables en sharding ou des tables fédérées.

J'espère que cela vous sera utile!! À bientôt... 

0
0 30
Article Iryna Mykhailova · Août 28, 2024 2m read

Récemment, je me suis retrouvé dans une situation où un utilisateur avait des rôles qui lui accordaient des rôles supplémentaires, etc.

Comme je ne comprenais pas d'où venait une autorisation particulière, j'ai écrit ce code qui obtient un ensemble initial de rôles et les décompresse de manière récursive, en tenant compte des éventuelles répétitions.

0
0 31
Article Pierre LaFay · Jan 3, 2024 8m read

Expérience et retour d'expérience du cours en ligne "Hands-On with InterSystems API Manager for Developers

Avec mes connaissances de base du conteneur Docker et de l'API REST, j'aimerais faire mon premier essai d'utilisation du gestionnaire d'API InterSystems pour prendre le contrôle des API et des microservices. J'ai suivi ce cours en ligne en utilisant mon instance IRIS locale comme hôte (système d'exploitation Windows) et IAM exécuté sur une machine virtuelle Linux (invité).

0
0 75
Article Pierre LaFay · Déc 30, 2023 1m read

Salut !

Récemment, j'ai eu besoin de configurer un serveur FHIR local à l'aide d'IRIS For Health et je pense avoir trouvé le moyen le plus simple et le plus simple qui soit.

Exécutez simplement dans le terminal ces deux lignes ci-dessous :

docker run --rm --name my-iris -d --publish 9091:1972 --publish 9092:52773 intersystemsdc/irishealth-community

et

docker exec -it my-iris iris session iris -U "USER" '##class(%ZPM.PackageManager).Shell("install fhir-server")'

Et vous aurez un serveur FHIR exécuté localement sur http://localhost:9092/fhir/r4.

AUssi simple que ça !

Le serveur FHIR utilisera la dernière version d'InterSystems IRIS for Health Community Edition et déploiera FHIR server from this app via le package IPM dans l'espace de noms FHIRSERVER.

Ceci est pour Mac, alors veuillez ajouter des commentaires sur la façon dont cela fonctionne sous Windows.

Il s'agit d'un article très court car il est très simple de configurer un serveur FHIR local avec InterSystems IRIS for Health et IPM Package Manager.

0
0 100
Article Guillaume Rongier · Nov 30, 2023 10m read

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Flux Git (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab
  • Diffusion continue
  • Installation et configuration de GitLab
  • GitLab CI/CD
0
0 77
Article Guillaume Rongier · Nov 27, 2023 5m read

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Flux Git (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab
  • Diffusion continue
  • Installation et configuration de GitLab
  • GitLab CI/CD

Dans le premier article, nous avons évoqué les notions de base de Git, les raisons pour lesquelles une compréhension approfondie des concepts de Git est importante pour le développement de logiciels modernes et la manière dont Git peut être utilisé pour développer des logiciels.

Dans le deuxième article, nous avons évoqué le flux de travail GitLab - un processus complet du cycle de vie du logiciel ainsi que Diffusion continue.

Dans cet article, nous allons examiner:

  • Installation et configuration de GitLab
  • Connexion de vos environnements à GitLab
0
0 83
Article Guillaume Rongier · Nov 23, 2023 9m read

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Le flux Git (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab
  • Diffusion continue
  • Installation et configuration de GitLab
  • GitLab CI/CD

Dans l'article précédent, nous avons évoqué les notions de base de Git, les raisons pour lesquelles une compréhension approfondie des concepts de Git est importante pour le développement de logiciels modernes et la manière dont Git peut être utilisé pour développer des logiciels. Et bien que nous nous soyons concentrés sur la partie mise en œuvre du développement de logiciels, cette partie présente :

  • Le flux de travail GitLab est un processus complet du cycle de vie d'un logiciel, allant de l'idée au retour utilisateur
  • Diffusion continue est une approche d'ingénierie logicielle dans laquelle les équipes produisent des logiciels en cycles courts, garantissant que le logiciel peut être diffusé de manière fiable à tout moment. Elle vise à créer, tester et publier des logiciels plus rapidement et plus fréquemment.
0
0 157
Article Guillaume Rongier · Nov 20, 2023 7m read

Tout le monde dispose d'un environnement de test.

Certains ont la chance de disposer d'un environnement totalement séparé pour la production.

-- Inconnu

.

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Git flow (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab WorkFlow
  • GitLab CI/CD
  • CI/CD avec des conteneurs

Cette première partie traite de la pierre angulaire du développement logiciel moderne - le système de contrôle de version Git et divers flux Git.

0
0 175
Article Sylvain Guilbaud · Sept 6, 2023 3m read

pour démonter/monter une base de données, utilisez les méthodes Dismount() et Mount() dans la classe SYS.Database disponible dans l'espace de noms %SYS.
NB : l'ID de la base de données est le nom du chemin absolu de son répertoire.

Vous trouverez quelques exemples de démontage/montage et de méthodes contrôlant si une base de données est montée (Mounted=1) ou non (Mounted=0), ou affichant rapidement tous les attributs d'une base de données (via zwrite)

0
0 120
Article Guillaume Rongier · Mai 15, 2023 4m read

Salut à tous !  

Dans cet article, j'aimerais passer en revue les extensions de VS Code que j'utilise moi-même pour travailler avec InterSystems et qui rendent mon travail beaucoup plus pratique. Je suis certain que cet article sera utile à ceux qui commencent tout juste à apprendre les technologies d'InterSystems. Cependant, j'espère également que cet article pourra être utile aux développeurs expérimentés ayant de nombreuses années d'expérience et qu'il leur ouvrira de nouvelles possibilités lors de l'utilisation de VS Code pour le développement.

Je recommande à tous ceux qui travaillent avec InterSystems d'avoir ces extensions installées et, dans cet article, je montrerai comment utiliser certaines d'entre elles.

Vous pouvez en savoir plus sur la fonctionnalité et l'utilisation de chaque extension dans la section Extensions de VS Code, où vous pouvez également télécharger, mettre à jour et désinstaller des extensions :

 Après l'installation, des icônes d'extension apparaissent sur le côté ou en bas de l'éditeur de code.

Extensions obligatoires

Je crois qu'il est logique de commencer notre voyage avec ces extensions de base, sans lesquelles il est impossible de travailler avec InterSystems dans VS Code.

  • L'extension du gestionnaire de serveur d'InterSystems pour VS Code permet de spécifier les connexions au serveur.
  • L'extension ObjectScript d'InterSystems pour VS Code permet l'écriture et la compilation des fichiers de code.
  • L'extension du serveur de langage d'InterSystems pour VS Code permet la mise en œuvre d'un serveur de langage pour ObjectScript, offrant des fonctions de coloration, de complétion de code, d'évaluation de la qualité et bien plus encore.
  • Conjointement, ces extensions offrent aux développeurs un moyen rationalisé de créer, tester et déployer des applications complètes basées sur InterSystems.

    Extensions supplémentaires

    Outre les extensions de base nécessaires, VS Code propose un grand nombre d'autres extensions. Vous pouvez écrire du code sans elles, mais leur utilisation rend le développement plus efficace lorsque vous utilisez n'importe quelle pile technologique, y compris les technologies d'InterSystems. J'en décrirai quelques-unes qui me semblent incontournables.

  • L'extension Docker rend la gestion des projets dockerisés un peu plus facile. Vous pouvez générer automatiquement un fichier Docker pour les projets, exécuter des images et gérer les conteneurs actifs.  
  • Le pilote SQLTools for InterSystems IRIS et SqlTools - sont deux extensions très pratiques qui fonctionnent conjointement. En les utilisant, vous pouvez créer et exécuter les requêtes SQL de la base de données dans VS Code sans avoir à aller dans le portail de gestion et à effectuer des requêtes sql pour interagir avec le contenu des tableaux qui s'y trouvent.
  •  

    Aujourd'hui, il est difficile d'imaginer développer un projet sans utiliser le contrôle de version. Le plus souvent, il s'agit de Git, et le code Visual Studio a un support minimal dès sa sortie de la boîte. Mais si cela ne vous suffit pas, jetez un coup d'œil aux deux extensions suivantes : 

  • Git Graph - montre les branches et leur statut de manière schématique. Ceci est utile dans les situations où vous avez besoin de comprendre rapidement l'état des branches, par exemple lorsqu'elles fusionnent.
  • Git Lens - permet de voir l'historique des modifications apportées à la ligne surlignée et à son auteur.
  •  Il est indispensable au travail d'équipe !

  • EditorConfig - une extension pour améliorer l'apparence du code, elle nécessite l'écriture d'un fichier .editorconfig, dans lequel vous pouvez spécifier tous les paramètres de formatage du code. Il est important de noter que, par défaut, cette fonctionnalité peut être mise en œuvre par l'extension du serveur de langage InterSystems pour VS Code. Pour appliquer le formatage de code ObjectScript standard dans VS Code, vous devez utiliser une combinaison de touches : Windows - [Shift + Alt + F], Mac - [Shift + Option + F], Ubuntu - [Ctrl + Shift + I]. Mais en utilisant le fichier .editorconfig, vous pouvez spécifier votre propre formatage de code pour différents fichiers au sein du projet.
  • Dans cet article, je n'ai abordé que les extensions utilisées par moi-même. Je vous serais reconnaissante de prendre le temps d'écrire dans les commentaires ce qui peut encore être utilisé pour rendre le développement plus pratique. Cet article n'en sera que plus utile !

    0
    0 297
    Article Lorenzo Scalese · Jan 18, 2023 4m read

    Bonjour aux développeurs d'InterSystems !

    Récemment, j'ai mis à jour le modèle FHIR dev template afin qu'il publie maintenant un paquet IPM fhir-server permettant de faire de la configuration du serveur FHIR d'InterSystems une procédure manuelle, automatique ou programmatique triviale d'une seule commande.

    Découvrez ci-dessous comment vous pouvez en bénéficier.

    TLDR

    USER>zpm "install fhir-server"

    Tous les détails ci-dessous.

    Configuration du serveur InterSystems FHIR sans IPM 

    Bien sûr, vous pouvez configurer le serveur InterSystems FHIR sans utiliser le gestionnaire de paquets IPM. Vous avez le choix :

    1. Vous pouvez configurer un serveur FHIR en nuage et l'essayer pendant plusieurs jours en suivant les instructions suivantes. Il s'agira d'un serveur FHIR d'InterSystems dans le nuage AWS.

    2. Vous pouvez configurer le serveur FHIR d'InterSystems en exécutant InterSystems IRIS for Health en suivant les étapes suivantes.

    3. Vous pouvez également cloner git le dépôt de ce modèle et l'exécuter dans un répertoire cloné :

    $ docker-compose up -d

    pour que le serveur FHIR d'InterSystems fonctionne sur votre ordinateur portable.

    Ce que je suggère dans l'article est le point 2 où vous pouvez sauter toutes les étapes manuelles et avoir le serveur FHIR en marche sur un ordinateur portable IRIS soit dans Docker soit dans l'OS hôte.

    **Configuration du serveur FHIR avec IPM **

    AVIS DE NON-RESPONSABILITÉ ! Les étapes décrites ci-dessous se rapportent à une instance d'IRIS for Health récemment installée ou à une utilisation avec des images Docker. Le paquet crée un nouvel espace de noms et une nouvelle application Web, ce qui pourrait nuire à la configuration précédente.

    IPM est l'acronyme anglais pour InterSystems Package manager, précédemment connu sous le nom de ZPM. Vérifiez que [IPM-client est installé] (https://openexchange.intersystems.com/package/InterSystems-Package-Manager-1). Vous pouvez le vérifier en exécutant la commande zpm dans le terminal IRIS et en obtenant le résultat suivant :

    IRISAPP>zpm     
    
    =============================================================================
    || Welcome to the Package Manager Shell (ZPM).                             ||
    || Enter q/quit to exit the shell. Enter ?/help to view available commands ||
    =============================================================================
    zpm:IRISAPP>

    Vous aurez besoin d'IRIS for Health pour les versions 2022.x et plus récentes.  

    Comment exécuter iris for health sur votre ordinateur portable ?

    Exécution d'une opération hôte

    Téléchargez la version la plus récente d'IRIS for Health sur le [site d'évaluation d'InterSystems] (https://evaluation.intersystems.com/Eval/index.html) qui correspond à votre plate-forme (Windows, Mac, Linux) et installez-la. Installez ZPM. Voici un exemple :

    USER>zn "%SYS" d ##class(Security.SSLConfigs).Create("z") s r=##class(%Net.HttpRequest).%New(),r.Server="pm.community.intersystems.com",r.SSLConfiguration="z" d r.Get("/packages/zpm/latest/installer"),$system.OBJ.LoadStream(r.HttpResponse.Data,"c")

    Exécution d'une version docker

    Appelez votre terminal pour le lancement :

    docker run --rm --name iris4h -d --publish 9091:1972 --publish 9092:52773 intersystemsdc/irishealth-community

    Puis lancez le terminal :

    docker exec -it iris4h iris session IRIS

    Installation du serveur FHIR

    Après avoir fait fonctionner IRIS sur l'hôte ou simplement dans le terminal IRIS :

    USER>zpm "install fhir-server"

    Cela installera le serveur FHIR dans l'espace de noms FHIRSERVER avec des paramètres :

    Set appKey = "/fhir/r4"
    Set strategyClass = "HS.FHIRServer.Storage.Json.InteractionsStrategy"
    set metadataPackages = $lb("hl7.fhir.r4.core@4.0.1")
    
    Set metadataConfigKey = "HL7v40"

    L'API REST FHIR sera disponible ici : http://yourserver/fhir/r4.

    Il ajoutera également quelques données synthétiques.

    Comment comprendre que le serveur fonctionne ?

    Pour tester la version hôte :

    http://localhost:52773/fhir/r4/metadata

    Pour tester la version docker :

    http://localhost:9092/fhir/r4/metadata

    zpm installe également l'interface utilisateur simple qui est disponible à l'adresse suivante : yourserver/fhirUI/FHIRAppDemo.html.

    Et vous verrez apparaître quelque chose comme ceci (avec le patient id=1 entré) :

    Comment ça marche ?

    En fait, vous pouvez observer ce qui est installé avec ce module ZPM dans le scénario suivant following module.xml. On peut voir qu'il importe du code, installe l'application frontale de démonstration fhirUI, exécute le script de post-installation, qui appelle la méthode suivante. Le script de la méthode effectue la configuration du serveur FHIR.

    Installation programmatique du serveur FHIR

    Vous pouvez également l'installer de manière programmatique en utilisant la commande suivante :

    set sc=$zpm("install fhir-server")

    Joyeux codage FHIR !

    0
    0 64
    Article Irène Mykhailova · Oct 5, 2022 5m read

    Salut la communauté,

    Souhaitez-vous bénéficier de soutien, discuter d'une fonctionnalité intéressante, faire une annonce ou partager vos connaissances ? Dans cet article, nous allons vous expliquer comment faire tout cela.

    Pour faciliter la navigation dans ce "mode d'emploi", suivez simplement le contenu :

    Instructions générales

    Pour commencer, il faut cliquer sur le bouton "Nouveau message" dans le menu principal du site de la Communauté des développeurs :

    Ensuite, vous verrez apparaître l'éditeur qui vous donnera le choix de créer une Question, une Annonce, un Article, ou une Discussion. Les différents types de messages ont leurs propres ensembles de champs obligatoires et facultatifs. 

    Tout d'abord, parlons des champs communs à tous les types de messages, pour ensuite passer aux particularités.

    En principe, chaque message comporte un titre (Title*), un corps (Body*), un groupe (Group*), des balises et quelques options supplémentaires permettant d'ajouter un sondage ou de joindre un ou plusieurs fichiers PDF. Tous les champs de texte marqués d'un astérisque (*) sont obligatoires. Tout d'abord, vous devez choisir le type de message, par exemple, une Question, une Annonce, un Article ou une Discussion.

    Ensuite, veuillez formuler l'idée principale de votre question de la manière la plus précise et la plus concrète possible et la noter sous forme de titre : Title.  

    Ensuite, dans le champ Corps, vous écrivez ce que vous voulez partager avec les autres. Vous avez le choix entre deux options pour rédiger le texte de votre post. Vous pouvez utiliser l'éditeur WYSIWYG ou Markdown. Bien entendu, le résultat sera le même dans les deux cas.

     

    vs. 

    Une fois que vous avez fini de rédiger le texte, vous devez choisir le champ Groupe, qui correspond généralement à la technologie, au produit ou au service fourni par InterSystems. 

    Après le champ Groupe, voici le champ Tags où vous pouvez ajouter des balises liées au contenu de votre message. Il y a pas mal de balises, donc il faut les choisir de manière responsable car d'autres personnes utilisent ces balises pour chercher ou trier les informations en cas de recherche.

    Sous les balises, il y a un lien pour voir plus d'options. Il est possible d'y attacher un document pdf Attach a pdf document (par exemple, l'horaire de l'événement au format pdf) et de fournir le nom que vous souhaitez voir apparaître.

    Une autre chose que vous pouvez faire par le biais de plus d'options, c'est le champ "Ajouter un questionnaire" Add a poll. Remplissez les champs avec une question, des réponses possibles, choisissez la durée, etc.

    Une fois que vous avez terminé, vous pouvez prévisualiser Preview votre message pour voir à quoi il ressemblera pour les autres, vous pouvez le sauvegarder Save pour le modifier plus tard, ou le publier Publish immédiatement.

    En outre, vous pouvez programmer la publication de votre message. Il suffit de cliquer sur la flèche vers le bas, de choisir le champ "Programmer le message" Schedule post, puis de définir la date et l'heure..

     

    Une fois que tout est prêt, il suffit de cliquer sur "Programmer le message" (Schedule post) et c'est tout! 

    Il s'agit essentiellement de la fonctionnalité commune de création d'un message.

    Question

    D'après le nom qu'il porte, il est évident que vous devriez choisir ce type de message si vous avez besoin de l'aide de quelqu'un. Ici, dans la Communauté des développeurs, il y a beaucoup de spécialistes et quelqu'un a peut-être déjà été confronté à la même situation. N'hésitez donc pas à poser des questions ou à y répondre ;)

    Pour demander de l'aide, veuillez formuler l'idée principale de votre question et la noter sous forme de titre. Ensuite, veuillez sélectionner la version du produit Product version que vous utilisez, car les différentes versions ont des fonctionnalités et des classes différentes et certains conseils pourraient être utiles pour certaines versions et inutiles pour d'autres.

    Pour être encore plus précis, vous pouvez fournir une version complète que vous utilisez actuellement dans la zone de texte $ZV. Pour obtenir votre version complète, vous pouvez ouvrir Terminal et exécuter la commande :

    write $ZV

      

    La même chose peut être faite dans l'EDI que vous utilisez ou vous pouvez le voir dans le portail de gestion :

    Les autres champs sont les mêmes que ceux décrits précédemment.

    Article ou annonce

    Pour partager vos connaissances ou faire une annonce, vous devez choisir un type de message Article ou Annonce respectivement. Ces types de messages, en plus des champs communs, ont également des champs supplémentaires. Il s'agit du Message précédent, le Message suivant, et du Lien de demande d'échange ouvert.

    Donc, en résumé, si cet article/cette annonce (ou une branche d'une discussion) est lié(e) à un autre, vous pouvez ajouter le lien dans le champ Article précédent (Previous post), et, par conséquent, les autres membres de la communauté verront le bloc Articles connexes suivant à la fin de l'article

    Vous n'avez pas besoin d'ouvrir le message précédent et d'y ajouter le lien vers un message suivant, cette opération est effectuée automatiquement.

    Si votre message est lié à un projet sur Open Exchange, vous pouvez ajouter le lien vers ce projet dans un champ correspondant.

    Discussion

    Pour entamer une conversation sur une des fonctionnalités ou partager votre expérience de l'utilisation de la technologie et demander un retour d'information, vous pouvez lancer une Discussion. Ce type de message comporte tous les champs communs ainsi que les liens vers le Message précédent et Message suivant.

    Et voilà !

    C'est ce que vous devez savoir pour commencer un nouveau fil de discussion sur la Communauté. Bonne chance !

    Et nous avons hâte de connaître vos impressions ;)

    0
    0 76
    Annonce Irène Mykhailova · Sept 24, 2022

    Si vous êtes sur le point d'apprendre InterSystems ObjectScript, nous rendons la décision beaucoup plus facile.

    Nous venons de mettre à jour le parcours d'apprentissage " Premiers pas avec InterSystems ObjectScript " avec 3 nouvelles vidéos de 5 minutes - et un exercice de synthèse pour vous aider à rassembler tout ce que vous apprendrez.

    🤝 Obtenez une introduction à InterSystems ObjectScript

    🤿 Plongez plus profondément dans les commandes et les fonctions

    🤔 Comprendre les types de données et les variables

    👨‍💻 Créer une définition de classe

    Faites tout cela dans notre parcours d'apprentissage mis à jour, Premiers pas avec InterSystems ObjectScript.

    0
    0 61
    Article Irène Mykhailova · Juil 1, 2022 1m read

    Vous connaissez plusieurs langues et souhaitez partager vos connaissances avec des utilisateurs de différentes régions du monde qui ne parlent pas français ?

    C'est maintenant à vous de briller ! 🤩

    Avec notre communauté de développeurs, c'est facile de lier votre article original et sa traduction dans une autre langue (ou même de demander une traduction).

    Parlons donc de la création de votre propre traduction :

    0
    0 83
    Article Lorenzo Scalese · Juin 13, 2022 19m read

    Une session concurrente dans IRIS : SQL, Objects, REST, et GraphQL  

    Kazimir Malevitch, "Athlètes" (1932) 

    "Mais bien sûr, vous ne comprenez pas ! Comment celui qui a toujours voyagé en calèche peut-il comprendre les sentiments et les impressions du voyageur en express ou du pilote dans les airs ?"

    Kazimir Malevich (1916)

    Introduction

    Nous avons déjà abordé le sujet des raisons pour lesquelles la représentation objet/type est préférable à SQL pour la mise en œuvre des modèles de domaine. Et ces conclusions et ces faits sont aussi vrais aujourd'hui qu'ils l'ont toujours été. Alors pourquoi devrions-nous faire un pas en arrière et discuter des technologies qui ramènent les abstractions au niveau global, où elles se trouvaient à l'ère pré-objet et pré-type ? Et pourquoi devrions-nous encourager l'utilisation d'un code spaghetti, qui donne lieu à des bogues difficiles à repérer et qui ne repose que sur les compétences virtuoses des développeurs ?

    Plusieurs arguments sont favorables à la transmission de données via des API basées sur SQL/REST/GraphQL plutôt qu'à leur représentation sous forme de types/objects:

    0
    0 499
    Article Guillaume Rongier · Avr 6, 2022 10m read

    Dans les parties précédentes (1 et 2) nous avons parlé des globales en tant qu'arbres. Dans cet article, nous allons les considérer comme des listes éparses.

    Une liste éparse - est un type de liste où la plupart des valeurs ont une valeur identique.

    En pratique, vous verrez souvent des listes éparses si volumineuses qu'il est inutile d'occuper la mémoire avec des éléments identiques. Il est donc judicieux d'organiser les listes éparses de telle sorte que la mémoire ne soit pas gaspillée pour stocker des valeurs en double.

    Dans certains langages de programmation, les listes éparses font partie intégrante du langage - par exemple, in J, MATLAB. Dans d'autres langages, il existe des bibliothèques spéciales qui vous permettent de les utiliser. Pour le C++, il s'agit de Eigen et d'autres bibliothèques de ce type.

    Les globales sont de bons candidats pour la mise en œuvre de listes éparses pour les raisons suivantes :

    1. Ils stockent uniquement les valeurs de nœuds particuliers et ne stockent pas les valeurs indéfinies ;

    2. L'interface d'accès à une valeur de nœud est extrêmement similaire à ce que de nombreux langages de programmation proposent pour accéder à un élément d'une liste multidimensionnelle.   Set ^a(1, 2, 3)=5 Write ^a(1, 2, 3)

    3. Une structure globale est une structure de niveau assez bas pour le stockage des données, ce qui explique pourquoi les globales possèdent des caractéristiques de performance exceptionnelles (des centaines de milliers à des dizaines de millions de transactions par seconde selon le matériel, voir 1)

    Puisqu'une globale est une structure persistante, il n'est logique de créer des listes éparses sur leur base que dans les situations où vous savez à l'avance que vous disposerez de suffisamment de mémoire pour elles.   L'une des nuances de la mise en œuvre des listes éparses est le retour d'une certaine valeur par défaut si vous vous adressez à un élément indéfini.

    Ceci peut être mis en œuvre en utilisant la fonction $GET dans COS. Prenons l'exemple d'une liste tridimensionnelle.

    SET a = $GET(^a(x,y,z), defValue)

    Quel type de tâches nécessite des listes éparses et comment les globales peuvent-elles vous aider ?

    Matrice d'adjacence

    Ces matrices sont utilisées pour la représentation des graphiques :

    Il est évident que plus un graphe est grand, plus il y aura de zéros dans la matrice. Si nous regardons le graphe d'un réseau social, par exemple, et que nous le représentons sous la forme d'une matrice de ce type, il sera principalement constitué de zéros, c'est-à-dire qu'il s'agira d'une liste éparse.

    Set ^m(id1, id2) = 1
    Set ^m(id1, id3) = 1
    Set ^m(id1, id4) = 1
    Set ^m(id1) = 3
    Set ^m(id2, id4) = 1
    Set ^m(id2, id5) = 1
    Set ^m(id2) = 2
    ....
    

    Dans cet exemple, nous allons sauvegarder la matrice d'adjacence dans le ^m globale, ainsi que le nombre d'arêtes de chaque nœud (qui est ami et avec qui et le nombre d'amis).

    Si le nombre d'éléments du graphique ne dépasse pas 29 millions (ce nombre est calculé comme 8 * longueur maximale de la chaîne), il existe même une méthode plus économique pour stocker de telles matrices - les chaines binaires, car elles optimisent les grands espaces d'une manière spéciale.

    Les manipulations de chaînes binaires sont effectuées à l'aide de la fonction $BIT.

    ; setting a bit
    SET $BIT(rowID, positionID) = 1
    ; getting a bit
    Write $BIT(rowID, positionID)
    

    Tableau des commutateurs FSM

    Le graphe des commutateurs FSM étant un graphe régulier, le tableau des commutateurs FSM est essentiellement la même matrice d'adjacence dont nous avons parlé précédemment.

    Automates cellulaires

    L'automate cellulaire le plus célèbre est le jeu "Life", dont les règles (lorsqu'une cellule a de nombreux voisins, elle meurt) en font essentiellement une liste éparse.

    Stephen Wolfram estime que les automates cellulaires représentent un nouveau domaine de la science. En 2002, il a publié un livre de 1280 pages intitulé "A New Kind of Science", dans lequel il affirme que les réalisations dans le domaine des automates cellulaires ne sont pas isolées, mais sont plutôt stables et importantes pour tous les domaines de la science.

    Il a été prouvé que tout algorithme qui peut être traité par un ordinateur peut également être mis en œuvre à l'aide d'un automate cellulaire. Les automates cellulaires sont utilisés pour simuler des environnements et des systèmes dynamiques, pour résoudre des problèmes algorithmiques et à d'autres fins.

    Si nous avons un champ considérable et que nous devons enregistrer tous les états intermédiaires d'un automate cellulaire, il est logique d'utiliser les globales.

    Cartographie

    La première chose qui me vient à l'esprit lorsqu'il s'agit d'utiliser des listes éparses est la cartographie.

    En règle générale, les cartes comportent beaucoup d'espace vide. Si nous imaginons que la carte du monde est composée de grands pixels, nous verrons que 71 % de tous les pixels de la Terre seront occupés par le réseau creux de l'océan. Et si nous ajoutons uniquement des structures artificielles à la carte, il y aura plus de 95 % d'espace vide.

    Bien sûr, personne ne stocke les cartes sous forme de tableaux bitmap, tout le monde utilise plutôt la représentation vectorielle.
    Mais en quoi consistent les cartes vectorielles ? C'est une sorte de cadre avec des polylignes et des polygones.
    En fait, il s'agit d'une base de données de points et de relations entre eux.

    L'une des tâches les plus difficiles en cartographie est la création d'une carte de notre galaxie réalisée par le télescope Gaia. Au sens figuré, notre galaxie est un gigantesque réseau creux : d'immenses espaces vides avec quelques points lumineux occasionnels - des étoiles. C'est 99,999999.......% d'espace absolument vide. Caché, une base de données basée sur des globales, a été choisie pour stocker la carte de notre galaxie.

    Je ne connais pas la structure exacte des globales dans ce projet, mais je peux supposer que c'est quelque chose comme ça :

    Set ^galaxy(b, l, d) = 1; le numéro de catalogue de l'étoile, s'il existe
    Set ^galaxy(b, l, d, "name") = "Sun"
    Set ^galaxy(b, l, d, "type") = "normal" ; les autres options peuvent inclure un trou noir, quazar, red_dwarf et autres.
    Set ^galaxy(b, l, d, "weight") = 14E50
    Set ^galaxy(b, l, d, "planetes") = 7
    Set ^galaxy(b, l, d, "planetes", 1) = "Mercure"
    Set ^galaxy(b, l, d, "planetes", 1, weight) = 1E20
    ...
    

    Où b, l, d représententcoordonnées galactiques: la latitude, la longitude et la distance par rapport au Soleil.

    La structure flexible des globales vous permet de stocker toutes les caractéristiques des étoiles et des planètes, puisque les bases de données basées sur les globales sont exemptes de schéma.

    Caché a été choisi pour stocker la carte de notre univers non seulement en raison de sa flexibilité, mais aussi grâce à sa capacité à sauvegarder rapidement un fil de données tout en créant simultanément des globales d'index pour une recherche rapide.

    Si nous revenons à la Terre, les globales ont été utilisées dans des projets axés sur les cartes comme OpenStreetMap XAPI et FOSM, un branchement d'OpenStreetMap.

    Récemment, lors d'un hackathon Caché, un groupe de développeurs a mis en œuvre des index géospatiaux en utilisant cette technologie. Pour plus de détails, consultez l'article.

    Mise en œuvre d'index géospatiaux à l'aide de globales dans OpenStreetMap XAPI

    Les illustrations sont tirées de cette présentation.

    Le globe entier est divisé en carrés, puis en sous-carrés, puis en encore plus de sous-carrés, et ainsi de suite. Au final, nous obtenons une structure hiérarchique pour laquelle les globales ont été créées.

    À tout moment, nous pouvons instantanément demander n'importe quelle case ou la vider, et toutes les sous-carrés seront également retournées ou vidées.

    Un schéma détaillé basé sur les globales peut être mis en œuvre de plusieurs façons.

    Variante 1:

    Set ^m(a, b, a, c, d, a, b,c, d, a, b, a, c, d, a, b,c, d, a, 1) = idPointOne
    Set ^m(a, b, a, c, d, a, b,c, d, a, b, a, c, d, a, b,c, d, a, 2) = idPointTwo
    ...

    Variante 2:

    Set ^m('abacdabcdabacdabcda', 1) = idPointOne
    Set ^m('abacdabcdabacdabcda', 2) = idPointTwo
    ...

    Dans les deux cas, il ne sera pas très difficile dans COS/M de demander des points situés dans un carré de n'importe quel niveau. Il sera un peu plus facile de dégager des segments d'espace carrés de n'importe quel niveau dans la première variante, mais cela est rarement nécessaire.

    Un exemple de carré de bas niveau :

    Et voici quelques globales du projet XAPI : représentation d'un index basé sur des globales :

    La globale ^voie est utilisé pour stocker les sommets des polylines (routes, petites rivières, etc.) et des polygones (zones fermées : bâtiments, bois, etc.).

    Une classification approximative de l'utilisation des listes éparses dans les globales.

    1. Nous stockons les coordonnées de certains objets et leur état (cartographie, automates cellulaires).
    2. Nous stockons des matrices creuses.

    Dans la variante 2), lorsqu'une certaine coordonnée est demandée et qu'aucune valeur n'est attribuée à un élément, nous devons obtenir la valeur par défaut de l'élément de la liste éparse.

    Les avantages que nous obtenons en stockant des matrices multidimensionnelles dans les globales

    Suppression et/ou sélection rapide de segments d'espace qui sont des multiples de chaînes, de surfaces, de cubes, etc. Pour les cas avec des index intégraux, il peut être pratique de pouvoir supprimer et/ou sélectionner rapidement des segments d'espace qui sont des multiples de chaînes, de surfaces, de cubes, etc.

    La commande Kill permet de supprimer un élément autonome, une chaîne de caractères et même une surface entière. Grâce aux propriétés de la globale, elle se produit très rapidement, mille fois plus vite que la suppression élément par élément.

    L'illustration montre un tableau tridimensionnel dans la globale ^a et différents types d'enlèvements.

    Pour sélectionner des segments d'espace par des indices connus, vous pouvez utiliser la commande Merge.

    Sélection d'une colonne de la matrice dans la colonne Variable :

    ; Définissons un tableau tridimensionnel creux 3x3x3
    Set ^a(0,0,0)=1,^a(2,2,0)=1,^a(2,0,1)=1,^a(0,2,1)=1,^a(2,2,2)=1,^a(2,1,2)=1
    Colonne de fusion = ^a(2,2)
    ; Produisons la colonne Variable
    Zwrite colonne
    

    Produit :

    Column(0)=1
    Colonne(2)=1
    

    Ce qui est intéressant, c'est que nous avons obtenu un tableau épars dans la colonne Variable que vous pouvez adresser via $GET puisque les valeurs par défaut ne sont pas stockées ici.

    La sélection de segments d'espace peut également se faire à l'aide d'un petit programme utilisant la fonction $Order. Ceci est particulièrement utile pour les espaces dont les indices ne sont pas quantifiés (cartographie).

    Conclusion

    Les réalités d'aujourd'hui posent de nouveaux défis. Les graphes peuvent comporter des milliards de sommets, les cartes peuvent avoir des milliards de points, certains peuvent même vouloir lancer leur propre univers basé sur des automates cellulaires (1, 2).

    Lorsque le volume de données dans les listes éparses ne peut pas être comprimé dans la RAM, mais que vous devez quand même travailler avec elles, vous devriez envisager de mettre en œuvre de tels projets en utilisant des globales et des COS.

    Clause de non-responsabilité :: cet article et les commentaires le concernant reflètent uniquement mon opinion et n'ont rien à voir avec la position officielle de la société d'InterSystems.
    0
    0 116
    Article Guillaume Rongier · Avr 4, 2022 13m read

    3. Variantes des structures lors de l'utilisation de globales

    Une structure, telle qu'un arbre ordonné, présente plusieurs cas particuliers. Examinons ceux qui ont une valeur pratique pour le travail avec les globales.

    3.1 Cas particulier 1. Un nœud sans branches

    Les globales peuvent être utilisées non seulement comme une liste de données, mais aussi comme des variables ordinaires. Par exemple, pour créer un compteur :  

    Set ^counter = 0  ; setting counter
    Set id=$Increment(^counter) ;  atomic incrementation
    

    En même temps, une globale peut avoir des branches outre sa valeur. L'un n'exclut pas l'autre.

    3.2 Cas particulier 2. Un nœud et plusieurs branches

    En fait, il s'agit d'une base classique clé-valeur. Et si nous enregistrons des tuples de valeurs au lieu de valeurs, nous obtiendrons une table ordinaire avec une clé primaire.

    Afin d'implémenter une table basé sur des globales, nous devrons former des chaînes de caractères à partir des valeurs des colonnes, puis les enregistrer dans une globale par la clé primaire. Afin de pouvoir diviser la chaîne en colonnes lors de la lecture, nous pouvons utiliser ce qui suit :

    1. Caractère de délimitation.
    Set ^t(id1) = "col11/col21/col31"
    Set ^t(id2) = "col12/col22/col32"
    1. Un schéma fixe, dans lequel chaque champ occupe un nombre particulier d'octets. C'est ainsi qu'on procède généralement dans les bases de données relationnelles.

    2. Une fonction spéciale $LB (introduite dans Caché) qui compose une chaîne de caractères à partir de valeurs.

    Set ^t(id1) = $LB("col11", "col21", "col31")
    Set ^t(id2) = $LB("col12", "col22", "col32")

    Ce qui est intéressant, c'est qu'il n'est pas difficile de faire quelque chose de similaire aux clés étrangères dans les bases de données relationnelles en utilisant des globales. Appelons ces structures des index globaux. Un index global est un arbre supplémentaire permettant d'effectuer des recherches rapides sur des champs qui ne font pas partie intégrante de la clé primaire de la globale principale. Vous devez écrire un code supplémentaire pour le remplir et l'utiliser.

    Nous créons un index global basé sur la première colonne.

    Set ^i("col11", id1) = 1
    Set ^i("col12", id2) = 1

    Pour effectuer une recherche rapide par la première colonne, vous devrez regarder dans la ^i globale et trouver les clés primaires (id) correspondant à la valeur nécessaire dans la première colonne.

    Lors de l'insertion d'une valeur, nous pouvons créer à la fois des valeurs et des index globaux pour les champs nécessaires. Pour plus de fiabilité, nous allons l'intégrer dans une transaction.

    TSTART
    Set ^t(id1) = $LB("col11", "col21", "col31")
    Set ^i("col11", id1) = 1
    TCOMMIT

    Plus d'informations sont disponibles ici making tables in M using globals and emulation of secondary keys.

    Ces tables fonctionneront aussi rapidement que dans les bases de données traditionnelles (ou même plus rapidement) si les fonctions d'insertion/mise à jour/suppression sont écrites en COS/M et compilées.

    J'ai vérifié cette affirmation en appliquant un grand nombre d'opérations INSERT et SELECT à une seule table à deux colonnes, en utilisant également les commandes TSTART et TCOMMIT (transactions).

    Je n'ai pas testé de scénarios plus complexes avec des accès concurrents et des transactions parallèles.

    Sans utiliser de transactions, la vitesse d'insertion pour un million de valeurs était de 778 361 insertions/seconde.

    Pour 300 millions de valeurs, la vitesse était de 422 141 insertions/seconde.

    Lorsque des transactions ont été utilisées, la vitesse a atteint 572 082 insertions/seconde pour 50 millions de valeurs. Toutes les opérations ont été exécutées à partir du code M compilé. J'ai utilisé des disques durs ordinaires, pas des SSD. RAID5 avec Write-back. Le tout fonctionnant sur un processeur Phenom II 1100T.

    Pour effectuer le même test pour une base de données SQL, il faudrait écrire une procédure stockée qui effectuerait les insertions en boucle. En testant MySQL 5.5 (stockage InnoDB) avec la même méthode, je n'ai jamais obtenu plus de 11K insertions par seconde.

    En effet, l'implémentation de tables avec des globales est plus complexe que de faire la même chose dans des bases de données relationnelles. C'est pourquoi les bases de données industrielles basées sur les globales ont un accès SQL pour simplifier le travail avec les données tabulaires.

    En général, si le schéma de données ne change pas souvent, que la vitesse d'insertion n'est pas critique et que l'ensemble de la base de données peut être facilement représenté par des tables normalisées, il est plus facile de travailler avec SQL, car il offre un niveau d'abstraction plus élevé.

    Dans ce cas, je voulais montrer que les globales peuvent être utilisées comme un constructeur pour créer d'autres bases de données. Comme le langage assembleur qui peut être utilisé pour créer d'autres langages. Et voici quelques exemples d'utilisation des globales pour créer des contreparties de key-values, lists, sets, tabular, document-oriented DB's.

    Si vous devez créer une base de données non standard avec un minimum d'efforts, vous devriez envisager d'utiliser les globales.

    3.3 Cas particulier 3. Un arbre à deux niveaux dont chaque nœud de deuxième niveau a un nombre fixe de branches

    Vous l'avez probablement deviné : il s'agit d'une implémentation alternative des tables utilisant des globales. Comparons-la avec la précédente.

    <th>
      Pros
    </th>
    
    <td>
      Un accès plus rapide aux valeurs de certaines colonnes, puisque vous n'avez pas besoin d'analyser la chaîne de caractères. D'après mes tests, c'est 11,5 % plus rapide pour 2 colonnes et encore plus rapide pour plus de colonnes. Il est plus facile de modifier le schéma de données et de lire le code.
    </td>
    
    Tables dans un arborescence deux niveaux vs. Tables dans un arborescence mono niveau.
    Cons
    Insertions plus lentes, car le nombre de nœuds doit être égal au nombre de colonnes. Une plus grande consommation d'espace sur le disque dur, car les index globaux (comme les index de table) avec les noms de colonne occupent de l'espace sur le disque dur et sont dupliqués pour chaque ligne.  

    Conclusion: Rien d'extraordinaire. Les performances étant l'un des principaux avantages des globales, il n'y a pratiquement aucun intérêt à utiliser cette approche, car il est peu probable qu'elle soit plus rapide que les tables ordinaires des bases de données relationnelles.

    3.4 Cas général. Arbres et clés ordonnées

    Toute structure de données qui peut être représentée comme un arbre s'adapte parfaitement aux globales.

    3.4.1 Objets avec des sous-objets

    C'est dans ce domaine que les globales sont traditionnellement utilisées. Il existe de nombreuses maladies, médicaments, symptômes et méthodes de traitement dans le domaine médical. Il est irrationnel de créer une table avec un million de champs pour chaque patient, d'autant plus que 99% d'entre eux seront vides.

    Imaginez une base de données SQL composée des tables suivants : " Patient " ~ 100 000 champs, " Médicament " 100 000 champs, " Thérapie " 100 000 champs, " Complications " 100 000 champs et ainsi de suite. Comme alternative, vous pouvez créer une BD avec des milliers de tableaux, chacun pour un type de patient particulier (et ils peuvent aussi se superposer !), un traitement, un médicament, ainsi que des milliers de tables pour les relations entre ces tables.

    Les globales s'adaptent parfaitement aux soins de santé, puisqu'elles permettent à chaque patient de disposer d'un dossier complet, de la liste des thérapies, des médicaments administrés et de leurs effets, le tout sous la forme d'un arbre, sans gaspiller trop d'espace disque en colonnes vides, comme ce serait le cas avec les bases de données relationnelles.

    Les globales fonctionnent bien pour les bases de données contenant des données personnelles, lorsque la tâche consiste à accumuler et à systématiser le maximum de données personnelles diverses sur un client. C'est particulièrement important dans les domaines de la santé, de la banque, du marketing, de l'archivage et autres.

    Il est évident que SQL permet également d'émuler un arbre en utilisant seulement quelques tables (EAV, 1,2,3,4,5,6, 7,8), mais c'est beaucoup plus complexe et plus lent. En fait, nous devrions écrire une globale basé sur des tables et cacher toutes les routines liées aux tables sous une couche d'abstraction. Il n'est pas correct d'émuler une technologie de niveau inférieur (les globales) à l'aide d'une technologie de niveau supérieur (SQL). C'est tout simplement injustifié.

    Ce n'est pas un secret que la modification d'un schéma de données dans des tableaux gigantesques (ALTER TABLE) peut prendre un temps considérable. MySQL, par exemple, effectue l'opération ALTER TABLE ADD|DROP COLUMN en copiant toutes les données de l'ancienne tableau vers la nouvelle (je l'ai testé sur MyISAM et InnoDB). Cela peut bloquer une base de données de production contenant des milliards d'enregistrements pendant des jours, voire des semaines.

    Si nous utilisons des globales, la modification de la structure des données ne nous coûte rien Nous pouvons ajouter de nouvelles propriétés à n'importe quel objet, à n'importe quel niveau de la hiérarchie et à n'importe quel moment. Les changements qui nécessitent de renommer les branches peuvent être appliqués en arrière-plan avec la base de données en fonctionnement.


    Par conséquent, lorsqu'il s'agit de stocker des objets comportant un grand nombre de propriétés facultatives, les globales fonctionnent parfaitement.

    Je vous rappelle que l'accès à l'une des propriétés est instantané, puisque dans une globale, tous les chemins sont un B-Arbre.

    Dans le cas général, les bases de données basées sur des globales sont un type de bases de données orientées documents qui supportent le stockage d'informations hiérarchiques. Par conséquent, les bases de données orientées documents peuvent concurrencer efficacement les globales dans le domaine du stockage des cartes médicales.

    Mais ce n'est pas encore le cas.

    Prenons MongoDB, par exemple. Dans ce champ, il perd face aux globales pour les raisons suivantes :
    1. Taille du document. L'unité de stockage est un texte au format JSON (BSON, pour être exact) dont la taille maximale est d'environ 16 Mo. Cette limitation a été introduite dans le but de s'assurer que la base de données JSON ne devienne pas trop lente lors de l'analyse syntaxique, lorsqu'un énorme document JSON y est enregistré et que des valeurs de champ particulières sont traitées. Ce document est censé contenir des informations complètes sur un patient. Nous savons tous à quel point les cartes de patient peuvent être épaisses. Si la taille maximale de la carte est plafonnée à 16 Mo, cela permet de filtrer immédiatement les patients dont les cartes contiennent des IRM, des radiographies et d'autres documents. Une seule branche d'une entreprise mondiale peut contenir des gigaoctets, des pétaoctets ou des téraoctets de données. Tout est dit, mais laissez-moi vous en dire plus.
    2. Le temps nécessaire à la création/modification/suppression de nouvelles propriétés de la carte du patient. Une telle base de données devrait copier la carte entière dans la mémoire (beaucoup de données !), analyser les données BSON, ajouter/modifier/supprimer le nouveau nœud, mettre à jour les index, remballer le tout en BSON et sauvegarder sur le disque. Une globale n'aurait besoin que d'adresser la propriété nécessaire et d'effectuer l'opération nécessaire.
    3. La vitesse d'accès à des propriétés particulières. Si le document possède de nombreuses propriétés et une structure à plusieurs niveaux, l'accès à des propriétés particulières sera plus rapide car chaque chemin dans la globale est le B-Arbre. En BSON, vous devrez analyser linéairement le document pour trouver la propriété nécessaire.

    3.3.2 Tables associatives

    Les tables associatives (même avec les tables imbriquées) fonctionnent parfaitement avec les globales. Par exemple, cette table PHP ressemblera à la première illustration en 3.3.1.

    $a = array(
      "name" => "Vince Medvedev",
      "city" => "Moscow",
      "threatments" => array(
        "surgeries" => array("apedicectomy", "biopsy"),
        "radiation" => array("gamma", "x-rays"),
        "physiotherapy" => array("knee", "shoulder")
      )
    );

    3.3.3 Documents hiérarchiques : XML, JSON

    Ils peuvent également être facilement stockés dans des globales et décomposés de manières différentes.

    XML

    La méthode la plus simple pour décomposer le XML en globales consiste à stocker les attributs des balises dans les nœuds. Et si vous avez besoin d'un accès rapide aux attributs des attributs, nous pouvons les placer dans des branches séparées.

    <note id=5>
    <to>Alex</to>
    <from>Sveta</from>
    <heading>Reminder</heading>
    <body>Call me tomorrow!</body>
    </note>

    Dans COS, le code ressemblera à ceci :

    Set ^xml("note")="id=5"
    Set ^xml("note","to")="Alex"
    Set ^xml("note","from")="Sveta"
    Set ^xml("note","heading")="Reminder"
    Set ^xml("note","body")="Call me tomorrow!"

    Note: Pour XML, JSON et les tables associatives, vous pouvez imaginer un certain nombre de méthodes pour les afficher dans les globales. Dans ce cas particulier, nous n'avons pas reflété l'ordre des balises imbriquées dans la balise "note". Dans la globale ^xml, les balises imbriquées seront affichés dans l'ordre alphabétique. Pour un affichage précis de l'ordre, vous pouvez utiliser le modèle suivant, par exemple :

    JSON.

    Le contenu de ce document JSON est présenté dans la première illustration de la section 3.3.1 :

    var document = {
      "name": "Vince Medvedev",
      "city": "Moscow",
      "threatments": {
        "surgeries": ["apedicectomy", "biopsy"],
        "radiation": ["gamma", "x-rays"],
        "physiotherapy": ["knee", "shoulder"]
      },
    };

    3.3.4 Structures identiques liées par des relations hiérarchiques

    Exemples : structure des bureaux de vente, positions des personnes dans une structure MLM, base des débuts aux échecs.

    Base de données des débuts. Vous pouvez utiliser une évaluation de la force du mouvement comme valeur de l'indice de nœud d'une globale. Dans ce cas, vous devrez sélectionner une branche ayant le poids le plus élevé pour déterminer le meilleur déplacement. Dans la globale, toutes les branches de chaque niveau seront triées en fonction de la force du mouvement.

    La structure des bureaux de vente, des personnes dans une société MLM. Les noeuds peuvent stocker certaines valeurs de cache reflétant les caractéristiques de la sous-arborescence entière. Par exemple, les ventes de cette sous-arborescence particulière. Nous pouvons obtenir des informations exactes sur les réalisations de n'importe quelle branche à tout moment.

    4. Situations où l'utilisation des globales est avantageuse

    La première colonne contient une liste de cas où l'utilisation des globales vous donnera un avantage considérable en termes de performance, et la seconde - une liste de situations où elles simplifieront le développement ou le modèle de données.

    <th>
      Commodité du traitement/de la présentation des données
    </th>
    
    <td>
    
    1.  Objets/instances avec un grand nombre de propriétés/instances non requises [et/ou imbriquées] 
      
    2.   Données sans schéma - de nouvelles propriétés peuvent souvent être ajoutées et d'anciennes supprimées
      
    3.   Vous devez créer une BD non standard.Bases de données de chemins et arbres de solutions 
      
    4.   Lorsque les chemins peuvent être représentés de manière pratique sous forme d'arbre
      
    5.  On doit supprimer les structures hiérarchiques sans utiliser la récursion  
      
    Vitesse
    1. Insertion [avec tri automatique à chaque niveau], [indexation par la clé primaire] 2. Suppression de sous-arbres 3. Objets comportant de nombreuses propriétés imbriquées auxquelles vous devez accéder individuellement 4. Structure hiérarchique avec possibilité de parcourir les branches enfant à partir de n'importe quelle branche, même inexistante 5. Parcours en profondeur de l'arbre
    Clause de non-responsabilité: cet article et les commentaires le concernant reflètent uniquement mon opinion et n'ont rien à voir avec la position officielle de la société InterSystems.
    0
    0 107
    Article Guillaume Rongier · Mars 29, 2022 9m read

    Les globales, ces épées magiques destinées à stocker des données, existent depuis un certain temps, mais peu de gens savent les utiliser efficacement ou connaissent cette super-arme.

    Si vous utilisez les globales pour des tâches où ils sont vraiment utiles, les résultats peuvent être étonnants, que ce soit en termes d'amélioration des performances ou de simplification spectaculaire de la solution globale (1, 2).

    Les globales offrent une façon particulière de stocker et de traiter les données, qui est complètement différente des tableaux SQL. Ils ont été introduits en 1966 dans le langage de programmation M(UMPS), qui était initialement utilisé dans les bases de données médicales. Il est toujours utilisé de la même manière, mais a également été adopté par d'autres secteurs où la fiabilité et les hautes performances sont des priorités absolues : finance, commerce, etc.

    Plus tard, M(UMPS) a évolué vers Caché ObjectScript (COS). COS a été développé par InterSystems comme un superset de M. Le langage original est toujours accepté par la communauté des développeurs et existe dans quelques implémentations. Il y a plusieurs signes d'activité sur le web : MUMPS Google group, Mumps User's group), effective ISO Standard, etc.

    Les DBMS (systèmes de base de données) globales modernes prennent en charge les transactions, la journalisation, la réplication et le partitionnement. Cela signifie qu'ils peuvent être utilisés pour construire des systèmes distribués modernes, fiables et rapides.

    Les globales ne vous limitent pas aux frontières du modèle relationnel. Ils vous donnent la liberté de créer des structures de données optimisées pour des tâches particulières. Pour de nombreuses applications, l'utilisation raisonnable des globales peut être une véritable solution miracle offrant des vitesses dont les développeurs d'applications relationnelles classiques ne peuvent que rêver.

    Les globales, en tant que méthode de stockage des données, peuvent être utilisés dans de nombreux langages de programmation modernes, tant de haut niveau que de bas niveau. Par conséquent, cet article se concentrera spécifiquement sur les globales et non sur le langage dont ils sont issus.

    2. Comment fonctionnent les globales

    Commençons par comprendre comment fonctionnent les globales et quels sont leurs avantages. Les globales peuvent être vus sous différents angles. Dans cette partie de l'article, nous les verrons comme des arbres ou des stockages de données hiérarchiques.

    En termes simples, une globale est une liste de données persistantes. Une liste qui est automatiquement sauvegardé sur le disque.

    Il est difficile d'imaginer quelque chose de plus simple pour stocker des données. Dans le code du programme (écrit en langage COS/M), la seule différence avec un tableau associatif ordinaire est le symbole ^ qui précède leur nom.

    Il n'est pas nécessaire de connaître SQL pour enregistrer des données dans une globale, car toutes les commandes nécessaires sont très simples et peuvent être apprises en une heure.

    Commençons par l'exemple le plus simple, un arborescence mono niveau avec deux branches. Les exemples sont écrits en COS.

    Set ^a("+7926X") = "John Sidorov"
    Set ^a("+7916Y") = "Sergey Smith"

      Lorsque des données sont insérées dans une globale (la commande Set), 3 choses se produisent automatiquement:

    1. Sauvegarde des données sur le disque.
    2. Indexation. Ce qui est entre les parenthèses est un indice, ce qui est à droite du signe égal est la valeur du nœud.
    3. Tri. Les données sont triées par une clé. La prochaine traversée mettra "Sergey Smith" en première position, suivi de "John Sidorov". Lorsque l'on obtient une liste d'utilisateurs à partir d'une globale, la base de données ne passe pas de temps à trier. Vous pouvez en fait demander une liste triée à partir de n'importe quelle clé, même une clé inexistante (la sortie commencera à partir de la première clé réelle suivant celle-ci).

    Toutes ces opérations sont effectuées à une vitesse incroyable. Sur mon système personnel (i5-3340, 16GB, HDD WD 1TB Blue), j'ai réussi à atteindre 1 050 000 insertions/sec en un seul processus. Sur les systèmes multi-cœurs, les vitesses peuvent atteindre des dizaines de millions of insertions/sec.

    Bien sûr, la vitesse de saisie des données en elle-même ne dit pas grand-chose. Nous pouvons, par exemple, saisir des données dans des fichiers texte - c'est ainsi que le traitement fonctionne chez Visa, selon les rumeurs. Cependant, avec les globales, nous obtenons un stockage structuré et indexé avec lequel vous pouvez travailler en profitant de sa grande vitesse et de sa facilité d'utilisation.

    • La plus grande force des globales est la vitesse d'insertion de nouveaux nœuds dans ceux-ci.
    • Les données sont toujours indexées dans une globale. Les traversées en profondeur et les traversées arborescentes mono-niveau sont toujours très rapides.

    Ajoutons quelques branches de deuxième et troisième niveau de la globale.

    Set ^a("+7926X", "city") = "Moscow"
    Set ^a("+7926X", "city", "street") = "Req Square"
    Set ^a("+7926X", "age") = 25
    Set ^a("+7916Y", "city") = "London"
    Set ^a("+7916Y", "city", "street") = "Baker Street"
    Set ^a("+7916Y", "age") = 36

    Apparemment, vous pouvez construire des arbres à plusieurs niveaux en utilisant des globales. L'accès à n'importe quel nœud est presque instantané grâce à l'indexation automatique après chaque insertion. Les branches de l'arbre à n'importe quel niveau sont triées par une clé.

    Comme vous pouvez le constater, les données peuvent être stockées à la fois sous forme de clés et de valeurs. La longueur combinée d'une clé (la somme des longueurs de tous les index) peut atteindre 511 octets et les valeurs peuvent atteindre une taille de 3,6 MB dans Caché. Le nombre de niveaux dans un arbre (nombre de dimensions) est plafonné à 31.

    Une autre chose intéressante : vous pouvez construire un arbre sans définir les valeurs des nœuds de niveau supérieur.

    Set ^b("a", "b", "c", "d") = 1
    Set ^b("a", "b", "c", "e") = 2
    Set ^b("a", "b", "f", "g") = 3

    Les cercles vides sont des nœuds sans valeur.

    Pour mieux comprendre les globales, comparons-les à d'autres arbres : les arbres de jardin et les arbres de noms de systèmes de fichiers.

    Comparons les globales aux structures hiérarchiques les plus familières : les arbres réguliers qui poussent dans les jardins et les champs, ainsi que les systèmes de fichiers.

    Comme nous pouvons le constater, les feuilles et les fruits ne poussent qu'à l'extrémité des branches des arbres ordinaires.
    Systèmes de fichiers - les informations sont également stockées à l'extrémité des branches, également connues comme des noms de fichiers complets.

    Et voici la structure de données d'une globale.

    Differences:

    1. Nœuds internes: les informations d'une globale peuvent être stockées dans tous les nœuds et pas seulement aux extrémités des branches.
    2. Nœuds externes: les globales doivent avoir des extrémités de branche définies (extrémités avec des valeurs), ce qui n'est pas obligatoire pour les systèmes de fichiers et les arbres de jardin.

    En ce qui concerne les noeuds internes, nous pouvons traiter la structure de globale comme un sur-ensemble des arbres de noms des systèmes de fichiers et des arbres de jardins. La structure de globale est donc plus flexible.

    En général, une globale est un arbre structuré qui prend en charge la sauvegarde des données dans chaque nœud.

    Afin de mieux comprendre le fonctionnement des globales, imaginons ce qui se passerait si les créateurs d'un système de fichiers utilisaient une approche identique à celle des globales pour stocker les informations ?

    1. Si le dernier fichier d'un dossier était supprimé, le dossier lui-même serait également supprimé, ainsi que tous les dossiers de niveau supérieur qui ne contenaient que ce dossier supprimé.
    2. Il n'y aurait pas besoin de dossiers du tout. Il y aurait des fichiers avec des sous-fichiers et des fichiers sans sous-fichiers. Si vous le comparez à un arbre normal, chaque branche deviendrait un fruit.


      3. Des choses comme README.txt ne seraient probablement plus nécessaires. Tout ce que vous avez besoin de dire sur le contenu d'un dossier pourrait être écrit dans le fichier du dossier lui-même. En général, les noms de fichiers ne peuvent pas être distingués des noms de dossiers (par exemple, /etc/readme peut être soit un dossier, soit un fichier), ce qui signifie que nous pourrions nous contenter d'exploiter des fichiers. 4. Les dossiers comportant des sous-dossiers et des fichiers pourraient être supprimés beaucoup plus rapidement. Il existe des articles sur le net qui racontent à quel point il est long et difficile de supprimer des millions de petits fichiers (1, 2, 3). En revanche, si vous créez un pseudo-système de fichiers basé sur une globale, cela prendra quelques secondes, voire des fractions de seconde. Lorsque j'ai testé la suppression de sous-arbres sur mon ordinateur personnel, j'ai réussi à supprimer 96 à 341 millions de nœuds d'un arbre à deux niveaux sur un disque dur (pas un disque dur externe). Et il convient de mentionner que nous parlons de la suppression d'une partie d'un arbre global, et non de la suppression d'un fichier entier contenant une globale.

    La suppression des sous-arbres est encore un autre avantage des globaux : vous n'avez pas besoin de récursion pour cela. C'est incroyablement rapide. Dans notre arbre, cela pourrait être fait avec une commande Kill.

    Kill ^a("+7926X")

    Vous trouverez ci-dessous un petit tableau qui vous permettra de mieux comprendre les actions que vous pouvez effectuer sur une globale.

    Commandes et fonctions clés liées aux globales dans COS
    Set Paramétrage (initialisation) des branches jusqu'à un noeud (si non défini) et valeur du noeud
    Merge Copie d'un sous-arbre
    Kill Suppression d'un sous-arbre
    ZKill Suppression de la valeur d'un nœud particulier. Le sous-arbre issu de ce noeud n'est pas affecté
    $Query Traversée complète et approfondie de l'arbre
    $Order Renvoie l'indice suivant au même niveau
    $Data Vérifier si un nœud est défini
    $Increment Incrémentation atomique de la valeur d'un nœud afin d'éviter la lecture et l'écriture pour ACID. La dernière recommandation est d'utiliser $Sequence à la place.

    Merci de votre attention, je serai heureux de répondre à vos questions.

    Démenti: Cet article reflète l'opinion privée de l'auteur et n'a aucun rapport avec la position officielle d'InterSystems.

    0
    0 133
    Article Irène Mykhailova · Mars 28, 2022 5m read

    Lorsque je décris InterSystems IRIS à des personnes plus orientées vers la technique, je commence toujours par dire qu'il s'agit d'un DBMS (système de gestion de base de données) multi-modèle.

    À mon avis, c'est son principal avantage (du côté du DBMS). Et les données ne sont stockées qu'une seule fois. Vous choisissez simplement l'API d'accès que vous voulez utiliser.

    • Voulez-vous une sorte de résumé pour vos données ? Utilisez SQL !
    • Souhaitez-vous travailler en profondeur avec un seul enregistrement ? Utilisez des objets !
    • Voulez-vous accéder ou définir une valeur et vous connaissez la clé ? Utilisez les globales !

    À première vue, c'est une belle histoire - courte et concrète, elle fait passer le message, mais lorsque les gens commencent vraiment à travailler avec InterSystems IRIS, les questions apparaissent. Comment les classes, les tables et les globales sont-ils liés ? Que sont-ils les uns pour les autres ? Comment les données sont-elles réellement stockées ?

    Dans cet article, je vais essayer de répondre à ces questions et d'expliquer ce qui se passe réellement.

    Première partie. Le biais des modèles.

    Les personnes qui travaillent avec des données ont souvent un biais en faveur du modèle avec lequel elles travaillent.

    Les développeurs pensent en objets. Pour eux, les bases de données et les tableaux sont des boîtes avec lesquelles vous interagissez via CRUD (Créer-Lire-Mettre à jour-Supprimer, de préférence via ORM), mais le modèle conceptuel sous-jacent est constitué d'objets (bien sûr, c'est surtout vrai pour les développeurs utilisant des langages orientés objet - donc la plupart d'entre nous).

    D'autre part, pour avoir passé beaucoup de temps dans des DBMS relationnels, les DBA considèrent souvent les données comme des tables. Dans ce cas, les objets ne sont que des enveloppes sur les lignes.

    Et avec InterSystems IRIS, une classe persistante est aussi un table, qui stocke les données en globale, donc une clarification est nécessaire.

    Deuxième partie. Un exemple.

    Disons que vous avez créé une classe Point :

    Class try.Point Extends %Persistent [DDLAllowed]
    {
        Property X;
        Property Y;
    }
    

    Vous pouvez également créer la même classe avec DDL/SQL :

    CREATE Table try.Point (
        X VARCHAR(50),
        Y VARCHAR(50))
    

    Après la compilation, notre nouvelle classe aurait généré automatiquement une structure de stockage qui fait correspondre les données qui sont nativement stockées dans les globaux aux colonnes (ou aux propriétés si vous êtes un penseur orienté objet) :

    Storage Default
    {
    <Data name="PointDefaultData">
        <Value name="1">
            <Value>%%CLASSNAME</Value>
        </Value>
        <Value name="2">
            <Value>X</Value>
        </Value>
        <Value name="3">
            <Value>Y</Value>
        </Value>
    </Data>
    <DataLocation>^try.PointD</DataLocation>
    <DefaultData>PointDefaultData</DefaultData>
    <IdLocation>^try.PointD</IdLocation>
    <IndexLocation>^try.PointI</IndexLocation>
    <StreamLocation>^try.PointS</StreamLocation>
    <Type>%Library.CacheStorage</Type>
    }
    

    Qu'est-ce qui se passe ici ?

    De bas en haut (les mots en gras sont importants, ignorez le reste) :

    • Type : le type de stockage généré, dans notre cas le stockage par défaut pour les objets persistants
    • StreamLocation - l'endroit où nous stockons les flux de données séquencé
    • IndexLocation - la globale pour les indices
    • IdLocation - la globale où nous stockons l'ID compteur autoincrémental
    • DefaultData - l'élément XML de stockage qui fait correspondre la valeur globale aux colonnes/propriétés
    • DataLocation - la globale dans lequel les données sont stockées

    Maintenant notre "DefaultData" est PointDefaultData alors regardons de plus près sa structure. Essentiellement, cela dit que le noeud global a cette structure :

    • 1 - %%CLASSNAME
    • 2 - X
    • 3 - Y

    On peut donc s'attendre à ce que notre globale ressemble à ceci :

    ^try.PointD(id) = %%CLASSNAME, X, Y
    

    Mais si nous imprimons notre globale, il sera vide car nous n'avons pas ajouté de données :

    zw ^try.PointD
    

    Ajoutons un objet :

    set p = ##class(try.Point).%New()
    set p.X = 1
    set p.Y = 2
    write p.%Save()
    

    Et voici notre globale

    zw ^try.PointD
    ^try.PointD=1
    ^try.PointD(1)=$lb("",1,2)
    

    Comme vous le voyez, notre structure attendue %%CLASSNAME, X, Y est définie avec $lb("",1,2) qui correspond aux propriétés X et Y de notre objet (%%CLASSNAME est une propriété du système, ignorez-la).

    Nous pouvons également ajouter une ligne via SQL :

    INSERT INTO try.Point (X, Y) VALUES (3,4)
    

    Maintenant, notre globale ressemble à ceci :

    zw ^try.PointD
    ^try.PointD=2
    ^try.PointD(1)=$lb("",1,2)
    ^try.PointD(2)=$lb("",3,4)
    

    Ainsi, les données que nous ajoutons par le biais d'objets ou de SQL sont stockées dans des globales en fonction des définitions de stockage (remarque : vous pouvez modifier manuellement la définition de stockage en remplaçant X et Y dans PointDefaultData - vérifiez ce qu'il arrive aux nouvelles données !)

    Maintenant, que se passe-t-il lorsque nous voulons exécuter une requête SQL ?

    SELECT * FROM try.Point
    

    Elle est traduite en code ObjectScript qui itère sur la globale ^try.PointD et remplit les colonnes en fonction de la définition du stockage - la partie PointDefaultData précisément.

    Maintenant pour les modifications. Supprimons toutes les données du table :

    DELETE FROM try.Point
    

    Et voyons notre globale à ce stade :

    zw ^try.PointD
    ^try.PointD=2
    

    Notez que seul le compteur d'ID est laissé, donc le nouvel objet/ligne aura un ID=3. De même, notre classe et notre table continuent d'exister. Mais que se passe-t-il quand on lance :

    DROP TABLE try.Point
    

    Il détruirait le table, la classe et supprimerait la globale.

    zw ^try.PointD
    

    Si vous avez suivi cet exemple, j'espère que vous comprenez maintenant mieux comment les globales, les classes et les tables s'intègrent et se complètent. L'utilisation de la bonne API pour le travail à effectuer permet un développement plus rapide, plus agile et moins bogué.

    0
    0 213
    Article Guillaume Rongier · Mars 16, 2022 21m read

    Cette formation s'adresse aux débutants qui souhaitent découvrir le framework IRIS Interoperability. Nous utiliserons Docker et VSCode.

    GitHub : https://github.com/grongierisc/formation-template

    1. Formation Ensemble / Interoperability

    Le but de cette formation est d'apprendre le cadre d'interopérabilité d'InterSystems, et en particulier l'utilisation de :

    • Productions
    • Messages
    • Opérations commerciales
    • Adaptateurs
    • Processus métier
    • Services commerciaux
    • Services et opérations REST

    TABLE DES MATIÈRES :

    2. Cadre de travail

    Voici le Framework IRIS.

    FrameworkFull

    Les composants à l'intérieur d'IRIS représentent une production. Les adaptateurs entrants et les adaptateurs sortants nous permettent d'utiliser différents types de formats comme entrée et sortie pour notre base de données. Les applications composites nous donneront accès à la production via des applications externes comme les services REST.

    Les flèches entre tous ces composants sont des messages. Ils peuvent être des demandes ou des réponses.

    3. Adapter le framework

    Dans notre cas, nous allons lire des lignes dans un fichier csv et les enregistrer dans la base de données IRIS.

    Nous ajouterons ensuite une opération qui nous permettra de sauvegarder également des objets dans une base de données externe, en utilisant JDBC. Cette base de données sera située dans un conteneur docker, en utilisant postgre.

    Enfin, nous verrons comment utiliser des applications composites pour insérer de nouveaux objets dans notre base de données ou pour consulter cette base (dans notre cas, via un service REST).

    Le framework adapté à notre objectif nous donne :

    FrameworkAdapted

    4. Prérequis

    Pour cette formation, vous aurez besoin de :

    5. Mise en place

    5.1. Conteneurs Docker

    Afin d'avoir accès aux images InterSystems, nous devons nous rendre à l'url suivante : http://container.intersystems.com. Après nous être connectés avec nos identifiants InterSystems, nous obtiendrons notre mot de passe pour nous connecter au registre. Dans l'addon docker VScode, dans l'onglet image, en appuyant sur connect registry et en entrant la même url que précédemment (http://container.intersystems.com) comme registre générique, il nous sera demandé de donner nos identifiants. L'identifiant est l'identifiant habituel mais le mot de passe est celui que nous avons obtenu sur le site Web.

    De là, nous devrions pouvoir construire et composer nos conteneurs (avec les fichiers docker-compose.yml et Dockerfile donnés).

    5.2. Portail de gestion

    Nous allons ouvrir un portail de gestion. Il nous donnera accès à une page web où nous pourrons créer notre production. Le portail devrait être situé à l'url : http://localhost:52775/csp/sys/UtilHome.csp?$NAMESPACE=IRISAPP. Vous aurez besoin des informations d'identification suivantes :

    IDENTIFIANT : SuperUser

    MOT DE PASSE : SYS

    5.3. Sauvegarde de la progression

    Une partie des choses que nous allons faire sera sauvegardée localement, mais tous les processus et productions sont sauvegardés dans le conteneur docker. Afin de persister tout notre progrès, nous devons exporter chaque classe qui est créée par le portail de gestion avec l'addon InterSystems ObjectScript :

    ExportProgress

    Nous devrons sauvegarder notre production, le plan d'enregistrement, les processus métier et le transfert de données de cette manière. Après cela, lorsque nous fermerons notre conteneur docker et le recomposerons, nous aurons toujours toute notre progression sauvegardée localement (c'est, bien sûr, à faire après chaque changement via le portail). Pour le rendre à nouveau accessible à IRIS, nous devons compiler les fichiers exportés (en les sauvegardant, les addons InterSystems s'occupent du reste).

    6. Productions

    Nous pouvons maintenant créer notre première production. Pour cela, nous allons passer par les menus [Interoperability] et [Configurer] :

    MenuProduction

    Nous devons ensuite appuyer sur [Nouveau], sélectionner le paquet [Formation] et choisir un nom pour notre production :

    ProductionCreation

    Immédiatement après avoir créé notre production, nous devons cliquer sur [Paramètres de production] juste au-dessus de la section [Opérations]. Dans le menu latéral de droite, nous devrons activer [Test activé] dans la partie [Développement et débogage] de l'onglet [Paramètres] (n'oubliez pas de cliquer sur [Appliquer]).

    ProductionTesting

    Dans cette première production, nous allons maintenant ajouter des opérations commerciales.

    7. Opérations

    Une Business Operation (BO) est une opération spécifique qui nous permettra d'envoyer des requêtes depuis IRIS vers une application / un système externe. Elle peut également être utilisée pour enregistrer directement dans IRIS ce que nous voulons.

    Nous allons créer ces opérations en local, c'est-à-dire dans le fichier Formation/BO/. En sauvegardant les fichiers, nous les compilerons dans IRIS.

    Pour notre première opération, nous allons sauvegarder le contenu d'un message dans la base de données locale.

    Nous devons d'abord avoir un moyen de stocker ce message.

    7.1. Création de notre classe de stockage

    Les classes de stockage dans IRIS étendent le type %Persistent. Elles seront enregistrées dans la base de données interne.

    Dans notre fichier Formation/Table/Formation.cls nous avons :

    Class Formation.Table.Formation Extends %Persistent
    {
    
    Property Name As %String;
    
    Property Salle As %String;
    
    }
    

    Notez que lors de l'enregistrement, des lignes supplémentaires sont automatiquement ajoutées au fichier. Elles sont obligatoires et sont ajoutées par les addons InterSystems.

    7.2. Création de notre classe de messages

    Ce message contient un objet Formation, situé dans le fichier Formation/Obj/Formation.cls :

    Class Formation.Obj.Formation Extends (%SerialObject, %XML.Adaptor)
    {
    
    Property Nom As %String;
    
    Property Salle As %String;
    
    }
    

    La classe Message utilisera cet objet Formation, src/Formation/Msg/FormationInsertRequest.cls :

    Class Formation.Msg.FormationInsertRequest Extends Ens.Request
    {
    
    Property Formation As Formation.Obj.Formation;
    
    }
    

    7.3. Création de notre opération

    Maintenant que nous avons tous les éléments dont nous avons besoin, nous pouvons créer notre opération, dans le fichier Formation/BO/LocalBDD.cls :

    Class Formation.BO.LocalBDD Extends Ens.BusinessOperation
    {
    
    Parameter INVOCATION = "Queue";
    
    Method InsertLocalBDD(pRequest As Formation.Msg.FormationInsertRequest, Output pResponse As Ens.StringResponse) As %Status
    {
        set tStatus = $$$OK
    
        try{
            set pResponse = ##class(Ens.Response).%New()
            set tFormation = ##class(Formation.Table.Formation).%New()
            set tFormation.Name = pRequest.Formation.Nom
            set tFormation.Salle = pRequest.Formation.Salle
            $$$ThrowOnError(tFormation.%Save())
        }
        catch exp
        {
            Set tStatus = exp.AsStatus()
        }
    
        Quit tStatus
    }
    
    XData MessageMap
    {
    <MapItems>
        <MapItem MessageType="Formation.Msg.FormationInsertRequest"> 
            <Method>InsertLocalBDD</Method>
        </MapItem>
    </MapItems>
    }
    
    }
    
    

    La MessageMap nous donne la méthode à lancer en fonction du type de demande (le message envoyé à l'opération).

    Comme nous pouvons le voir, si l'opération a reçu un message du type Formation.Msg.FormationInsertRequest, la méthode InsertLocalBDD sera appelée. Cette méthode enregistrera le message dans la base de données locale d'IRIS.

    7.4. Ajout de l'opération à la production

    Nous devons maintenant ajouter cette opération à la production. Pour cela, nous utilisons le portail de gestion. En appuyant sur le signe [+] à côté de [Opérations], nous avons accès à l'[Assistant d'opérations commerciales]. Là, nous choisissons la classe d'opération que nous venons de créer dans le menu déroulant.

    OperationCreation

    9.3. Test

    Un double clic sur l'opération nous permettra de l'activer. Après cela, en sélectionnant l'opération et en allant dans les onglets [Actions] dans le menu latéral droit, nous devrions être en mesure de tester l'opération (si ce n'est pas le cas, consultez la partie création de la production pour activer les tests / vous devrez peut-être démarrer la production si elle est arrêtée).

    En faisant cela, nous allons envoyer à l'opération un message du type que nous avons déclaré plus tôt. Si tout se passe bien, les résultats devraient être comme indiqué ci-dessous :

    OperationTest

    L'affichage de la trace visuelle nous permettra de voir ce qui s'est passé entre les processus, les services et les opérations. Ici, nous pouvons voir le message envoyé à l'opération par le processus, et l'opération renvoyant une réponse (qui est juste une chaîne vide).

    8. Processus métier

    Les processus métier (BP) sont la logique métier de notre production. Ils sont utilisés pour traiter les demandes ou relayer ces demandes à d'autres composants de la production.

    Les processus métier sont créés dans le portail de gestion :

    BPMenu

    8.1. BP simple

    8.1.1. Création du processus

    Nous sommes maintenant dans le concepteur de processus métier. Nous allons créer un BP simple qui appellera notre opération :

    BPAddingCall

    8.1.2. Modifier le contexte d'un BP

    Un BP possède un Contexte. Il est composé d'une classe de requête, la classe de l'entrée, et d'une classe de réponse, la classe de la sortie. Les processus métier n'ont qu'une entrée et une sortie. Il est également possible d'ajouter des propriétés.

    Puisque notre BP ne sera utilisé que pour appeler notre BO, nous pouvons mettre comme classe de requête la classe de message que nous avons créée (nous n'avons pas besoin d'une sortie puisque nous voulons juste insérer dans la base de données).

    BPContext

    Nous avons ensuite choisi la cible de la fonction d'appel : notre BO. Cette opération, étant appelée a une propriété callrequest. Nous devons lier cette callrequest à la requête de la BP (elles sont toutes deux de la classe Formation.Msg.FormationInsertRequest), nous faisons cela en cliquant sur la fonction d'appel et en utilisant le constructeur de requête :

    BPBindRequests

    Nous pouvons maintenant sauvegarder cette BP (dans le package « Formation.BP » et sous le nom « InsertLocalBDD » ou « Main », par exemple). Tout comme les opérations, les processus peuvent être instanciés et testés via la configuration de production, pour cela ils doivent être compilés au préalable (sur l'écran Concepteur de processus métier).

    Pour l'instant, notre processus ne fait que transmettre le message à notre opération. Nous allons le complexifier pour que le BP prenne en entrée une ligne d'un fichier CSV.

    8.2. Lecture de lignes CSV par un BP

    8.2.1. Création d'une carte d'enregistrement

    Afin de lire un fichier et de mettre son contenu dans un fichier, nous avons besoin d'une Carte d'enregistrement (RM). Il existe un Record Mapper spécialisé pour les fichiers CSV dans le menu [Interoperability > Build] du portail de gestion :

    RMMenu

    Nous créerons le mapper comme suit :

    RMCreation

    Nous allons créer le mappeur comme ceci :

    RMDetails

    Maintenant que la carte est créée, nous devons la générer (avec le bouton Générer). Nous devons maintenant avoir une Transformation de données à partir du format de la carte des enregistrements et un message d'insertion.

    8.2.2. Création d'une transformation de données

    Nous trouverons le créateur de transformations de données (DT) dans le menu [Interoperability > Builder]. Nous allons créer notre DT comme ceci (si vous ne trouvez pas Formation.RM.Csv.Record, peut-être que vous n'avez pas généré la carte d'enregistrement) :

    DTCreation

    Nous pouvons pouvons maintenant mapper les différents champs ensemble :

    DTMap

    8.2.3. Ajout de la transformation des données au processus métier

    La première chose que nous devons changer est la classe de requête de la BP, puisque nous devons avoir en entrée la carte d'enregistrement que nous avons créée.

    BP2ChangeContext

    Nous pouvons alors ajouter notre transformation (le nom du processus ne change rien, d'ici nous avons choisi de le nommer Main) :

    BP2AddingTransform

    L'activité de transformation va prendre la requête de la BP (un enregistrement du fichier CSV, grâce à notre Record Mapper), et la transformer en un message FormationInsertRequest. Afin de stocker ce message pour l'envoyer à la BO, nous devons ajouter une propriété au contexte de la BP.

    BP2MsgContext

    Nous pouvons maintenant configurer notre fonction de transformation pour qu'elle prenne l'entrée du BP et enregistre sa sortie dans la propriété nouvellement créée. La source et la cible de la transformation RmToMsg sont respectivement request et context.Msg :

    BP2RmToMsg

    Nous devons faire de même pour Call BO. Son entrée, ou callrequest, est la valeur stockée dans context.msg :

    BP2CallBO

    Au final, le flux dans la BP peut être représenté comme ceci :

    BP2Diagram

    8.2.4. Configuration de la production

    Avec le signe [+], nous pouvons ajouter notre nouveau processus à la production (si ce n'est pas déjà fait). Nous avons également besoin d'un service générique pour utiliser le record map, nous utilisons EnsLib.RecordMap.Service.FileService (nous l'ajoutons avec le bouton [+] à côté des services). Nous paramétrons ensuite ce service :

    ServiceParam

    Nous devrions maintenant être en mesure de tester notre BP.

    8.2.5. Test

    Nous testons l'ensemble de la production comme suit :

    TestProductionCSV

    Dans le menu Explorateur système > SQL, vous pouvez exécuter la commande

    SELECT 
    ID, Name, Salle
    FROM Formation_Table.Formation
    

    pour voir les objets que nous venons d'enregistrer.

    9. Accéder à une base de données externe à l'aide de JDBC

    Dans cette section, nous allons créer une opération pour sauvegarder nos objets dans une base de données externe. Nous utiliserons l'API JDBC, ainsi que l'autre conteneur docker que nous avons mis en place, avec postgre dessus.

    9.1. Création de notre nouvelle opération

    Notre nouvelle opération, dans le fichier Formation/BO/RemoteBDD.cls est la suivante :

    Include EnsSQLTypes
    
    Class Formation.BO.RemoteBDD Extends Ens.BusinessOperation
    {
    
    Parameter ADAPTER = "EnsLib.SQL.OutboundAdapter";
    
    Property Adapter As EnsLib.SQL.OutboundAdapter;
    
    Parameter INVOCATION = "Queue";
    
    Method InsertRemoteBDD(pRequest As Formation.Msg.FormationInsertRequest, Output pResponse As Ens.StringResponse) As %Status
    {
        set tStatus = $$$OK
    
        try{
            set pResponse = ##class(Ens.Response).%New()
            set ^inc = $I(^inc)
            set tInsertSql = "INSERT INTO public.formation (id, nom, salle) VALUES(?, ?, ?)"
            $$$ThrowOnError(..Adapter.ExecuteUpdate(.nrows,tInsertSql,^inc,pRequest.Formation.Nom, pRequest.Formation.Salle ))
        }
        catch exp
        {
            Set tStatus = exp.AsStatus()
        }
    
        Quit tStatus
    }
    
    XData MessageMap
    {
    <MapItems>
        <MapItem MessageType="Formation.Msg.FormationInsertRequest"> 
            <Method>InsertRemoteBDD</Method>
        </MapItem>
    </MapItems>
    }
    
    }
    

    Cette opération est similaire à la première que nous avons créée. Lorsqu'elle recevra un message du type Formation.Msg.FormationInsertRequest, elle utilisera un adaptateur pour exécuter des requêtes SQL. Ces requêtes seront envoyées à notre base de données postgre.

    9.2. Configurer la production

    Maintenant, via le portail de gestion, nous allons instancier cette opération (en l'ajoutant avec le signe [+] dans la production).

    Nous devrons également ajouter le JavaGateway pour le pilote JDBC dans les services. Le nom complet de ce service est EnsLib.JavaGateway.Service.

    JDBCProduction

    Nous devons maintenant configurer notre opération. Puisque nous avons mis en place un conteneur postgre, et connecté son port 5432, les valeurs dont nous avons besoin dans les paramètres suivants sont :

    DSN : jdbc:postgresql://db:5432/DemoData

    Pilote JDBC : org.postgresql.Driver

    JDBC Classpath : /tmp/iris/postgresql-42.2.14.jar

    JDBCParam

    Enfin, nous devons configurer les informations d'identification pour avoir accès à la base de données distante. Pour cela, nous devons ouvrir la visionneuse d'identifiants :

    JDBCCredentialMenu

    L'identifiant et le mot de passe sont tous deux DemoData, comme nous l'avons configuré dans le fichier docker-compose.yml.

    JDBCCredentialCreation

    De retour à la production, nous pouvons ajouter « Postgre » dans le champ [Identifiant] dans les paramètres de notre opération (il devrait être dans le menu déroulant). Avant de pouvoir le tester, nous devons ajouter le JGService à l'opération. Dans l'onglet [Paramètres], dans les [Paramètres supplémentaires] :

    JDBCService

    7.5. Test

    Lors du test, la trace visuelle doit indiquer un succès :

    JDBCTest

    Lors du test, la trace visuelle doit montrer un succès :

    9.4. Exercice

    À titre d'exercice, il pourrait être intéressant de modifier BO.LocalBDD afin qu'il renvoie un booléen qui indiquera au BP d'appeler BO.RemoteBDD en fonction de la valeur de ce booléen.

    Indice : cela peut être fait en changeant le type de réponse que LocalBDD renvoie et en ajoutant une nouvelle propriété au contexte et en utilisant l'activité if dans notre BP.

    9.5. Solution

    Tout d'abord, nous devons avoir une réponse de notre opération LocalBDD. Nous allons créer un nouveau message, dans le fichier Formation/Msg/FormationInsertResponse.cls :

    Class Formation.Msg.FormationInsertResponse Extends Ens.Response
    {
    
    Property Double As %Boolean;
    
    }
    

    Ensuite, nous modifions la réponse de LocalBDD par cette réponse, et définissons la valeur de son booléen de manière aléatoire (ou non) :

    Method InsertLocalBDD(pRequest As Formation.Msg.FormationInsertRequest, Output pResponse As Formation.Msg.FormationInsertResponse) As %Status
    {
        set tStatus = $$$OK
    
        try{
            set pResponse = ##class(Formation.Msg.FormationInsertResponse).%New()
            if $RANDOM(10) < 5 {
                set pResponse.Double = 1
            } 
            else {
                set pResponse.Double = 0
            }
    ...
    

    Nous allons maintenant créer un nouveau processus (copié sur celui que nous avons fait), où nous ajouterons une nouvelle propriété de contexte, de type %Boolean :

    ExerciseContext

    Cette propriété sera remplie avec la valeur du callresponse.Double de notre appel d'opération (nous devons définir la [Classe de message de réponse] à notre nouvelle classe de message) :

    ExerciseBinding

    Nous ajoutons ensuite une activité if, avec la propriété context.Double comme condition :

    ExerciseIf

    TRÈS IMPORTANT : nous devons décocher Asynchrone dans les paramètres de notre appel LocallBDD, ou l'activité if se déclenchera avant de recevoir la réponse booléenne.

    Enfin, nous configurons notre activité d'appel avec comme cible le BO RemoteBDD :

    ExerciseRemoteCall

    Pour compléter l'activité if, nous devons faire glisser un autre connecteur de la sortie du if vers le triangle join ci-dessous. Comme nous ne ferons rien si le booléen est faux, nous laisserons ce connecteur vide. Après avoir compilé et instancié, nous devrions être en mesure de tester notre nouveau processus. Pour cela, nous devons changer le Target Config Name de notre File Service.

    Dans la trace, nous devrions avoir environ la moitié des objets lus dans le csv enregistrés également dans la base de données distante.

    10. Service REST

    Dans cette partie, nous allons créer et utiliser un service REST.

    10.1. Créer le service

    Pour créer un service REST, nous avons besoin d'une classe qui étend %CSP.REST, dans Formation/REST/Dispatch.cls nous avons :

    Class Formation.REST.Dispatch Extends %CSP.REST
    {
    
    /// Ignore any writes done directly by the REST method.
    Parameter IgnoreWrites = 0;
    
    /// Convertir par défaut le flux d'entrée en Unicode
    Parameter CONVERTINPUTSTREAM = 1;
    
    /// Le jeu de caractères par défaut est utf-8
    Parameter CHARSET = "utf-8";
    
    Parameter HandleCorsRequest = 1;
    
    XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
    {
    <Routes>
      <!-- Get this spec -->
      <Route Url="/import" Method="post" Call="import" />
    </Routes>
    }
    
    /// Obtenir cette spécification
    ClassMethod import() As %Status
    {
      set tSc = $$$OK
    
      Try {
    
          set tBsName = "Formation.BS.RestInput"
          set tMsg = ##class(Formation.Msg.FormationInsertRequest).%New()
    
          set body = $zcvt(%request.Content.Read(),"I","UTF8")
          set dyna = {}.%FromJSON(body)
    
          set tFormation = ##class(Formation.Obj.Formation).%New()
          set tFormation.Nom = dyna.nom
          set tFormation.Salle = dyna.salle
    
          set tMsg.Formation = tFormation
    
          $$$ThrowOnError(##class(Ens.Director).CreateBusinessService(tBsName,.tService))
    
          $$$ThrowOnError(tService.ProcessInput(tMsg,.output))
    
      } Catch ex {
          set tSc = ex.AsStatus()
      }
    
      Quit tSc
    }
    
    }
    

    Cette classe contient une route pour importer un objet, liée au verbe POST :

    <Routes>
      <!-- Obtenir cette spécification -->
      <Route Url="/import" Method="post" Call="import" />
    </Routes>
    

    La méthode d'importation va créer un message qui sera envoyé à un service métier.

    10.2. Ajouter notre BS

    Nous allons créer une classe générique qui va router toutes ses sollicitations vers TargetConfigNames. Cette cible sera configurée lorsque nous instancierons ce service. Dans le fichier Formation/BS/RestInput.cls nous avons :

    Class Formation.BS.RestInput Extends Ens.BusinessService
    {
    
    Property TargetConfigNames As %String(MAXLEN = 1000) [ InitialExpression = "BuisnessProcess" ];
    
    Parameter SETTINGS = "TargetConfigNames:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId}";
    
    Method OnProcessInput(pDocIn As %RegisteredObject, Output pDocOut As %RegisteredObject) As %Status
    {
        set status = $$$OK
    
        try {
    
            for iTarget=1:1:$L(..TargetConfigNames, ",") {
                set tOneTarget=$ZStrip($P(..TargetConfigNames,",",iTarget),"<>W")  Continue:""=tOneTarget
                $$$ThrowOnError(..SendRequestSync(tOneTarget,pDocIn,.pDocOut))
            }
        } catch ex {
            set status = ex.AsStatus()
        }
    
        Quit status
    }
    
    }
    

    De retour à la configuration de production, nous ajoutons le service de la manière habituelle. Dans le champ [Target Config Names], nous mettons notre BO LocalBDD :

    RESTServiceSetup

    Pour utiliser ce service, nous devons le publier. Pour cela, nous utilisons le menu [Modifier l'application Web] :

    RESTServicePublish

    10.3. Test

    Enfin, nous pouvons tester notre service avec n'importe quel type de client REST :

    RESTTest

    Conclusion

    Grâce à cette formation, nous avons créé une production capable de lire les lignes d'un fichier csv et de sauvegarder les données lues à la fois dans la base de données IRIS et dans une base de données externe en utilisant JDBC. Nous avons également ajouté un service REST afin d'utiliser le verbe POST pour sauvegarder de nouveaux objets.

    Nous avons découvert les principaux éléments du cadre d'interopérabilité d'InterSystems.

    Nous l'avons fait en utilisant docker, vscode et le portail de gestion IRIS d'InterSystems.

    0
    0 322
    Article Irène Mykhailova · Mars 10, 2022 5m read

    Bonjour chers membres de la communauté des développeurs,

    Dans cette publication, nous aimerions vous montrer comment utiliser les balises CD. Tirons le meilleur parti de cette option de la communauté des développeurs !

    Une balise est un mot ou une phrase qui décrit le sujet de la publication. Les balises sont un moyen de mettre en relation les membres et les experts avec les publications dont ils pourront discuter ou auxquelles ils pourront donner la bonne réponse en classant les publications dans des catégories spécifiques et bien définies.

    Les balises peuvent également être utilisées pour vous aider à identifier les publications qui sont intéressantes ou pertinentes pour vous.

    Vous trouverez la liste complète des balises dans la section Balises du menu supérieur de la CD :

    Types de balises et arborescence de balises de la communauté des développeurs 

    Il existe deux types de balises de la communauté des développeurs :

    1. Groupes − balises dites principales pour des sujets larges et incluant toutes les technologies InterSystems.
    2. Balises − balises ordinaires pour des sujets plus spécialisés.

    Chaque publication doit avoir au moins un de ces groupes. Connaissez-vous tous les groupes ?

    • Un groupe de balises pour chaque technologie InterSystems (9) : 

     

    • Un groupe de balises pour Visual Studio Code, la populaire plateforme croisée de Microsoft :

    • Un groupe de balises pour les annonces officielles concernant la CD ou InterSystems :


    • Un groupe de balises pour les avis et les alertes du Worldwide Response Center (WRC) :

    • Un groupe de balises pour Open Exchange (la galerie InterSystems de solutions logicielles et de frameworks construits avec/pour InterSystems), un autre pour Global Masters (la plateforme de ludification d'InterSystems), et un autre pour le Partner Directory (la plateforme InterSystems pour les clients et les partenaires**)** :


    • Un groupe de balises pour Global Summit, la réunion annuelle d'InterSystems :

    • Des groupes de balises pour l'apprentissage en ligne et la documentation :


    • Un groupe de balises pour les commentaires, opinions, suggestions... concernant la CD :

    • Un groupe de balises pour les annonces d'opportunités d'emploi liées à la technologie InterSystems :

    • Et un groupe de balises alternatif au reste, pour les publications qui ne peuvent pas être balisées avec l'une des balises précédentes :

    En plus des groupes, les membres de la CD utilisent les balises pour préciser encore plus le contenu des publications.

    Dans l'arborescence des balises de la CD, vous pouvez également trouver des sous-balises, qui catégorisent le contenu des balises. 

    Par exemple, la balise « Languages » possède les sous-balises suivantes :« "C++ », « Python », « JavaScript », « MultiValue Basic », « ObjectScript », « Java » et « .NET ».

     

    Il n'est pas obligatoire d'ajouter des balises aux publications, mais vous devez sélectionner au moins un groupe :

    Trier les balises

    Vous pouvez trier les balises de trois manières différentes à l'aide de l'arborescence des balises CD :

    1. Par popularité :

    Les groupes et les balises sont triés en fonction du nombre de fois où ils ont été utilisés dans des publications. Ce nombre apparaît à côté de chaque balise (entre parenthèses).

    Par exemple, la balise Open Exchange a été utilisée dans 368 publications :

    2. Par nom :

    Les groupes et balise sont triés par ordre alphabétique.

    3. Par nouveauté :

    En sélectionnant ce tri, les groupes et balises les plus récemment créés seront affichés en premier.

    Page des balises : suivez, triez, filtrez les publications avec des balises

    Chaque balise a sa propre URL/page Web, où vous pouvez voir toutes les publications qui ont utilisé cette balise. 

    Par exemple, la balise « XML » a cette page Web : community.intersystems.com/tags/xml, montrant toutes les publications utilisant cette balise :

    Toutes les publications peuvent être filtrées selon différents critères sur la page Balise : par mise à jour, par date, par j'aime, par vues ou par réponses.

    Elles peuvent également être triées par type de publication : annonces, articles, questions, discussions, vidéos ou emplois. Vous devez vous rendre dans le menu situé dans le coin supérieur gauche et sélectionner le type de publication que vous recherchez.

    Suivez les balises qui vous intéressent !

    Si un sujet vous intéresse, vous pouvez rechercher sa balise dans l'arborescence des balises de la CD, la sélectionner et cliquer sur le bouton « Suivre » à côté. Lorsque vous suivez une balise, vous recevez des e-mails contenant toutes les publications utilisant cette balise.

    Balises que nous suggérons pour commencer : Meilleures pratiques | Astuces et conseils | Débutant | Didacticiel.


    Alors...

    Jetez un coup d'œil à l'arborescence des balises de la CD dès maintenant − des sujets (balises) intéressants et une tonne de contenu utile vous attendent :

    • lisez toutes les publications sur le sujet qui vous intéresse ;
    • suivez les balises pour ne pas manquer les futures publications sur vos sujets favoris.

    Si vous avez des questions sur les balises, veuillez laisser vos commentaires/suggestions ci-dessous !

    0
    0 65