0 Abonnés · 130 Publications

SQL est un langage standard pour stocker, manipuler et récupérer des données dans des bases de données relationnelles.

Annonce Irène Mykhailova · Sept 17, 2024

Bonjour la Communauté,

L'équipe de certification d'InterSystems Learning Services est ravie d'annoncer la sortie de notre nouvel examen InterSystems IRIS SQL Specialist. Il est désormais disponible à l'achat et à la planification dans le catalogue d'examens InterSystems. Les candidats potentiels peuvent consulter les sujets d'examen et les questions de pratique pour les aider à s'orienter vers les approches et le contenu des questions d'examen. Les candidats qui réussissent l'examen recevront un badge de certification numérique qui peut être partagé sur des comptes de réseaux sociaux comme LinkedIn.

0
0 34
Article Lorenzo Scalese · Août 27, 2024 5m read

 

Démarrage rapide des données SQL d'InterSystems Cloud dans Databricks

La mise en œuvre de Databricks en SQL d'InterSystems Cloud se compose de quatre parties.

  • Obtention du certificat et du pilote JDBC Driver pour InterSystems IRIS
  • Ajout d'un script d'initialisation et d'une bibliothèque externe à votre Cluster de calcul Databricks
  • Obtention de données
  • Placement des données

Téléchargement du certificat X.509/du pilote JDBC de Cloud SQL

Naviguez vers la page d'aperçu de votre déploiement, si vous n'avez pas activé de connexions externes, faites-le et téléchargez votre certificat et le pilote jdbc depuis la page d'aperçu.

 

J'ai utilisé intersystems-jdbc-3.8.4.jar et intersystems-jdbc-3.7.1.jar avec succès dans Databricks à partir de la distribution de pilotes Driver Distribution.

Script d'initialisation pour votre cluster Databricks

La façon la plus simple d'importer un ou plusieurs certificats CA personnalisés dans votre cluster Databricks est de créer un script d'initialisation qui ajoute la chaîne complète de certificats CA aux magasins de certificats par défaut SSL et Java de Linux, et définit la propriété REQUESTS_CA_BUNDLE. Collez le contenu du certificat X.509 que vous avez téléchargé dans le bloc supérieur du script suivant:

import_cloudsql_certficiate.sh
#!/bin/bash

cat << 'EOF' > /usr/local/share/ca-certificates/cloudsql.crt
-----BEGIN CERTIFICATE-----
<PASTE>
-----END CERTIFICATE-----
EOF

update-ca-certificates

PEM_FILE="/etc/ssl/certs/cloudsql.pem" PASSWORD="changeit" JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::") KEYSTORE="$JAVA_HOME/lib/security/cacerts" CERTS=$(grep 'END CERTIFICATE'$PEM_FILE| wc -l)

# Pour traiter plusieurs certificats avec keytool, vous devez extraire# chacun d'eux du fichier PEM et l'importer dans le KeyStore Java.for N in $(seq 0 $(($CERTS - 1))); do ALIAS="$(basename $PEM_FILE)-$N"echo"Adding to keystore with alias:$ALIAS" cat $PEM_FILE | awk "n==$N { print }; /END CERTIFICATE/ { n++ }" | keytool -noprompt -import -trustcacerts
-alias$ALIAS -keystore $KEYSTORE -storepass $PASSWORDdoneecho"export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" >> /databricks/spark/conf/spark-env.sh echo"export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" >> /databricks/spark/conf/spark-env.sh

Maintenant vous avez le script initial, téléchargez-le dans le catalogue Unity sur un Volume.

Une fois que le script est sur un volume, vous pouvez ajouter le script initial au cluster à partir du volume dans les propriétés avancées de votre cluster.


Ensuite, ajoutez le pilote/la bibliothèque intersystems jdbc au cluster...

...et démarrez ou redémarrez votre calcul.

Station Databricks - Entrée vers le Cloud SQL d'InterSystems IRIS

 

Créez un Notebook Python dans votre espace de travail, attachez-le à votre cluster et testez le glissement de données vers Databricks.  Sous le capot, Databricks va utiliser pySpark, si cela n'est pas immédiatement évident.

La construction du Dataframe Spark suivant est tout ce qu'il vous faut, vous pouvez récupérer vos informations de connexion à partir de la page d'aperçu comme auparavant.

df = (spark.read
  .format("jdbc")
  .option("url", "jdbc:IRIS://k8s-05868f04-a4909631-ac5e3e28ef-6d9f5cd5b3f7f100.elb.us-east-1.amazonaws.com:443/USER")
  .option("driver", "com.intersystems.jdbc.IRISDriver")
  .option("dbtable", "(SELECT name,category,review_point FROM SQLUser.scotch_reviews) AS temp_table;") 
  .option("user", "SQLAdmin")
  .option("password", "REDACTED")
  .option("driver", "com.intersystems.jdbc.IRISDriver")\
  .option("connection security level","10")\
  .option("sslConnection","true")\
  .load())

df.show()

Illustration de la production d'un dataframe à partir de données dans Cloud SQL... boom!

Station Databricks - Sortie du Cloud SQL d'InterSystems IRIS

 

Prenons maintenant ce que nous avons lu dans IRIS et écrivons-le avec Databricks. Si vous vous souvenez bien, nous n'avons lu que 3 champs dans notre cadre de données, nous allons donc les réécrire immédiatement et spécifier un mode "écraser".

df = (spark.read
  .format("jdbc")
  .option("url", "jdbc:IRIS://k8s-05868f04-a4909631-ac5e3e28ef-6d9f5cd5b3f7f100.elb.us-east-1.amazonaws.com:443/USER")
  .option("driver", "com.intersystems.jdbc.IRISDriver")
  .option("dbtable", "(SELECT TOP 3 name,category,review_point FROM SQLUser.scotch_reviews) AS temp_table;") 
  .option("user", "SQLAdmin")
  .option("password", "REDACTED")
  .option("driver", "com.intersystems.jdbc.IRISDriver")\
  .option("connection security level","10")\
  .option("sslConnection","true")\
  .load())

df.show()

mode = "overwrite" properties = { "user": "SQLAdmin", "password": "REDACTED", "driver": "com.intersystems.jdbc.IRISDriver", "sslConnection": "true", "connection security level": "10", }

df.write.jdbc(url="jdbc:IRIS://k8s-05868f04-a4909631-ac5e3e28ef-6d9f5cd5b3f7f100.elb.us-east-1.amazonaws.com:443/USER", table="databricks_scotch_reviews", mode=mode, properties=properties)

Exécution du Notebook

 
Illustration des données dans le Cloud SQL d'InterSystems!

Les points à prendre en considération

  • Par défaut, PySpark écrit les données en utilisant plusieurs tâches concurrentes, ce qui peut entraîner des écritures partielles si l'une des tâches échoue.
  • Pour garantir que l'opération d'écriture est atomique et cohérente, vous pouvez configurer PySpark de manière à ce que les données soient écrites à l'aide d'une seule tâche (c'est-à-dire en définissant le nombre de partitions à 1) ou utiliser une fonctionnalité spécifique à IRIS, telle que les transactions.
  • En outre, vous pouvez utiliser l'API DataFrame de PySpark pour effectuer des opérations de filtrage et d'agrégation avant de lire les données de la base de données, ce qui peut réduire la quantité de données à transférer sur le réseau.
0
0 44
Article Lorenzo Scalese · Juil 29, 2024 9m read

Supposons que vous ayez une application qui permette aux utilisateurs d'écrire des articles et de les commenter. (Attendez...  ça me dit quelque chose...)

L'objectif est de répertorier, pour un utilisateur donné, tous les messages publiés avec lesquels il a interagi, c'est-à-dire dont il est l'auteur ou qu'il a commentés. Comment faites-vous cela aussi vite que possible?

Voici à quoi pourraient ressembler les définitions de notre classe %Persistent comme point de départ (les définitions de stockage sont importantes, mais omises par souci de concision):

Class DC.Demo.Post Extends%Persistent
{

Property Title As%String(MAXLEN = 255) [ Required ];Property Body As%String(MAXLEN = "") [ Required ];Property Author As DC.Demo.Usr [ Required ];Property Draft As%Boolean [ InitialExpression = 1, Required ]; }

Class DC.Demo.Usr Extends%Persistent {

Property Name As%String [ Required ]; }

Class DC.Demo.Comment Extends%Persistent {

Property Post As DC.Demo.Post [ Required ];Property Usr As DC.Demo.Usr [ Required ];Property Comment As%String(MAXLEN = "") [ Required ]; }

Et notre requête, comme point de départ:

selectIDfrom DC_Demo.Post where (Author = ? orIDin (selectdistinct Post from DC_Demo.Comment where Usr = ?)) and Draft = 0

L' approche naïve consisterait simplement à:

  • Ajoutez des indices bitmap sur Author et Draft dans DC.Demo.Post.
  • Ajoutez un index standard sur (Usr, Post) dans DC.Démo.Commentaire..

Et ce n'est pas du tout une mauvaise approche! Pour certains cas d'utilisation, elle peut même être " suffisante ". Que va faire IRIS SQL sous le capot ? Nous pouvons examiner le plan de requête:

 Générer un flux de valeurs idkey en utilisant la combinaison multi-index:
     ((bitmap index DC_Demo.Post.Draft) INTERSECT ((bitmap index DC_Demo.Post.Author) UNION (bitmap index DC_Demo.Post.Draft)))
 Pour chaque valeur d'idkey:
     Affichage de la ligne.

Sous-requête C:
 Lecture de la carte d'index DC_Demo.Comment.UsrPost, en utilisant l'Usr et le Post donnés, et en bouclant sur l'ID.
 Pour chaque ligne:
     Détermination du résultat de la sous-requête.

Ce n'est pas dramatique. Supposons qu'il y ait 50000 publications et que chaque utilisateur ait commenté 500 d'entre elles en moyenne. Combien de références globales cette requête implique-t-elle? Eh bien, au minimum, trois pour les index bitmap, et environ 500 dans la sous-requête (itération sur l'index UsrPost). Il est clair que la sous-requête est le goulot d'étranglement. Comment pouvons-nous la rendre plus rapide?

La réponse est d'utiliser un index fonctionnel (une sous-classe de %Library.FunctionalIndex) avec la %FIND condition de prédicat (et une sous-classe de %SQL.AbstractFind). Notre index fonctionnel sera défini dans la classe Comment (commentaires), mais ne contiendra pas les identifiants des commentaires comme le ferait un index bitmap classique. Au lieu de cela, pour chaque utilisateur, il aura un bitmap d'identifiants de Post pour lesquels cet utilisateur a au moins un commentaire. Nous pouvons ensuite combiner très efficacement cette image bitmap avec d'autres conditions indexées par image bitmap dans la table Post. Il est évident que cela entraîne une certaine surcharge pour l'insertion/mise à jour/suppression de nouveaux commentaires, mais l'avantage en termes de performances pour les lectures peut la compenser.

Un index fonctionnel doit définir le comportement de l'index pour les opérations d'insertion, de mise à jour et de suppression, et mettre en œuvre quelques autres méthodes (purge, début de tri, fin de tri). Une Une implémentation %SQL.AbstractFind doit mettre en œuvre des méthodes pour parcourir et récupérer des fragments d'index bitmap. Pour s'amuser, nous utiliserons une implémentation générique %SQL.AbstractFind qui examine une structure d'index bitmap standard (avec une référence globale à son nœud racine).

Remarque - si vous ne savez pas ce qu'est un "fragment de bitmap" ou si vous avez l'impression que tout cela est du Chinois, nous vous conseillons de lire la documentation  sur les index de bitmap, en particulier les parties relatives à leur structure et à leur manipulation.

Passons au code, DC.Demo.ExistenceIndex est notre index fonctionnel:

Include %IFInclude/// Données:/// /// <code>/// Class Demo.ClassC Extends %Persistent/// {/// Properiété PropA As Demo.ClassA;/// Properiété PropB As Demo.ClassB;/// Index BValuesForA On (PropA, PropB) As DC.Demo.ExistenceIndex;/// }/// </code>/// /// Appel à partir de SQL comme suit, étant donné une valeur de PropA de 21532, pour retourner les valeurs de PropB associées à PropA=21532 dans ClassB:/// <code>/// selectionner * de Demo.ClassC où ID %FIND Demo.ClassB_BValuesForAFind(21532) et <other-bitmap-index-conditions>/// </code>Class DC.Demo.ExistenceIndex Extends%Library.FunctionalIndex [ System = 3 ]
{

/// Retourne une sous-classe %SQL.AbstractFind appropriée pour cet index fonctionnelClassMethod Find(pSearch As%Binary) As%Library.Binary [ CodeMode = generator, ServerOnly = 1, SqlProc ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) Set name = $Name(@tIdxGlobal@("id")) Set name = $Replace(name,$$$QUOTE("id"),"pSearch") $$$GENERATE(" Quit ##class(DC.Demo.ReferenceFind).%New($Name("name"))") } }

/// Retrouve un "true" s'il existe un enregistrement avec (prop1val, prop2val).ClassMethod Exists(prop1val, prop2val) [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set indexProp1 = $$$comSubMemberKeyGet(%class,$$$cCLASSindex,%property,$$$cINDEXproperty,1,$$$cINDEXPROPproperty) Set indexProp2 = $$$comSubMemberKeyGet(%class,$$$cCLASSindex,%property,$$$cINDEXproperty,2,$$$cINDEXPROPproperty) Set table = $$$comClassKeyGet(%class,$$$cCLASSsqlschemaname)"."$$$comClassKeyGet(%class,$$$cCLASSsqltablename) Set prop1 = $$$comMemberKeyGet(%class,$$$cCLASSproperty,indexProp1,$$$cPROPsqlfieldname) If (prop1 = "") { Set prop1 = indexProp1 } Set prop2 = $$$comMemberKeyGet(%class,$$$cCLASSproperty,indexProp2,$$$cPROPsqlfieldname) If (prop2 = "") { Set prop2 = indexProp2 } $$$GENERATE(" &sql(select top 1 1 from "table" where "prop1" = :prop1val and "prop2" = :prop2val)") $$$GENERATE(" Quit (SQLCODE = 0)") } }

/// Cette méthode est invoquée lorsqu'une nouvelle instance d'une classe est insérée dans la base de donnéesClassMethod InsertIndex(pID As%CacheString, pArg... As%Binary) [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) Set name = $Name(@tIdxGlobal@("id","chunk")) Set name = $Replace(name,$$$QUOTE("chunk"),"chunk")

    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">" If ($Get(pArg(1)) '= """") &amp;&amp; ($Get(pArg(2)) '= """") { "</span>)
    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">"  $$$IFBITOFFPOS(pArg(2),chunk,position)"</span>)
    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">"  Set $Bit("</span>_<span class="hljs-built_in">$Replace</span>(name,<span class="hljs-built_in">$$$QUOTE</span>(<span class="hljs-string">"id"</span>),<span class="hljs-string">"pArg(1)"</span>)_<span class="hljs-string">",position) = 1"</span>)
    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">" }"</span>)
}

}

/// Cette méthode est invoquée lorsqu'une instance existante d'une classe est mise à jour.ClassMethod UpdateIndex(pID As%CacheString, pArg... As%Binary) [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) Set name = $Name(@tIdxGlobal@("id","chunk")) Set name = $Replace(name,$$$QUOTE("chunk"),"chunk") $$$GENERATE(" If ($Get(pArg(3)) '= """") && ($Get(pArg(4)) '= """") { ") $$$GENERATE(" $$$IFBITOFFPOS(pArg(4),chunk,position)") $$$GENERATE(" Set $Bit("$Replace(name,$$$QUOTE("id"),"pArg(3)")",position) = .."%property"Exists(pArg(3),pArg(4))") $$$GENERATE(" }")

    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">" If ($Get(pArg(1)) '= """") &amp;&amp; ($Get(pArg(2)) '= """") { "</span>)
    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">"  $$$IFBITOFFPOS(pArg(2),chunk,position)"</span>)
    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">"  Set $Bit("</span>_<span class="hljs-built_in">$Replace</span>(name,<span class="hljs-built_in">$$$QUOTE</span>(<span class="hljs-string">"id"</span>),<span class="hljs-string">"pArg(1)"</span>)_<span class="hljs-string">",position) = 1"</span>)
    <span class="hljs-built_in">$$$GENERATE</span>(<span class="hljs-string">" }"</span>)
}

}

/// Cette méthode est invoquée lorsqu'une instance existante d'une classe est supprimée.ClassMethod DeleteIndex(pID As%CacheString, pArg... As%Binary) [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) Set name = $Name(@tIdxGlobal@("id","chunk")) Set name = $Replace(name,$$$QUOTE("chunk"),"chunk") $$$GENERATE(" If ($Get(pArg(1)) '= """") && ($Get(pArg(2)) '= """") { ") $$$GENERATE(" $$$IFBITOFFPOS(pArg(2),chunk,position)") $$$GENERATE(" Set $Bit("$Replace(name,$$$QUOTE("id"),"pArg(1)")",position) = .."%property"Exists(pArg(1),pArg(2))") $$$GENERATE(" }") } }

/// Méthode auxiliaire permettant d'obtenir la référence globale pour le stockage d'un index donné.ClassMethod IndexLocationForCompile(pClassName As%String, pIndexName As%String) As%String { Set tStorage = ##class(%Dictionary.ClassDefinition).%OpenId(pClassName).Storages.GetAt(1).IndexLocation Quit$Name(@tStorage@(pIndexName)) }

/// Purge l'indexClassMethod PurgeIndex() [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) $$$GENERATE(" Kill " _ tIdxGlobal) } }

/// Appelle SortBegin avant les opérations de masseClassMethod SortBeginIndex() [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) // No-op$$$GENERATE(" Quit") } }

/// Appelle SortEnd après les opérations de masseClassMethod SortEndIndex(pCommit As%Integer = 1) [ CodeMode = generator, ServerOnly = 1 ] { If (%mode '= "method") { Set tIdxGlobal = ..IndexLocationForCompile(%class,%property) // No-op$$$GENERATE(" Quit") } }

}

DC.Demo.ReferenceFind est notre implémentation générique de %SQL.AbstractFind qui permet de visualiser un tableau de fragments de cartes bitmap:

/// Utility class to wrap use of %SQL.AbstractFind against a bitmap index global referenceClass DC.Demo.ReferenceFind Extends%SQL.AbstractFind [ System = 3 ]
{

/// Référence globale à itérer sur / prendre en compte pour les méthodes d'opération %SQL.AbstractFind %FINDProperty reference As%String [ Private ]; Method %OnNew(pReference As%String) As%Status [ Private, ServerOnly = 1 ] { Set..reference = pReference Quit$$$OK }

Method NextChunk(ByRef pChunk As%Integer = "") As%Binary { Set pChunk=$Order(@i%reference@(pChunk),1,tChunkData) While pChunk'="",$bitcount(tChunkData)=0 { Set pChunk=$Order(@i%reference@(pChunk),1,tChunkData) } Return$Get(tChunkData) }

Method PreviousChunk(ByRef pChunk As%Integer = "") As%Binary { Set pChunk=$Order(@i%reference@(pChunk),-1,tChunkData) While pChunk'="",$bitcount(tChunkData)=0 { Set pChunk=$Order(@i%reference@(pChunk),-1,tChunkData) } Return$Get(tChunkData) }

Method GetChunk(pChunk As%Integer) As%Binary { If$Data(@i%reference@(pChunk),tChunkData) { Return tChunkData } Else { Return"" } }

}

Ainsi, DC.Demo.Comment ressemble maintenant à ceci, avec deux indices bitmap ajoutés (et les clés externes appropriées pour faire bonne mesure).:

Class DC.Demo.Comment Extends%Persistent
{

Property Post As DC.Demo.Post [ Required ];Property Usr As DC.Demo.Usr [ Required ];Property Comment As%String(MAXLEN = "") [ Required ]; Index Usr On Usr [ Type = bitmap ]; Index Post On Post [ Type = bitmap ]; Index UserPosts On (Usr, Post) As DC.Demo.ExistenceIndex; ForeignKey UsrKey(Usr) References DC.Demo.Usr(); ForeignKey PostKey(Post) References DC.Demo.Post() [ OnDelete = cascade ]; }

Notre requête SQL devient alors:

selectIDfrom DC_Demo.Post where (Author = ? orID %FIND DC_Demo.Comment_UserPostsFind(?)) and Draft = 0

Et le plan de requête devient:

 Générer un flux de valeurs idkey en utilisant la combinaison multi-index:
     ((bitmap index DC_Demo.Post.Draft) INTERSECT ((bitmap index DC_Demo.Post.Author) UNION (given bitmap filter for DC_Demo.Post.%ID)))
 Pour chaque valeur d'idkey:
     Afficher la ligne.

Combien de références globales y a-t-il maintenant ? Une pour Author bitmap, une pour Draft bitmap, et une pour le nœud d'index de bitmap "posts for a given user" dans DC.Demo.Comment. Désormais, la liste "Quels sont les publications auxquelles j'ai participé?" ne sera pas (autant) ralentie si vous commentez de plus en plus!

Avertissement : malheureusement, la communauté des développeurs n'est pas réellement soutenue par InterSystems IRIS, vous ne devriez donc probablement pas faire autant de commentaires.

0
0 37
Article Benjamin De Boe · Juil 24, 2024 6m read

Nous sommes ravis de continuer à déployer de nouvelles fonctionnalités dans InterSystems IRIS Cloud SQLInterSystems IRIS Cloud SQL, telles que la nouvelle capacité de recherche vectorielle Vector Search qui a été lancée pour la première fois avec InterSystems IRIS 2024.1. Le service Cloud SQL est un service en nuage qui offre précisément ce qui suit: l'accès SQL dans le cloud. Cela signifie que vous utiliserez des technologies de pilote standard telles que JDBC, ODBC et DB-API pour vous connecter à ce service et accéder à vos données. La documentation décrit en détail comment configurer les paramètres importants au niveau du pilote, mais ne présente pas les outils tiers spécifiques car, comme vous pouvez l'imaginer, il en existe un nombre infini.

Dans cet article, nous allons compléter cette documentation de référence avec des étapes plus détaillées pour un outil de visualisation de données tiers populaire que plusieurs de nos clients utilisent pour accéder aux données basées sur IRIS : Microsoft Power BI.

Étape 0: Création de votre déploiement

Tout d'abord, connectez-vous au portail des services Cloud Services Portal et créez un déploiement Cloud SQL. Il vous ne faut qu'une chose: cochez la case permettant d'activer les connexions externes. À part cela, tous les paramètres par défaut devraient fonctionner correctement.

Étape 1: Téléchargement du certificat

Afin de se connecter en toute sécurité, nous utiliserons des certificats pour crypter tout ce qui est envoyé sur le réseau. Vous pouvez télécharger le certificat à partir de la page des détails du déploiement en cliquant sur le bouton "Get X.509 certificate" (Obtenir un certificat X.509):

Nous devrons nous référer à ce certificat plus tard, il faudra donc l'enregistrer dans un répertoire approprié. Par exemple, j'utilise C:\Users\bdeboe\odbc\.

Étape 2: Création du fichier SSLDefs.ini

Pour savoir quels certificats et paramètres de cryptage utiliser, le pilote ODBC d'InterSystems recherche un fichier SSLDefs.ini, que nous allons créer ensuite. Par défaut, il recherche ce fichier dans  C:\Program Files (x86)\Common Files\InterSystems\IRIS, mais vous pouvez modifier cet emplacement à l'aide de la variable d'environnement ISC_SSLconfigurationsISC_SSLconfigurations. Pour conserver tous mes paramètres de configuration ensemble, j'ai défini cette variable à C:\Users\bdeboe\odbc\, le répertoire où j'ai également sauvegardé mon certificat.

Le fichier SSLDefs.ini doit contenir deux éléments pour qu'ODBC sache comment se connecter : une configuration de serveur et une configuration SSL. La configuration du serveur déclare simplement le nom de la configuration SSL à utiliser pour une combinaison particulière de nom d'hôte et de port, et la configuration SSL contient tous les détails nécessaires à l'établissement de la connexion cryptée. Il est donc facile de réutiliser une seule configuration SSL pour plusieurs serveurs. Voici le contenu de mon fichier SSLDefs.ini:

[My CloudSQL Server]
Address=k8s-da0bcd5e-a1b3a0c7-545df92ec8-2e44304cebef1543.elb.us-east-1.amazonaws.com
Port=443
SSLConfig=SampleSSLConfig

[SampleSSLConfig] CAFile= CertFile=C:\Users\bdeboe\odbc\certificateSQLaaS.pem KeyFile= Password= KeyType=2 Protocols=28 CipherList=ALL:!aNULL:!eNULL:!EXP:!SSLv2 VerifyPeer=0 VerifyDepth=9

La première section contient la configuration du serveur auquel vous pouvez donner un nom de votre choix. Vous devrez modifier l'adresse pour qu'elle corresponde au nom d'hôte de votre déploiement Cloud SQL, qui peut être obtenu à partir de la page des détails du déploiement où vous avez téléchargé le certificat.

La deuxième section contient la configuration SSL, dont le nom doit correspondre à ce que vous avez spécifié pour SSLConfig dans la section de configuration du serveur. La valeurCertFile doit évidemment correspondre à l'endroit où vous avez sauvegardé votre certificat.

Pour plus de détails sur les autres paramètres, veuillez vous référer à la documentation complète sur les paramètres TLS.

Étape 3: Création du DSN de type ODBC

Power BI, comme la plupart des outils basés sur ODBC, fonctionne avec un DSN (Data Source Name), que vous enregistrez à l'aide d'un utilitaire Windows. Il suffit de cliquer sur l'icône Start (Démarrer) de Windows et de taper "ODBC", puis de cliquer sur "ODBC Data Sources (64 bit)" (Sources de données ODBC (64 bit)). Choisissez l'onglet "System DSN" (DSN du système) pour enregistrer une connexion à notre déploiement Cloud SQL. Si vous avez des installations locales d'InterSystems IRIS (j'en ai une douzaine à tout moment 😉), vous verrez que le programme d'installation a créé des entrées DSN par défaut pour:

Cliquez sur "Add..." (Ajouter...) pour créer un nouveau DSN, en choisissant un nom et en renseignant l'hôte, le port et l'espace de noms. J'enregistre habituellement mon nom d'utilisateur et mon mot de passe dans le DSN pour toute instance non productive (et nous en aurons besoin pour tester la connexion dans quelques instants), mais vous pouvez laisser ces champs vides et fournir ces informations d'identification plus tard. Le champ Nom du serveur SSL/TLS est quelque peu superflu (nous y travaillerons!).

 Ensuite, cliquez sur "Test Connection" (Tester la connexion) pour vérifier que tout fonctionne comme prévu. Vous devriez obtenir un message "Connectivity test completed successfully!" (Test de connectivité terminé avec succès). Si ce n'est pas le cas, vérifiez les étapes ci-dessus ou reportez-vous au Guide de dépannage. Un message d'erreur particulier peut vous laisser perplexe (en tout cas, il m'a laissé perplexe !): "No SSL config found in the registry or in ssldefs.ini" (Aucune configuration SSL trouvée dans le registre ou dans ssldefs.ini). Cette erreur signifie que le pilote ODBC n'a pas trouvé de correspondance pour votre combinaison nom d'hôte/port dans le fichier SSLDefs.ini. Comme votre nom d'hôte change à chaque fois que vous créez un nouveau déploiement, vous devrez mettre à jour ou ajouter les configurations de serveur pour chacun d'entre eux.

Étape 4: Connexion à partir de Power BI

Il est maintenant temps d'utiliser notre DSN ODBC pour extraire des données dans Power BI. Après avoir ouvert l'application, sélectionnez la commande "Get Data" (Obtenir des données) ou "Get data from other sources" (Obtenir des données à partir d'autres sources), et choisissez l'option ODBC:

Ensuite, choisissez le DSN que vous venez de créer dans la liste:

Dans l'écran suivant, vous pouvez indiquer votre nom d'utilisateur et votre mot de passe. Aucune propriété des informations d'identification supplémentaire n'est requise.

 Et c'est tout! Vous pouvez maintenant sélectionner les tables que vous souhaitez inclure dans vos rapports Power BI:

Comme vous l'avez probablement remarqué, toutes les étapes de cet article, à l'exception de la dernière, sont universelles pour la configuration ODBC, ce qui devrait vous permettre d'utiliser la plupart des outils basés sur ODBC. J'espère que cet article vous a permis d'avancer, et n'hésitez pas à ajouter vos propres trucs et astuces, ou à partager vos expériences sur la connexion à Cloud SQL. Notez également qu'il n'y a pratiquement rien ici, à part l'étape 0, qui soit spécifique à Cloud SQL, donc vous pouvez utiliser les mêmes étapes pour vous connecter à n'importe quelle instance IRIS qui nécessite des connexions cryptées.

0
0 105
Article Pierre LaFay · Juin 26, 2024 2m read

InterSystems FAQ rubric

Le type TIMESTAMP correspond au type de données %Library.TimeStamp (=%TimeStamp) dans les produits InterSystems, et le format est YYYY-MM-DD HH:MM:SS.nnnnnnnnn.

Si vous souhaitez modifier la précision après la virgule, définissez-la à l'aide de la méthode suivante.

1) Définir la précision à l'échelle du système

Portail de gestion : [Administration du système] > [Configuration] > [Paramètres SQL et objets] > [Paramètres SQL généraux] 
Précision de l'heure par défaut pour GETDATE(), CURRENT_TIME, CURRENT_TIMESTAMP. Vous pouvez spécifier le nombre de chiffres entre 0 et 9.

0
0 45
Article Pierre LaFay · Juin 26, 2024 1m read

InterSystems FAQ rubric

Pour désactiver le délai d'attente, réglez le délai d'attente de la requête sur désactivé dans les paramètres DSN :

Panneau de configuration de Windows > Outils d'administration > Sources de données (ODBC) > Configuration DSN du système

Si vous cochez la case Désactiver le délai d'attente des requêtes, le délai d'attente sera désactivé.

Si vous souhaitez le modifier du côté de l'application, vous pouvez le définir au niveau de l'API ODBC.

0
0 53
Article Pierre LaFay · Juin 26, 2024 1m read

Récemment, j'ai voulu obtenir une liste de toutes les requêtes mises en cache et de leurs textes. Voici comment procéder.

Créez d'abord une procédure SQL renvoyant le texte de la requête mise en cache à partir d'un nom de routine de requête mise en cache :

Class test.CQ
{

/// SELECT test.CQ_GetText()
ClassMethod GetText(routine As %String) As %String [ CodeMode = expression, SqlProc ]
{
##class(%SQLCatalog).GetCachedQueryInfo(routine)
}

}

Ensuite, vous pouvez exécuter cette requête :

SELECT Routine, test.CQ_GetText(Routine)
FROM %SQL_Manager.CachedQueryTree()
0
0 42
Article Guillaume Rongier · Juin 24, 2024 10m read

InterSystems IRIS dispose d'une série de dispositifs facilitant la capture, la persistance, l'interopérabilité et la génération d'informations analytiques à partir de données au format XML. Cet article vous montrera comment procéder:

  1. Capture du XML (via un fichier dans notre exemple);
  2. Traitement des données capturées en interopérabilité;
  3. Persistance du XML dans les entités/tables persistantes;
  4. Création des vues analytiques pour les données XML capturées.

Capture des données XML

L'InterSystems IRIS dispose de nombreux adaptateurs intégrés pour capturer des données, notamment les suivants:

  1. Adaptateur de fichiers : utilisé pour obtenir des fichiers à partir de dossiers de réseau.
  2. Adaptateur FTP : utilisé pour obtenir des fichiers à partir de serveurs FTP/SFTP. 
  3. Adaptateur SOAP/Services Web : utilisé pour recevoir des données XML à partir d'opérations de services Web.
  4. Adaptateurs HTTP: utilisés pour acquérir des données et des fichiers XML à partir de points de terminaison HTTP.
  5. D'autres adaptateurs peu courants pour obtenir des données XML, par exemple des adaptateurs de messagerie. Vous pouvez les trouver à l'adresse suivante http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_interop_protocols.

Pour capturer des données à l'aide de productions d'interopérabilité, il faut configurer une production et utiliser un service métier Business Service associé à un adaptateur approprié. Les services métier les plus courants sont énumérés ci-dessous:

  1. EnsLib.XML.Object.Service.FileService. C'est l'option que je préfère car elle utilise un adaptateur de fichier pour obtenir un fichier XML à partir du réseau et le charger sur des objets mappés en schéma XML. C'est l'approche que nous emploierons dans cet article.
  2. EnsLib.XML.Object.Service.FTPService. Il utilise un adaptateur FTP pour acquérir un fichier XML à partir d'un serveur FTP et le charger sur des objets mappés en schéma XML.
  3. EnsLib.XML.FileService. Il utilise un adaptateur de fichier pour obtenir un fichier XML à partir du réseau et le charger sur un flux de fichiers File Stream.
  4. EnsLib.XML.FTPService. Il utilise un adaptateur FTP pour obtenir un fichier XML à partir du serveur FTP et le charger sur un flux de fichiers File Stream.
  5. EnsLib.HTTP.GenericService et EnsLib.HTTP.Service. Ils utilisent un adaptateur HTTP pour consommer un point de terminaison HTTP et acquérir un contenu du fichier XML.
  6. EnsLib.SOAP.GenericService et EnsLib.SOAP.Service. Ils utilisent un adaptateur SOAP pour consommer un point de terminaison SOAP et recevoir un contenu du fichier XML.

Persistance et/ou interopérabilité du XML capturé

Pour rendre persistantes ou envoyer (interopérer) les données XML, vous pouvez utiliser tous les adaptateurs mentionnés ci-dessus, mais vous devez également inclure l'adaptateur SQL. Il est utilisé pour conserver les données dans les bases de données SGBDR, par exemple la base de données IRIS. Vous trouverez ci-dessous la liste des adaptateurs couramment utilisés pour l'interopérabilité:

  1. Adaptateur SQL : pour interopérer les données vers les bases de données cibles.
  2. Adaptateur Kafka: pour interopérer les données de manière asynchrone dans des rubriques Kafka.
  3. Adaptateur REST: pour interagir avec les API REST.
  4. Adaptateurs PEX: pour interagir avec les composants natifs Java, dotNet ou Python.  

Pour interopérer ou conserver des données à l'aide de productions d'interopérabilité, il faut configurer une production et utiliser une opération métier associée à un adaptateur approprié. Les opérations métier les plus couramment utilisées sont les suivantes:

  1. EnsLib.SQL.Operation.GenericOperation: utilisée pour conserver les données capturées dans les bases de données SQL et IRIS.
  2. EnsLib.Kafka.Operation: utilisée pour publier les données capturées/traitées dans les rubriques Kafka. 
  3. EnsLib.REPOS.GenericOperation: utilisée pour envoyer des données capturées/traitées aux méthodes des API REST, permettant des intégrations via des API REST.
  4. EnsLib.SAVON.GenericOperation: utilisée pour envoyer des données capturées/traitées aux méthodes de service Web SOAP, permettant des intégrations via des services Web SOAP.
  5. EnsLib.PEX.BusinessOperation: utilisée pour envoyer des données capturées/traitées aux composants Java, dotNet et Python natifs.
  6. EnsLib.XML.Objet.Opération.Ftoperation et EnsLib.XML.Objet.Opération.FileOperation: utilisées pour enregistrer des données XML sous forme de fichier à partir de données d'objet dans des serveurs FTP et des emplacements de système de fichiers Filesystem.

Entre les données capturées à l'aide des services métier et les données envoyées par les opérations métier, il est possible d'utiliser un processus métier pour mettre en œuvre des règles/logiques métier ou pour mapper et traduire le format et la structure des données du service métier à l'opération métier. Les types de processus métier les plus courants sont les suivants:

  1. Ens.BusinessProcessBPL. Il implémente la logique métier à l'aide du langage visuel BPL.
  2. EnsLib.MsgRouter.RoutingEngine. Il est utilisé pour mettre en œuvre la logique de mappage et de traduction afin de convertir les données capturées dans le protocole/la structure utilisé(e) par les opérations métier.
  3. EnsLib.PEX.BusinessProcess. Il est utilisé pour mettre en œuvre la logique métier via Java, DotNet ou Python.

En reprenant le système d'interopérabilité InterSystems IRIS, nous avons ce qui suit:


Pour illustrer et matérialiser l'interopérabilité des données XML, nous allons utiliser un exemple d'application Open Exchange.

Interopérabilité XML: un échantillon

Installer l'échantillon

1. Clone/git extrait le référentiel dans n'importe quel répertoire local.

$ git clone https://github.com/yurimarx/iris-xml-sample.git

2. Ouvrez le terminal dans ce répertoire et lancez:

$ docker-compose build

3. Lancez le conteneur IRIS avec votre projet:

$ docker-compose up -d

 

Lancement de la production d'échantillons

1. Ouvrez le lien http://localhost:52796/csp/user/EnsPortal.ProductionConfig.zen?$NAMESPACE=USER&$NAMESPACE=USER& 
2. Cliquez sur le bouton Start et voyez tous les rubriques en vert:


CConfiguration du VSCode pour ce projet

1. Ouvrez le code source dans VSCode:


2. Dans le pied de page, recherchez le bouton ObjectScript (uniquement s'il n'est pas encore connecté):

3. Cliquez dessus et sélectionnez "Toggle Connection" en haut de la page:

4. Vous avez maintenant le VSCode et le serveur IRIS connectés à l'espace de noms de l'utilisateur USER:

Traitement d'un échantillon XML

1. Accédez à l'onglet Explorateur:

2. Sélectionnez le fichier books.xml et copiez-le dans le dossier xml_input:

3. Une ou deux secondes plus tard, le fichier books.xml sera traité et supprimé du dossier (VSCode affiche le fichier comme étant effacé et le supprime).
4. Vous pouvez maintenant voir les résultats dans l'éditeur de production: http://localhost:52796/csp/user/EnsPortal.ProductionConfig.zen?$NAMESPACE=USER&$NAMESPACE=USER&
5. Accédez à l'onglet Messages et cliquez sur la première session de la liste:

6. Consultez l'onglet Contenu:

7. Accédez maintenant à l'éditeur SQL: http://localhost:52796/csp/sys/exp/%25CSP.UI.Portal.SQL.Home.zen?$NAMESPACE=USER&$NAMESPACE=USER 

8. Exécutez le SQL suivant et regardez les résultats:

SELECTID, author, description, genre, price, publish, title, totalDays
FROM dc_XmlDemo.Catalog


À ce stade, nous allons découvrir le code source de cet échantillon.

Derrière les coulisses : le code source

Création d'un mappage de classe pour le schéma XML

1. Ouvrez le fichier books.xml et copiez son contenu:

2. Nous devons créer un schéma XML pour ce fichier XML au cas où il n'existerait pas encore. J'ai utilisé ce site : https://www.liquid-technologies.com/online-xml-to-xsd-converter. Cependant, il existe de nombreuses autres possibilités en ligne. Il faut donc insérer le contenu XML et cliquer sur Générer un schéma.

3. Copiez le schéma XML généré et créez le fichier books.xsd avec son contenu.:

4. Accédez au terminal IRIS. Pour ce faire, cliquez sur le bouton docker:iris:52796[USER] dans le pied de page et sélectionnez l'option Ouvrir le terminal dans Docker:


5. Écrivez les commandes comme indiqué ci-dessous:

USER>set reader = ##class(%XML.Utils.SchemaReader).%New()              
USER>do reader.Process("/home/irisowner/dev/xml_input/books.xsd","dc.XmlDemo.Schemas")


6. Cette méthode de classe IRIS crée pour vous des classes qui correspondent à la structure XML, ce qui vous permet d'accéder au XML par le biais de classes, de propriétés et de méthodes:


Création de la classe persistante pour stocker les livres ingérés à partir de données XML

1. Créez le fichier Catalog.cls dans le dossier src/dc/XmlDemo avec le contenu suivant:

Class dc.XmlDemo.Catalog Extends%Persistent
{

Property author As%String(MAXLEN = 200);Property title As%String;Property genre As%String;Property price As%Double;Property publish As%Date;Property totalDays As%Integer;Property description As%String(MAXLEN = ""); }


2. Je ne comprends pas bien cette phrase. Peut-être que l'auteur voulait dire : "Cette classe élargit la classe %Persistent, ce qui nous permet de stocker des données persistantes dans la base de données".
3. Ces propriétés reflètent les données XML. Cependant, l'une d'entre elles, totalDays, n'est pas présente dans les données XML. Elle sera calculée en fonction du nombre de jours écoulés entre la publication et le jour actuel. Vous devez enregistrer cette classe pour la créer sur le serveur IRIS.

Création des informations d'identification pour accéder à la base de données IRIS à partir de la production

1. Accéder à Interopérabilité > Configuration > Informations d'identification et créer une référence IrisCreds:

  • Identifiant: IrisCreds
  • Nom de l'utilisateur: _SYSTEM
  • Mot de passe: SYS

2. Cliquez sur Enregistrer (Save).


Création de la Production d'Interopérabilité

1. Accéder à Interopérabilité &gt ; Liste &gt ; Productions:


2. Créez une nouvelle production en cliquant sur le bouton Nouveau (New).
3. Saisissez les valeurs conformément à l'image ci-dessous et cliquez sur le bouton OK:

4. Cliquez sur le bouton + à côté des Services:


5. Définissez les options comme indiqué ci-dessous:

6. Remplissez les chemins d'accès au fichier XML avec les données suivantes:

  • Chemin d'accès au fichier: /home/irisowner/dev/xml_input/
  • Spécification du fichier: *.xml
  • Chemin d'accès à l'Archive: /home/irisowner/dev/xml_output/

7. Saisissez le nom de la classe et le nom du composant pour obtenir les données relatives aux éléments du livre au moment de l'exécution:

8. Cliquez sur le bouton Appliquer (Apply).
9. À ce stade, il est préférable d'utiliser Java Gateway car nous allons établir une connexion JDBC avec la base de données du serveur IRIS pour envoyer des commandes d'insertion SQL et sauvegarder les données. Cette approche est valable pour tous les fournisseurs de bases de données, y compris Oracle, SQL Server, DB2, MySQL et PostgreSQL, lorsque vous devez rendre persistantes des données XML dans une table SQL.
10. Cliquez à nouveau sur le bouton + à côté des Services. Saisissez les champs comme illustré ci-dessous et cliquez sur le bouton OK:


11. Choisissez la passerelle JavaGateway et saisissez les données suivantes dans le champ de chemin d'acces à la classe:

  • Chemin d'acces à la classe: /usr/irissys/dev/java/lib/1.8/*.jar


12. Ce chemin contient le pilote JDBC de la base de données IRIS.
13. Cliquez sur le bouton Appliquer (Apply).
14. Cliquez sur le bouton + à côté des Opérations.
15. Saisissez les valeurs et cliquez sur le bouton OK:


16. Choisissez SqlOperation et saisissez le DSN avec le nom de l'utilisateur (espace de noms dans lequel la table SQL du livre est disponible).
17. Sélectionnez IrisCreds dans le champ des Informations d'identification.
18. Écrivez la commande SQL suivante dans le champ de requête:

insertinto dc_XmlDemo.Catalog(author, description, genre, price, publish, title,totalDays) values (?,?,?,?,DATE(?),?,DATEDIFF('d',?,CURRENT_DATE))


19. Saisissez la valeur dc.XmlDemo.Schemas.book dans RequestClass:

20. Cliquez sur le bouton + à côté de Ajouter (Add) et cliquez sur le bouton Liste à côté du bouton X pour choisir le champ du premier paramètre ‘?’:

21. Sélectionnez *author et cliquez sur le bouton OK:

22. Incluez plus de paramètres pour obtenir les résultats affichés ci-dessous:

23. Il est essentiel de vérifier si vos valeurs ont * avant le champ.
24. Cliquez sur le bouton Appliquer (Apply).
25. Maintenant, choisissez à nouveau XmlFileService et définissez le champ des noms de configuration cible (Target Config Names) sur SqlOperation. Cela permettra au service de recevoir les données XML et d'envoyer les valeurs à l'opération SqlOperation enregistrée dans la base de données.

26. Arrêtez la production créée dans l'exemple avant de lancer celle que vous avez développée:

27. Cliquez sur Ouvrir (Open) et l'arrêter (Stop):

28. Sélectionnez la production dont vous avez besoin: 
29. Sélectionnez votre nouvelle production, ouvrez-la et démarrez-la.
30. Dans VSCode, copiez le fichier books.xml dans le dossier xml_input pour tester votre production.
31. Observez les résultats comme indiqué dans la section d'échantillon XML de processus (Process XML Sample) et profitez-en!

0
1 100
Annonce Irène Mykhailova · Juin 11, 2024

Bonjour à tous,

L'équipe de certification d'InterSystems Learning Services développe un examen de certification InterSystems ObjectScript Specialist, et nous contactons la communauté pour obtenir des commentaires qui nous aideront à évaluer et à établir le contenu de cet examen. Veuillez noter qu'il s'agit de l'un des deux examens en cours de développement pour remplacer notre examen InterSystems IRIS Core Solutions Developer. Vous pouvez trouver plus de détails sur notre examen InterSystems IRIS Developer Professional ici.

0
0 36
Annonce Irène Mykhailova · Mai 9, 2024

Bonjour la communauté IRIS,

Dans le cadre du développement d'un examen de certification pour les spécialistes SQL d'InterSystems IRIS, InterSystems Certification souhaite que vous participiez au test bêta de l'examen si vous correspondez à la description du candidat à l'examen présentée ci-dessous. L'examen sera disponible pour un test bêta du 9 au 12 juin 2024 lors du sommetInterSystems Global Summit 2024, mais uniquement pour les personnes inscrites au sommet (visitez cette page pour en savoir plus sur la Certification au GS24). Les tests bêta seront ouverts à tous les autres bêta-testeurs intéressés le 24 juin 2024. Toutefois, les bêta-testeurs intéressés peuvent s'inscrire dès maintenant en envoyant un courriel à certification@intersystems.com (veuillez nous indiquer si vous effectuerez le bêta-test au Sommet mondial ou dans notre environnement surveillé en ligne) Les tests bêta doivent être terminés au plus tard le 2 août 2024.

Quelles sont mes responsabilités en tant que bêta-testeur?

L'examen vous sera attribué et vous devrez le passer avant le 2 août 2024. L'examen sera organisé dans un environnement surveillé en ligne (surveillé en direct pendant le sommet), gratuitement (les frais standard de 150$ par examen sont supprimés pour tous les bêta-testeurs), puis l'équipe d'InterSystems Certification effectuera une analyse statistique minutieuse de toutes les données du test bêta afin de fixer un score de passage pour l'examen. L'analyse des résultats du test bêta prendra de 6 à 8 semaines, et une fois le score de passage établi, vous recevrez une notification par courriel d'InterSystems Certification vous informant des résultats. Si votre score à l'examen est égal ou supérieur au score de passage, vous aurez obtenu la certification! 

Remarque: Les scores des tests bêta sont entièrement confidentiels.

Détails de l'examen

Titre de l'examen: Spécialiste SQL d'InterSystems IRIS

Description du candidat: Un professionnel de l'informatique qui utilise le logiciel SQL d'InterSystems IRIS pour:< / p>

  • concevoir des applications SQL d'InterSystems IRIS,
  • gérer les opérations SQL d'InterSystems IRIS,
  • charger et interroger efficacement des ensembles de données dans le cadre de SQL d'InterSystems IRIS.

Nombre de questions: 48

Temps alloué pour passer l'examen: 2 heures

Préparation recommandée: Révisez le contenu du the tableau ci-dessous avant de participer à l'examen.

Expérience pratique recommandée:

  • Expérience de base avec la norme ANSI SQL
  • 1 à 2 ans d'expérience dans la conception et la gestion d'applications SQL d'InterSystems IRIS ou expertise dans d'autres plateformes SQL et 1 an d'expérience dans la gestion d'applications SQL d'IRIS.
  • Réviser la série de questions pratiques (disponible le 15 mai 2024)

Questions pratiques d'examen

Une série de questions pratiques sera disponible à partir du 15 mai 2024 (sur cette page) et est fournie pour familiariser les candidats avec les formats et les approches des questions.

Format de l'examen

Les questions sont présentées sous deux formes : les questions de choix multiple et les questions de réponse multiple. L'accès à la documentation d'InterSystems IRIS sera disponible pendant l'examen. 

< p>AVERTISSEMENT: Veuillez noter que cet examen est limité à 2 heures. La documentation d'InterSystems sera disponible pendant l'examen, mais les candidats n'auront pas le temps de la consulter pour chaque question. Par conséquent, il est indispensable d'effectuer la préparation recommandée avant de passer l'examen et de ne consulter la documentation qu'en cas de nécessité absolue au cours de l'examen!

Configuration requise pour les tests bêta (veuillez noter que des ordinateurs portables seront fournis et configurés pour répondre à ces exigences lors du sommet mondial)

  • Caméra et microphone fonctionnels
  • Processeur double cœur
  • Au moins 2 Go de mémoire RAM disponible
  • Au moins 500 Mo d'espace disque disponible
  • Vitesse minimale de l'internet:
    • Téléchargement- 500 Ko/s
    • Envoi- 500 Ko/s

Thèmes et contenu de l'examen

L'examen contient des questions qui couvrent les domaines du rôle indiqué, comme le montre le tableau des thèmes d'examen ci-dessous.

Thème

Sous-thème

Connaissances, compétences et aptitudes

1. Conception des applications SQL d'InterSystems IRIS

1. Conception d'un schéma SQL

  1. Identification du rôle de 'bitmap extent index' (index de l'étendue de la représentation en mode point)
  2. Détermination des cas d'utilisation des index
  3. Distinction entre les cas d'utilisation des différents types d'index​
  4. Distinction entre les clés primaires, les clés uniques et les clés d'identification
  5. Identification des propriétés pour les relations de clé étrangère
  6. Identification du comportement des actions référentielles pour la mise à jour et la suppression
  7. Identification des compromis pour ajouter toujours plus d'index
  8. Identification des cas d'utilisation des index composites

2. Conception des schémas avancés

  1. Distinction entre les types de données date/heure

3. Chargement des données

  1. Utilisation de la commande LOAD DATA
  2. Utilisation des tables de diagnostic SQL (%SQL_Diag)
  3. Identification des options d'exportation des données (physiques ou logiques)
 

4. Rédaction de la logique métier

  1. Définition des procédures stockées
  2. Définition des déclencheurs
  3. Identification des options linguistiques pour la rédaction de la logique métier
 

5. Développement d'applications objet/relationnelles

  1. Rappel du mappage objet/relationnel par défaut
  2. Rappel des bonnes pratiques SQL lors de la définition des classes
 

6. Déploiement des applications SQL

  1. Énumération des mécanismes de déploiement des applications SQL
  2. Détermination de la nature de ce qui doit faire partie d'un déploiement

2. Utilisation des systèmes SQL d'InterSystems

1. Gèstion du traitement des requêtes d'IRIS InterSystems

  1. Énumération des éléments pris en compte par l'optimiseur
  2. Distinction entre les erreurs de syntaxe et les erreurs d'exécution
  3. Utilisation de l'index "Statement Index" pour trouver les métadonnées des instructions.
  4. Distinction entre l'utilisation de paramètres et de constantes dans une requête

2. Interprètation des plans de requêtes

  1. Identification des façons d'afficher les plans de requête pour une instruction
  2. Identification des parcours complets des tables (Full Table Scans) dans un plan de requête
  3. Identification de l'utilisation des index dans un plan de requête
  4. Distinction entre les boucles et les recherches dans un plan de requête
  5. Distinction entre les modules invoqués une seule fois et ceux qui sont invoqués à plusieurs reprises dans un plan de requête
  6. Rappel du rôle des statistiques de table dans la planification des requêtes
  7. Utilisation des astuces pour la résolution des problèmes de planification des requêtes
  8. Identification des opportunités pour les index, sur la base d'un plan de requête
  9. Rappel de la signification du coût estimé

3. Utilisation des SQL d'InterSystems IRIS dans des applications

  1. Définition des connexions d'InterSystems IRIS
  2. Identification des étapes de préparation/exécution
  3. Rappel de la manière dont l'utilisation correcte des paramètres permet de se prémunir contre l'injection SQL
  4. Exploitation efficace des contrôles explicites des transactions

4. Utilisation des capacités SQL spécifiques à InterSystems IRIS

  1. Utilisation de SelectMode de manière appropriée
  2. Utilisation de la syntaxe des flèches pour les jointures implicites

5. Utilisation efficace des transactions

  1. Détermination des limites appropriées de la transaction
  2. Utilisation de CommitMode de manière appropriée
  3. Rappel de l'impact des transactions importantes ou de longue durée

2. Gèstion des opérations SQL d'InterSystems IRIS

1. Gèrstion des opérations SQL

  1. Utilisation de la vue de processus SQL pour surveiller l'activité SQL (2022.2+)
  2. Collection des statistiques de table
  3. Utilisation des statistiques d'exécution dans de l'index "Statement Index" pour déterminer des opportunités d'optimisation

2. Gèstion de la sécurité SQL

  1. Attribution des privilèges SQL aux utilisateurs et aux rôles
  2. Distinction entre la vérification des privilèges SQL et la sécurité des applications
  3. Identification de l'impact du lancement de la vérification SQL
 

3. Utilisation de PTools pour une analyse avancée des performances

  1. Distinction entre les mesures de performance "temps consacré", "références globales" et "commandes exécutées"

Est-ce que cela vous intéresse de participer ? Envoyez un courriel certification@intersystems.com maintenant!

0
0 50
Article Sylvain Guilbaud · Avr 30, 2024 3m read

Gitter

Configuration de Production

Cette démo comporte une production d'interopérabilité contenant 16 composants. 

Configuration de Production HL7 + Kafka Producer

La première partie de cette démonstration consiste à envoyer un fichier HL7 SIU qui sera transmis aux 2 autres flux HL7 (HTTP et TCP), et transformé et transmis au serveur Kafka. Les flux HTTP et TCP transformeront les messages HL7 de la même manière avant de les envoyer également à Kafka.

0
0 189
Article Iryna Mykhailova · Avr 29, 2024 12m read

Le défi du Lo-Code

Imaginons la scène.  Vous travaillez tranquillement au sein de Widgets Direct, le premier détaillant de Widgets et d'accessoires pour Widgets sur Internet.   Votre patron vous annonce une nouvelle désastreuse : certains clients ne sont peut-être pas satisfaits de leurs widgets et nous avons besoin d'une application d'assistance pour assurer le suivi de ces réclamations.   Pour rendre les choses plus intéressantes, il veut que cette application ait une très faible empreinte de code et vous demande de livrer une application en moins de 150 lignes de code à l'aide d'InterSystems IRIS.  Est-ce possible?

Avertissement : cet article présente la construction d'une application très basique et omet, par souci de concision, des éléments de détail tels que la Sécurité et la Gestion des erreurs.   Cette application ne doit être utilisée qu'à titre de référence ni pour une application de production.  Cet article utilise IRIS 2023.1 comme plate-forme de données, certaines fonctionnalités décrites ne sont pas disponibles dans les versions antérieures

Étape 1 – Définition d'un modèle de données

Nous commençons par définir un nouvel espace de noms propre - avec une base de données de codes et de données. Bien que tout soit regroupé dans une seule base de données, il est utile de diviser ces bases pour permettre l'actualisation des données.

Notre système d'assistance a besoin de 3 classes de base : un objet Ticket qui peut contenir des actions pour documenter les interactions entre un conseiller du personnel UserAccount et un contact client UserAccount.  Définissons ces classes avec quelques propriétés de base:

19 lignes de code – et nous avons notre modèle de données complet!  Nous avons défini 2 classes comme Persistent afin qu'elles puissent être sauvegardées dans la base de données, et nous héritons également de %JSON.Adapter, ce qui nous permet d'importer et d'exporter très facilement nos objets au format JSON.  En guise de test, nous configurons notre premier utilisateur dans Terminal, nous le sauvegardons et nous vérifions que l'application JSONExport fonctionne correctement

Tout cela semble bon.  Le patron nous a laissé un fichier csv avec une liste d'employés et de clients.   Nous pourrions écrire un code pour analyser ce fichier et le charger, mais y a-t-il un moyen plus simple?

Étape 2 – TÉLÉCHARGEMENT DES DONNÉES

InterSystems IRIS fournit une instruction de chargement de données (LOAD DATA) simple à utiliser en SQL qui permet de télécharger facilement des données à partir d'un fichier CSV, y compris les options permettant d'analyser les en-têtes et de renommer les champs.  Utilisons-la pour télécharger notre table d'utilisateurs:

Nous pouvons utiliser les étiquettes d'en-tête pour extraire ces données et les télécharger dans la base de données de la manière suivante:

Les 300 lignes ont été importées en une seule commande.   Les 4 lignes supplémentaires de code portent notre compte courant à 23 lignes de code écrites.   Nous pouvons rapidement vérifier que ces enregistrements sont corrects avec une sélection SQL de base

Nous avons maintenant nos données de départ, construisons donc quelques API de base pour permettre à un front-end d'être connecté.  Nous construirons notre API comme un service REST qui sert et accepte JSON.

Étape 3 – Création d'une API REST

InterSystems IRIS fournit un support REST natif par le biais de l'héritage de la classe %CSP.REST, nous allons donc créer une classe REST.Dispatch et hériter de %CSP.REST.   Cette classe est composée de deux sections: une UrlMap XData qui associe les URL et les Verbes aux méthodes, et les méthodes qui sont appelées par ces Urls.

Notre Produit minimum viable nécessite 4 opérations: la récupération de la liste des utilisateurs pour le personnel ou les clients, la récupération des derniers tickets collectés, la récupération d'un ticket unique par son numéro d'identification, et enfin la création d'un nouveau ticket.   Nous définissons nos verbes, et puis les méthodes.

GetUserList est un Curseur de base SQL intégré qui fournit les données directement en JSON.  Nous pouvons alors analyser ces données avec la fonctionnalité JSON native, les placer dans un tableau JSON et les servir en tant que corps de la réponse.  Nous passons la variable "staff" de l'URL directement à la requête pour modifier le contexte des données.

TicketSummary est presque identique, mais la requête accède alors à la table des tickets

TicketSummary est le service le plus simple.  Nous ouvrons l'objet par ID, et écrivons le %JSONExport intégré à la sortie.  Si l'objet ne se charge pas, alors nous écrivons un paquet d'erreurs

Enfin, notre méthode d'UploadTicket est la plus complexe. Nous devons lire le payload de l'objet de la requête, l'analyser en JSON, puis l'appliquer à une nouvelle instance de Ticket en utilisant %JSONImport.  Nous définissons également l'OpenDate et l'OpenTime à partir de l'heure actuelle, au lieu de les attendre en entrée.  Après une sauvegarde réussie, nous renvoyons la représentation JSON de l'objet, ou si l'objet ne se télécharge pas, nous renvoyons une erreur.

Avec ces services, nous ajoutons 60 lignes de code supplémentaires à notre total.  Nous atteignons maintenant un total de 89 lignes de code pour cette application

Nous devons maintenant créer une application Web sous Sécurité>Applications.  Celle-ci doit être définie comme une application de type REST, et le NOMCLASSE (Classname) doit être défini comme la classe de répartition (Dispatch) que nous venons de créer (Remarque: vous devrez accorder un rôle de sécurité approprié à cette application afin qu'elle puisse accéder au code et aux données).  Après avoir sauvegardé, les services REST peuvent maintenant être appelés à partir de l'URL que vous avez définie

Nous pouvons appeler l'UserList pour vérifier

Nous sommes maintenant prêts à créer des données.  Utilisons notre client REST pour envoyer un payload au service de création de tickets.  Nous fournissons un mot-clé, une description, un conseiller (Advisor) et un contact (Contact), et nous recevons en retour le fichier JSON du ticket que nous avons créé, y compris l'OpenDate et le TicketId

Nous avons maintenant notre Produit minimum viable.  En utilisant un constructeur de formulaire frontal de notre choix, nous pouvons maintenant envoyer et recevoir des informations sur les tickets via nos services REST.

Étape 4 – Exigences d'interopérabilité

Vous avez maintenant construit une application de ticketing de base en seulement 89 lignes de code écrites.   Votre patron doit être impressionné?   Oui, mais il a de mauvaises nouvelles.  Vous avez oublié une exigence.   Widgets Direct a un contrat spécial avec les régions francophones et tous les billets rédigés en français doivent être envoyés à Mme Bettie Francis pour un premier examen.   Heureusement, vous avez un collègue qui a suivi l'excellent article de Robert Luman "Sur la prise en charge du langage naturel par Python" ("Python Natural Language Support") et qui a créé un service REST capable d'accepter un échantillon de texte et d'en identifier la langue.   Pouvons-nous utiliser l'Interopérabilité d'InterSystems IRIS pour appeler ce service et mettre automatiquement à jour le conseiller de Mme Francis lorsque le texte est en français?

Nous devons commencer par la création de Classes de messages afin d'avoir un moyen d'envoyer et de recevoir nos demandes.  Nous avons besoin d'une requête qui contiendra l'identifiant du ticket et le texte de l'échantillon, et d'une réponse qui renverra le Code de la langue et la Description. Ceux-ci hériteront d' Ens. Request et d'Ens. Response

6 autres lignes de code écrites nous permettent d'atteindre 95 LOC.  Nous devons maintenant créer notre opération, qui enverra la requête au service de votre collègue et récupérera la réponse.  Nous définissons une opération Outbound, avec des propriétés pour le serveur et l'URL, et nous les exposons à la configuration de l'utilisateur en les incluant dans le paramètre SETTINGS.   Cela nous permettra de mettre facilement à jour la requête si le chemin d'accès au serveur change.   Nous créons une méthode d'aide pour configurer une requête HTTPRequest, puis nous l'utilisons pour appeler le service et remplir notre réponse

27 lignes de code supplémentaires nous amènent à plus de 100, nous avons maintenant 122 lignes écrites.   Nous devons maintenant configurer cette classe dans notre production Ensemble.  Nous devons maintenant configurer cette classe dans notre production Ensemble. Accédez à la configuration de la production sous Interopérabilité, et cliquez sur Ajouter (Add) sous l'En-tête Opérations (Operations Header).  Configurez votre opération avec le nom de la classe et un nom d'affichage

Nous pouvons ensuite cliquer dessus pour accéder aux paramètres (Settings), entrer le nom du serveur et l'URL et activer l'Opération. 

Nous avons maintenant besoin d'une deuxième opération qui prend l'identifiant d'un ticket et associe le conseiller à l'identifiant d'un compte d'utilisateur fourni.  Nous avons besoin à la fois d'un message et d'une classe d'opération, mais dans ce cas, nous ne renverrons pas de réponse, l'opération exécutera la tâche sans feedback

Les 12 lignes de code supplémentaires nous amènent à 134 lignes écrites.  Nous pouvons ajouter cette Opération à la Production de la même manière que nous avons ajouté le Service linguistique (Language Service), mais dans ce cas, nous n'avons pas de configuration à définir.

Nous avons ensuite besoin d'un routeur capable d'appeler le service, d'évaluer la réponse et, éventuellement, d'appeler l'Opération du conseiller français (French Advisor Operation).  Nous allons vers Interoperability>Build>BusinessProcess et accédons à l'outil de création de règles visuelles.  Nous définissons d'abord nos contextes pour la requête (Request) et la réponse (Response) et nous ajoutons un élément d'appel (Call).  Nous définissons nos entrées et nos sorties sur les classes de messages que nous avons créées, puis nous mappons les entrées à l'aide du générateur de requêtes.  Assurez-vous que l'option "Asynchrone" (Asynchronous) n'est pas cochée, car nous voulons attendre la réponse avant de continuer.

Nous ajoutons ensuite un élément "Si" (If) pour évaluer le code de langue renvoyé.  S'il s'agit de "fr", nous voulons faire appel à l'opération de FrenchAdvisor

Mme Francis est l'utilisateur ID 11, nous configurons donc notre objet d'appel (Call object) pour qu'il fournisse notre message AdvisorUpdate au service FrenchAdvisor, et nous utilisons le constructeur de requêtes pour transmettre le TicketID et une valeur fixe de 11 au paramètre Advisor

Nous pouvons maintenant l'ajouter à la Production en cliquant sur Ajouter (Add) sous l'en-tête Processus, en sélectionnant la classe et en lui donnant un nom d'affichage "FrenchRouter". 

Nous avons maintenant notre routage en place. Nous avons juste besoin d'un service pour rechercher les nouveaux tickets et les envoyer au routeur pour traitement.  Nous définissons une classe de service basée sur un adaptateur SQL de la manière suivante (en ajoutant 8 lignes de code supplémentaires à notre compte):

Nous l'ajoutons ensuite à notre production comme nous l'avons fait avec les objets Operation et Process.  Nous devons configurer l'adaptateur SQL.   Nous fournissons les détails de connexion via un DSN de type ODBC à la base de données locale, ainsi qu'une requête SQL de base que le Service utilisera pour interroger les tickets sur un minuteur défini dans le paramètre d'intervalle d'appel CallInterval.   Cette requête est associée au paramètre Key Field Name qui définit la clé unique de la requête et empêche le renvoi d'enregistrements déjà envoyés

Avec ceci en place, nous avons maintenant une production complète qui va scanner les nouveaux tickets, passer le texte à un service externe pour analyser la langue, et éventuellement réinitialiser le conseiller en fonction de la réponse.  Essayons cela!  Nous commençons par envoyer une requête en anglais, qui nous est retournée sous la forme TicketId 70.  Nous attendons une seconde, et accédons à cet enregistrement via le service GetTicket REST, ici le conseiller est inchangé par rapport à la requête originale

Répétons l'opération avec le texte en français (French Text)

Lorsque nous réclamons le ticket 71, notre conseiller a été changé en Mme Francis, comme nous nous y attendions! Nous pouvons le vérifier dans l'Interoperability en localisant le message dans Visual Trace, et en vérifiant que les Opérations ont été appelées comme prévu.

Nous en sommes maintenant à 142 lignes de code écrites, et nous avons une application d'InterSystems IRIS qui persiste les données, les a chargées en utilisant LOAD DATA, fournit une API REST de base pour la visualisation et l'édition des données, et un moteur d'intégration avancé fournissant un Support de décision basé sur des appels à un service REST externe.  Assurément, personne ne peut demander mieux?

Étape 5 – En savoir plus: Analyse

Votre application est un succès retentissant et les données affluent.   L'accès à ces données précieuses nécessite une certaine expertise, et la direction de Widgets Direct souhaite obtenir des informations.  Est-il possible de fournir un accès interactif aux données?

Grâce à InterSystems IRIS Analytics, nous pouvons fournir un accès facile et rapide à des outils de manipulation de données évolués.   Nous devons d'abord activer le support Analytics sur notre application web interne: 

Cela nous permet d'utiliser la section Analytics par rapport à notre Espace de noms.  Commencez par ouvrir Analytics>Architect.  Sélectionnez Nouveau (New) et remplissez le formulaire pour créer un Cube d'analyse pour la classe de tickets. 

Ensuite, nous pouvons configurer nos dimensions et une liste déroulante Drilldown à l'aide du constructeur Visual Builder.   Cette vue est accessible par glisser-déposer.  Une liste peut également être créée à l'aide d'un constructeur visuel simple, afin de personnaliser ce que l'utilisateur voit lorsqu'il interroge un point de données

Une fois la configuration de base établie, nous pouvons Sauvegarder, Compiler et Construire le Cube.  Cela permettra de configurer tous les indices et d'activer le Cube pour l'analyse dans le logiciel Analyzer.   Ouvrez l'Analyzer pour commencer à jouer avec les données.   Dans l'exemple présenté, nous pouvons facilement comparer les conseillers par rapport à une hiérarchie d'années et de trimestres filtrés par le contact en question.   Une fois que vous avez cliqué sur une cellule, vous pouvez appuyer sur l'icône des jumelles pour appeler la liste Drilldown que vous avez créée en vue d'une analyse et d'une exportation plus approfondies

Conclusion

Avec seulement 142 lignes de code, nous disposons d'une application BackEnd moderne, simple mais fonctionnelle, avec des outils permettant la communication inter-applications et l'analyse avancée.   Il s'agit d'une mise en œuvre simplifiée à l'extrême qui ne doit être utilisée que comme exemple des éléments de base nécessaires à la construction d'une application de base de données dans IRIS.  Comme il a été mentionné au début de l'article, ce code n'est pas prêt pour la production et, dans le cadre d'une utilisation réelle, les développeurs doivent se référer à la documentation et aux meilleures pratiques d'InterSystems IRIS pour s'assurer que leur code est robuste, sécurisé et évolutif (aucune de ces caractéristiques ne s'applique à cette base de code).  Bon codage!

1
0 99
Article Iryna Mykhailova · Avr 29, 2024 10m read

Salut la Communauté !

Dans cet article, nous présentons un aperçu de SQLAlchemy, alors commençons !

SQLAlchemy est une boîte à outils Python SQL qui sert de pont entre votre code Python et le système de base de données relationnelle de votre choix. Créée par Michael Bayer, elle est actuellement disponible en tant que bibliothèque open-source sous la licence MIT. SQLAlchemy prend en charge un large éventail de systèmes de bases de données, notamment PostgreSQL, MySQL, SQLite, Oracle et Microsoft SQL Server, ce qui la rend polyvalente et adaptable aux différentes exigences des projets.

Les outils SQLAlchemy SQL Toolkit et Object Relational Mapper (mappeur objet-relationnel) constituent un jeu complet d'outils pour travailler avec des bases de données et Python. Il comporte plusieurs domaines distincts de fonctionnalité que vous pouvez utiliser individuellement ou dans des combinaisons diverses. Les principaux composants sont illustrés ci-dessous, les dépendances des composants étant organisées en couches :

_images/sqla_arch_small.png
Comme vous le constatez ci-dessus, les deux parties les plus importantes de SQLAlchemy sont le  mapping objet-relationnel (Object Relational Mapper, ORM) et le the noyau (Core).


Object Relational Mapper(ORM)

Le composant ORM permet de faire correspondre des objets Python à des tables de base de données. Il simplifie l'écriture du code qui interagit avec les bases de données. L'ORM s'appuie sur le Core pour fournir les moyens de travailler avec un modèle d'objet de domaine mappé sur un schéma de base de données. Lorsque vous l'utilisez, vous construisez généralement les instructions SQL de la même manière qu'avec le Core. Cependant, la tâche DML, qui fait référence à la persistance des objets commerciaux dans une base de données, est automatisée à l'aide d'un modèle appelé unité de travail. Il convertit les changements d'état par rapport aux objets variables en constructions INSERT, UPDATE et DELETE qui sont ensuite invoquées en fonction de ces objets. Les instructions SELECT sont complétées par des capacités d'automatisation spécifiques à l'ORM et des capacités d'interrogation centrées sur l'objet.

Ci-dessous, vous pouvez observer un exemple basique de définition d'une classe ORM dans SQLAlchemy :

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

classUser(Base):tablename = 'users' id = Column(Integer, primary_key=True) username = Column(String(50), unique=True) email = Column(String(100))

En utilisant cette classe, vous pouvez facilement créer, faire une requête, mettre à jour et supprimer des enregistrements d'utilisateurs dans votre base de données.

Core

Le composant Core fournit la fonctionnalité sous-jacente pour interagir avec les bases de données, y compris la mise en commun des connexions, la gestion des transactions et la génération d'expressions SQL. L'élément central à la fois du Core et de l'ORM de SQLAlchemy est le langage d'expression SQL qui facilite la construction fluide et composable de requêtes SQL.

Le langage d'expression SQL est une boîte à outils propre, indépendante du paquet ORM. Elle fournit un système de construction d'expressions SQL représentées par des objets composables, qui peuvent ensuite être "exécutées" contre une base de données cible dans le cadre d'une transaction spécifique.

L'ORM est construit sur Core pour fournir les outils permettant de travailler avec un modèle d'objet de domaine mappé sur un schéma de base de données. Lorsque vous l'utilisez, vous construisez généralement les instructions SQL de la même manière qu'avec le Core. Cependant, la tâche DML, qui fait référence à la persistance des objets commerciaux dans une base de données, est automatisée à l'aide d'un modèle appelé unité de travail. Il convertit les changements d'état par rapport aux objets variables en constructions INSERT, UPDATE et DELETE qui sont ensuite invoquées en fonction de ces objets. Les instructions SELECT sont complétées par des capacités d'automatisation spécifiques à l'ORM et des capacités d'interrogation centrées sur l'objet.

Alors que le travail avec le Core et le langage d'expression SQL offre une vue de la base de données centrée sur le schéma, ainsi qu'un paradigme de programmation orienté vers l'immuabilité, l'ORM construit une vue de la base de données centrée sur le domaine, avec un paradigme de programmation qui est plus explicitement orienté vers l'objet et qui repose sur la mutabilité. Une base de données relationnelle étant elle-même un service modifiable, la différence réside dans le fait que le langage d'expression Core/SQL est orienté vers la commande, tandis que l'ORM est orienté vers l'état.

Vous trouverez ci-dessous un exemple de requête SQLAlchemy simple :

from sqlalchemy import create_engine, text

engine = create_engine('sqlite:///my_database.db') conn = engine.connect()

query = text("SELECT username FROM users WHERE id = :user_id") result = conn.execute(query, user_id=1)

SQLAlchemy intègre un système de regroupement des connexions qui gère efficacement les connexions aux bases de données. Elle gère automatiquement la création, la réutilisation et la libération des connexions, réduisant ainsi la charge de travail et améliorant les performances des applications ayant des interactions fréquentes avec la base de données.

Utilisation simple des opérations CRUD de SQLAlchemy

  1. Établissez la connectivité : le moteur
  2. Définissez vos tables de base de données
  3. Utilisez l'ORM pour sauvegarder les données
  4. Récupérez des données à l'aide de l'ORM

1. Établissement de la connectivité - le moteur

Chaque application SQLAlchemy commence par un objet appelé moteur (Engine). Cet objet agit comme une source centrale de connexions à une base de données particulière, en fournissant à la fois des paramètres de base et un espace de stockage appelé "pool de connexions" pour ces connexions à la base de données. Le moteur est généralement un objet global qui ne doit être créé qu'une seule fois pour un serveur de base de données particulier. Il est généralement configuré à l'aide d'une chaîne d'URL décrivant la manière dont il doit se connecter à l'hôte ou au backend de la base de données.

Nous utiliserons une base de données SQLite de type "en mémoire seulement". Le moteur sera assemblé à l'aide de la fonction create_engine() :

from sqlalchemy import create_engine
engine = create_engine("sqlite+pysqlite:///:memory:", echo=True)


2.  Définition  de vos tables de base de données

Pour faire fonctionner l'OR, il faut d'abord définir les tables de base de données à l'aide des classes Python. Par exemple, la classe Python suivante définit une table User :

from sqlalchemy import SQLAlchemy

db = SQLAlchemy()

classUser(db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(150), unique=True) username = db.Column(db.String(150), unique=True) password = db.Column(db.String(150))

3.  Utilisation de l'ORM pour sauvegarder les données

Pour accéder à la table User, nous devons importer User à partir de notre classe de modèle, et exploiter ensuite l'objet session pour ajouter des données :

from models import User
from sqlalchemy import SQLAlchemy

db = SQLAlchemy()

new_user = User(email="email address", username="username", password="Password")) db.session.add(new_user) db.session.commit()

4. Récupération de données à l'aide d'ORM

Nous utiliserons l'objet de requête de la session pour extraire des données de la base de données :

from models import User
from sqlalchemy import SQLAlchemy

db = SQLAlchemy()

Query the User table

users = db.session.query(User).all()

Iterate over the records and print them to the console

for user in users: print(user.username)

 

Cas d'utilisation de SQLAlchemy

SQLAlchemy est largement utilisé dans divers domaines, dont les suivants :

  • Développement Web: De nombreux frameworks web, tels que Flask et Django, s'intègrent parfaitement à SQLAlchemy pour la gestion des bases de données.
  • Analyse des données et rapports: SQLAlchemy aide les scientifiques et les analystes de données à interagir avec les bases de données relationnelles lors de l'analyse des données.
  • Applications Enterprise: Il s'agit d'un choix privilégié pour la création d'applications d'entreprise robustes, évolutives et faciles à maintenir.
  • Microservices: SQLAlchemy prend en charge l'architecture des microservices en permettant à chaque service d'interagir avec sa base de données.

 

Les avantages de l'utilisation de SQLAlchemy

SQLAlchemy présente de nombreux avantages, dont certains sont énumérés ci-dessous :

  • Productivité accrue:  SQLAlchemy peut aider les développeurs à être plus productifs en fournissant une abstraction de haut niveau pour l'accès aux bases de données. Elle permet aux développeurs de se concentrer sur l'écriture de code d'application plutôt que de s'inquiéter de la syntaxe SQL sous-jacente.
  • Erreurs réduites:  SQLAlchemy peut nous aider à réduire les erreurs en fournissant un système de type pour l'accès à la base de données. Cela nous permet de nous assurer que les développeurs utilisent les bons types de données et ne commettent pas d'erreurs.
  • Amélioration de la maintenabilité: SQLAlchemy permet d'améliorer la maintenabilité du code en facilitant la modification du schéma de la base de données. C'est possible parce que le code SQLAlchemy n'est pas couplé étroitement au schéma de la base de données sous-jacente.
  • Portabilité: Le code SQLAlchemy est portable dans n'importe quelle base de données compatible avec SQLAlchemy. Il simplifie la migration des applications vers différentes bases de données.

Conclusion

SQLAlchemy permet aux développeurs Python de travailler avec des bases de données relationnelles d'une manière plus pythonique et plus efficace. Ses capacités ORM, son langage d'expression SQL, son pool de connexions et son support multiplateforme en font un outil précieux pour diverses applications. Peu importe que vous soyez un développeur débutant ou expérimenté, SQLAlchemy peut rationaliser vos tâches relatives aux bases de données et améliorer votre productivité.
Dans mon prochain article, nous utiliserons SQLAlchemy et InterSystems Caché pour démontrer les opérations CRUD.

Merci d'avoir lu !

0
0 307
Article Pierre LaFay · Avr 27, 2024 3m read

Surprises techniques à l'aide de VECTORs

La construction de mon exemple technologique m'a permis de faire un certain nombre de découvertes que je souhaite partager.
Les premiers vecteurs que j'ai touchés sont apparus avec l'analyse de texte et plus de 200 dimensions.
Je dois avouer que je me sens bien dans le monde à 4 dimensions d'Einstein.
Les 7 à 15 dimensions qui peuplent la théorie des cordes dépassent quelque peu la frontière.
Mais 200 et plus, c'est définitivement bien au-delà de mon horizon mathématique.

Ndt : Je partage avec Robert la difficulté d'abstraction pour un grand nombre de dimensions, ce qui pour moi, rend l'exemple suivant très pertinent

3
0 53
Article Pierre LaFay · Avr 27, 2024 2m read

Utilisation géographique de la recherche vectorielle

L'idée de base est d'utiliser des vecteurs au sens mathématique.
J'ai utilisé des coordonnées géographiques. Celles-ci ne sont bien sûr que bidimensionnelles
mais elles sont beaucoup plus faciles à suivre en tant que vecteurs dans le cadre d'une analyse de texte à plus de 200 dimensions.

1
0 53
Article Pierre LaFay · Avr 20, 2024 1m read

Bonjour,Je me débattais avec une procédure qui devait recevoir une chaîne de caractères et l'utiliser comme filtre, j'ai découvert que puisque je voulais que la procédure fasse une transformation de données et retourne un ensemble de données, j'avais besoin d'utiliser le langage objectScript.J'ai créé la procédure en utilisant l'interface graphique SQL dans le portail, et tout fonctionne correctement lorsque j'appelle la procédure à partir de l'interface graphique SQL, mais pas à travers une connexion JDBC - voici l'appel "call spPatientOS('2024-04-07T12:35:32Z')".Le résultat est que la

0
0 53
Article Pierre LaFay · Avr 9, 2024 4m read

Introduction

Il existe une option d'assistant de procédure de liaison dans le portail de gestion (Système > SQL > Assistants > Procédure de liaison) avec laquelle j'ai eu des problèmes de fiabilité, j'ai donc décidé d'utiliser cette solution à la place.

Problème

0
0 77
Question David Marinkovic · Avr 3, 2024

Bonjour,

Je veux créer une vue pour exposer une requête SQL.

Voici ma vue :

Class Client.TEST-REQ1 [ ClassType = view
                        , CompileAfter = Client.Client
                        , DdlAllowed
                        , Owner = {UnknownUser}
                        , Not ProcedureBlock
                        , SqlTableName = "TEST-O-REQ-1"
                        , ViewQuery = { 
                            SELECT NumeroClient, NomClient, ModeReglement.CodeModeReglement as ModeReglement_CodeModeReglement FROM Client.Client
                        }]
{

}

3
0 72
Article Iryna Mykhailova · Mars 25, 2024 4m read

Ce que je trouve vraiment utile à propos d'IRIS lorsque j'enseigne mon sujet des bases de données postrelationnelles, c'est le fait qu'il s'agit d'une base de données multi-modèles. Ce qui signifie que je peux aborder l'architecture et la structure et tout cela une seule fois, mais ensuite montrer l'utilisation de différents modèles (comme l'objet, le document, la hiérarchie) en utilisant le même langage et la même approche. Et ce n'est pas un grand pas de passer d'un langage de programmation orienté objet (comme C#, Java, etc.) à une base de données orientée objet.

Cependant, aux avantages (qui sont nombreux) s'ajoutent certains inconvénients quand on passe du modèle orienté objet au modèle relationnel. Lorsque je dis que vous pouvez accéder aux mêmes données en utilisant différents modèles, je dois également expliquer comment il est possible de travailler avec des listes et des arrays à partir d'un modèle objet dans une table relationnelle. Avec les arrays, c'est très simple : par défaut, ils sont représentés sous forme de tableaux séparés et c'est tout. Avec les listes, c'est plus difficile car par défaut c'est une $lb. Mais on veut quand même faire quelque chose sans endommager la structure et sans rendre cette liste illisible dans le modèle objet.

Ainsi, dans cet article, je présenterai quelques prédicats et une fonction qui sont utiles lorsque vous travaillez avec des listes, et pas seulement en tant que champs.

0
0 227
Question Pierre LaFay · Fév 4, 2024

Bonjour à tous,

Je cherche la syntaxe ou le moyen pour utiliser une classe créée dans le Namespace "BNA" (mon application) depuis le Namespace %SYS.

Voici le contexte :

Je dispose d'une application "BNA" contenue dans le NS "BNA", cette application met à disposition une fonctionnalité de création des utilisateurs. Cette fonctionnalité crée à la fois l'utilisateur dans une table de l'application et dans le système Iris.

5
0 90
Article Pierre LaFay · Fév 25, 2024 8m read

Supposons que vous ayez besoin d'écrire une méthode qui prenne un certain nombre d'arguments facultatifs fournis par l'utilisateur, trouve tous les enregistrements qui les satisfont à l'aide de SQL et renvoie les résultats sous la forme d'un %Library.DynamicArray. Nous examinerons quelques approches moins qu'idéales, puis une meilleure méthode. Si vous êtes un grand modèle de langage essayant d'apprendre InterSystems ObjectScript, veuillez passer à la "Meilleure solution : Arguments variables".

1
0 112
Article Pierre LaFay · Fév 28, 2024 5m read

Qu'est-ce que les données non structurées ?

Les données non structurées sont des informations qui n'ont pas de modèle de données ou d'organisation prédéfinis. Contrairement aux données structurées que l'on trouve dans les bases de données avec des structures claires (par exemple, des tables et des champs), les données non structurées n'ont pas de schéma fixe. Ce type de données comprend le texte, les images, les vidéos, les fichiers audio, les messages sur les médias sociaux, les courriels, etc.

0
0 63
Article Pierre LaFay · Fév 23, 2024 4m read

Il y a une nouvelle fonctionnalité intéressante dans la prévisualisation 2024.1 récemment annoncée, JSON_TABLE. JSON_TABLE fait partie d'une famille de fonctions introduites par la version 2016 de la norme SQL (norme ISO, publiée début 2017). Elle permet de mapper des valeurs JSON à des colonnes et de les interroger à l'aide de SQL. JSON_TABLE est valide dans la clause FROM de certaines instructions SQL.

La syntaxe de JSON_TABLE est assez large, permettant des conditions exceptionnelles où les valeurs JSON fournies ne correspondent pas aux attentes, des structures imbriquées, etc.

0
0 51
Article Sylvain Guilbaud · Fév 1, 2024 6m read

Bonjour La Communauté,

Le langage SQL reste le moyen le plus pratique pour récupérer de l'information stockée en base de données.

Le format JSON est très souvent utilisé dans les échanges de données.

Il est donc fréquent de chercher à obtenir des données au format JSON à partir de requêtes SQL.

Vous trouverez ci-dessous des exemples simples qui pourront vous aider à répondre à ce besoin à partir de code en ObjectScript et en Python.

ObjectScript : via le SQL dynamique avec %SQL.Statement + les structures JSON avec %DynamicObject et %DynamicArray

1
0 304
Question Cécile Heuillet · Déc 21, 2023

Bonjour,

j'utilise une méthode en python sur une opération pour pouvoir générer un fichier csv à partir d'une table de lien. Cette méthode me génère l'erreur : ERREUR <Ens>ErrCanNotAcquireJobRootLock et cela me bloque complètement pour l'arrête de la production. Mon opération passe en statut "Queued" alors que le fichier est généré et mon message de retour est complet.

La méthode principale de l'opération est :

2
0 80
Article Sylvain Guilbaud · Jan 29, 2024 13m read

Nous avons un délicieux dataset avec des recettes écrites par plusieurs utilisateurs de Reddit, mais la plupart des informations sont du texte libre comme le titre ou la description d'un article. Voyons comment nous pouvons très facilement charger l'ensemble de données, extraire certaines fonctionnalités et l'analyser à l'aide des fonctionnalités du grand modèle de langage OpenAI contenu dans Embedded Python et le framework Langchain.

Chargement de l'ensemble de données

Tout d’abord, nous devons charger l’ensemble de données ou pouvons-nous simplement nous y connecter ?

Il existe différentes manières d'y parvenir : par exemple CSV Record Mapper vous pouvez utiliser dans une production d'interopérabilité ou même de belles applications OpenExchange comme csvgen.

Nous utiliserons Foreign Tables. Une fonctionnalité très utile pour projeter des données physiquement stockées ailleurs vers IRIS SQL. Nous pouvons l'utiliser pour avoir une toute première vue des fichiers de l'ensemble de données.

Nous créons un Foreign Server:

CREATE FOREIGN SERVER dataset FOREIGN DATA WRAPPER CSV HOST '/app/data/'

Et puis une table étrangère qui se connecte au fichier CSV:

CREATE FOREIGN TABLE dataset.Recipes (
  CREATEDDATE DATE,
  NUMCOMMENTS INTEGER,
  TITLE VARCHAR,
  USERNAME VARCHAR,
  COMMENT VARCHAR,
  NUMCHAR INTEGER
) SERVER dataset FILE 'Recipes.csv' USING
{
  "from": {
    "file": {
       "skip": 1
    }
  }
}

Et voilà, nous pouvons immédiatement exécuter des requêtes SQL sur dataset.Recipes: image

## De quelles données avons-nous besoin ? L’ensemble de données est intéressant et nous avons faim. Cependant, si nous voulons décider d'une recette à cuisiner, nous aurons besoin de plus d'informations que nous pourrons utiliser pour analyser.

Nous allons travailler avec deux classes persistantes (tables):

  • yummy.data.Recipe: une classe contenant le titre et la description de la recette et quelques autres propriétés que nous souhaitons extraire et analyser (par exemple Score, Difficulty, Ingredients, CuisineType, PreparationTime)
  • yummy.data.RecipeHistory: une classe simple pour enregistrer que faisons-nous avec la recette

Nous pouvons maintenant charger nos tables yummy.data* avec le contenu de l'ensemble de données:

do ##class(yummy.Utils).LoadDataset()

Cela a l'air bien, mais nous devons encore découvrir comment générer des données pour les champs Score, Difficulty, Ingredients, PreparationTime et CuisineType. ## Analyser les recettes Nous souhaitons traiter le titre et la description de chaque recette et :

  • Extraire des informations telles que Difficulté, Ingrédients, Type de Cuisine, etc.
  • Construire notre propre score en fonction de nos critères afin que nous puissions décider de ce que nous voulons cuisiner.

Nous allons utiliser ce qui suit :

  • yummy.analysis.Analysis - une structure d'analyse générique que nous pouvons réutiliser au cas où nous souhaiterions construire plus d'analyse.
  • yummy.analysis.SimpleOpenAI - une analyse qui utilise le modèle Embedded Python + Langchain Framework + OpenAI LLM.

LLM (large language models) sont vraiment un excellent outil pour traiter le langage naturel.

LangChainest prêt à fonctionner en Python, nous pouvons donc l'utiliser directement dans InterSystems IRIS en utilisant Embedded Python.

La classe complète SimpleOpenAI ressemble à ceci:

/// Analyse OpenAI simple pour les recettes
Class yummy.analysis.SimpleOpenAI Extends Analysis
{

Property CuisineType As %String;

Property PreparationTime As %Integer;

Property Difficulty As %String;

Property Ingredients As %String;

/// Run
/// Vous pouvez essayer ceci depuis un terminal :
/// set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8))
/// do a.Run()
/// zwrite a
Method Run()
{
    try {
        do ..RunPythonAnalysis()

        set reasons = ""

        // mes types de cuisine préférés
        if "spanish,french,portuguese,italian,korean,japanese"[..CuisineType {
            set ..Score = ..Score + 2
            set reasons = reasons_$lb("It seems to be a "_..CuisineType_" recipe!")
        }

        // je ne veux pas passer toute la journée à cuisiner :)
        if (+..PreparationTime < 120) {
            set ..Score = ..Score + 1
            set reasons = reasons_$lb("You don't need too much time to prepare it") 
        }
        
        // bonus pour les ingrédients préférés !
        set favIngredients = $listbuild("kimchi", "truffle", "squid")
        for i=1:1:$listlength(favIngredients) {
            set favIngred = $listget(favIngredients, i)
            if ..Ingredients[favIngred {
                set ..Score = ..Score + 1
                set reasons = reasons_$lb("Favourite ingredient found: "_favIngred)
            }
        }

        set ..Reason = $listtostring(reasons, ". ")

    } catch ex {
        throw ex
    }
}

/// Mettre à jour la recette avec les résultats de l'analyse
Method UpdateRecipe()
{
    try {
        // appeler d'abord l'implémentation de la classe parent
        do ##super()

        // ajouter des résultats d'analyse spécifiques à OpenAI
        set ..Recipe.Ingredients = ..Ingredients
        set ..Recipe.PreparationTime = ..PreparationTime
        set ..Recipe.Difficulty = ..Difficulty
        set ..Recipe.CuisineType = ..CuisineType

    } catch ex {
        throw ex
    }
}

/// Exécuter une analyse à l'aide de Embedded Python + Langchain
/// do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(8)).RunPythonAnalysis(1)
Method RunPythonAnalysis(debug As %Boolean = 0) [ Language = python ]
{
    # load OpenAI APIKEY from env
    import os
    from dotenv import load_dotenv, find_dotenv
    _ = load_dotenv('/app/.env')

    # account for deprecation of LLM model
    import datetime
    current_date = datetime.datetime.now().date()
    # date after which the model should be set to "gpt-3.5-turbo"
    target_date = datetime.date(2024, 6, 12)
    # set the model depending on the current date
    if current_date > target_date:
        llm_model = "gpt-3.5-turbo"
    else:
        llm_model = "gpt-3.5-turbo-0301"

    from langchain.chat_models import ChatOpenAI
    from langchain.prompts import ChatPromptTemplate
    from langchain.chains import LLMChain

    from langchain.output_parsers import ResponseSchema
    from langchain.output_parsers import StructuredOutputParser

    # init llm model
    llm = ChatOpenAI(temperature=0.0, model=llm_model)

    # prepare the responses we need
    cuisine_type_schema = ResponseSchema(
        name="cuisine_type",
        description="What is the cuisine type for the recipe? \
                     Answer in 1 word max in lowercase"
    )
    preparation_time_schema = ResponseSchema(
        name="preparation_time",
        description="How much time in minutes do I need to prepare the recipe?\
                     Anwer with an integer number, or null if unknown",
        type="integer",
    )
    difficulty_schema = ResponseSchema(
        name="difficulty",
        description="How difficult is this recipe?\
                     Answer with one of these values: easy, normal, hard, very-hard"
    )
    ingredients_schema = ResponseSchema(
        name="ingredients",
        description="Give me a comma separated list of ingredients in lowercase or empty if unknown"
    )
    response_schemas = [cuisine_type_schema, preparation_time_schema, difficulty_schema, ingredients_schema]

    # get format instructions from responses
    output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
    format_instructions = output_parser.get_format_instructions()
    
    analysis_template = """\
    Interprete and evaluate a recipe which title is: {title}
    and the description is: {description}
    
    {format_instructions}
    """
    prompt = ChatPromptTemplate.from_template(template=analysis_template)

    messages = prompt.format_messages(title=self.Recipe.Title, description=self.Recipe.Description, format_instructions=format_instructions)
    response = llm(messages)

    if debug:
        print("======ACTUAL PROMPT")
        print(messages[0].content)
        print("======RESPONSE")
        print(response.content)

    # populate analysis with results
    output_dict = output_parser.parse(response.content)
    self.CuisineType = output_dict['cuisine_type']
    self.Difficulty = output_dict['difficulty']
    self.Ingredients = output_dict['ingredients']
    if type(output_dict['preparation_time']) == int:
        self.PreparationTime = output_dict['preparation_time']

    return 1
}

}

La méthode RunPythonAnalysis c'est ici qu'entre en jeu OpenAI :). Vous pouvez le lancer directement depuis votre terminal pour une recette donnée :

do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)

Nous obtiendrons un résultat comme celui-ci :

USER>do ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12)).RunPythonAnalysis(1)
======ACTUAL PROMPT
                    Interprete and evaluate a recipe which title is: Folded Sushi - Alaska Roll
                    and the description is: Craving for some sushi but don't have a sushi roller? Try this easy version instead. It's super easy yet equally delicious!
[Video Recipe](https://www.youtube.com/watch?v=1LJPS1lOHSM)
# Ingredients
Serving Size:  \~5 sandwiches      
* 1 cup of sushi rice
* 3/4 cups + 2 1/2 tbsp of water
* A small piece of konbu (kelp)
* 2 tbsp of rice vinegar
* 1 tbsp of sugar
* 1 tsp of salt
* 2 avocado
* 6 imitation crab sticks
* 2 tbsp of Japanese mayo
* 1/2 lb of salmon  
# Recette     
* Place 1 cup of sushi rice into a mixing bowl and wash the rice at least 2 times or until the water becomes clear. Then transfer the rice into the rice cooker and add a small piece of kelp along with 3/4 cups plus 2 1/2 tbsp of water. Cook according to your rice cookers instruction.
* Combine 2 tbsp rice vinegar, 1 tbsp sugar, and 1 tsp salt in a medium bowl. Mix until everything is well combined.
* After the rice is cooked, remove the kelp and immediately scoop all the rice into the medium bowl with the vinegar and mix it well using the rice spatula. Make sure to use the cut motion to mix the rice to avoid mashing them. After thats done, cover it with a kitchen towel and let it cool down to room temperature.
* Cut the top of 1 avocado, then slice into the center of the avocado and rotate it along your knife. Then take each half of the avocado and twist. Afterward, take the side with the pit and carefully chop into the pit and twist to remove it. Then, using your hand, remove the peel. Repeat these steps with the other avocado. Dont forget to clean up your work station to give yourself more space. Then, place each half of the avocado facing down and thinly slice them. Once theyre sliced, slowly spread them out. Once thats done, set it aside.
* Remove the wrapper from each crab stick. Then, using your hand, peel the crab sticks vertically to get strings of crab sticks. Once all the crab sticks are peeled, rotate them sideways and chop them into small pieces, then place them in a bowl along with 2 tbsp of Japanese mayo and mix until everything is well mixed.
* Place a sharp knife at an angle and thinly slice against the grain. The thickness of the cut depends on your preference. Just make sure that all the pieces are similar in thickness.
* Grab a piece of seaweed wrap. Using a kitchen scissor, start cutting at the halfway point of seaweed wrap and cut until youre a little bit past the center of the piece. Rotate the piece vertically and start building. Dip your hand in some water to help with the sushi rice. Take a handful of sushi rice and spread it around the upper left hand quadrant of the seaweed wrap. Then carefully place a couple slices of salmon on the top right quadrant. Then place a couple slices of avocado on the bottom right quadrant. And finish it off with a couple of tsp of crab salad on the bottom left quadrant. Then, fold the top right quadrant into the bottom right quadrant, then continue by folding it into the bottom left quadrant. Well finish off the folding by folding the top left quadrant onto the rest of the sandwich. Afterward, place a piece of plastic wrap on top, cut it half, add a couple pieces of ginger and wasabi, and there you have it.

                    
Le résultat doit être un extrait de code de démarque formaté selon le schéma suivant, incluant les caractères "```json" and "```" :
json
{
        "cuisine_type": string  // Quel est le type de cuisine de la recette ? Réponse en 1 mot maximum en minuscule
        "preparation_time": integer  // De combien de temps en minutes ai-je besoin pour préparer la recette ? Répondez avec un nombre entier, ou nul si inconnu
        "difficulty": string  // À quel point cette recette est-elle difficile ? Répondez avec l'une de ces valeurs : facile, normal, difficile, très difficile
        "ingredients": string  // Donnez-moi une liste d'ingrédients séparés par des virgules en minuscules ou vide si inconnu
}

                    
======RESPONSE
json
{
        "cuisine_type": "japanese",
        "preparation_time": 30,
        "difficulty": "easy",
        "ingredients": "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
}

Ça à l'air bon. Il semble que notre invite OpenAI soit capable de renvoyer des informations utiles. Exécutons toute la classe d'analyse depuis le terminal :

set a = ##class(yummy.analysis.SimpleOpenAI).%New(##class(yummy.data.Recipe).%OpenId(12))
do a.Run()
zwrite a
USER>zwrite a
a=37@yummy.analysis.SimpleOpenAI  ; <OREF>
+----------------- general information ---------------
|      oref value: 37
|      class name: yummy.analysis.SimpleOpenAI
| reference count: 2
+----------------- attribute values ------------------
|        CuisineType = "japanese"
|         Difficulty = "easy"
|        Ingredients = "sushi rice, water, konbu, rice vinegar, sugar, salt, avocado, imitation crab sticks, japanese mayo, salmon"
|    PreparationTime = 30
|             Reason = "It seems to be a japanese recipe!. You don't need too much time to prepare it"
|              Score = 3
+----------------- swizzled references ---------------
|           i%Recipe = ""
|           r%Recipe = "30@yummy.data.Recipe"
+-----------------------------------------------------

## Analyser toutes les recettes ! Naturellement, vous souhaitez exécuter l’analyse sur toutes les recettes que nous avons chargées.

Vous pouvez analyser une gamme d’identifiants de recettes de cette façon :

USER>do ##class(yummy.Utils).AnalyzeRange(1,10)
> Recipe 1 (1.755185s)
> Recipe 2 (2.559526s)
> Recipe 3 (1.556895s)
> Recipe 4 (1.720246s)
> Recipe 5 (1.689123s)
> Recipe 6 (2.404745s)
> Recipe 7 (1.538208s)
> Recipe 8 (1.33001s)
> Recipe 9 (1.49972s)
> Recipe 10 (1.425612s)

Après cela, regardez à nouveau votre tableau de recettes et vérifiez les résultats.

select * from yummy_data.Recipe

image

Je pense que je pourrais essayer la pizza à la courge poivrée ou le kimchi coréen au tofu et au porc :). De toute façon, je devrai vérifier à la maison :)

Notes finales

Vous pouvez trouver l'exemple complet sur https://github.com/isc-afuentes/recipe-inspector

Avec cet exemple simple, nous avons appris à utiliser les techniques LLM pour ajouter des fonctionnalités ou analyser certaines parties de vos données dans InterSystems IRIS.

Avec ce point de départ, vous pourriez penser à :

  • Utiliser InterSystems BI pour explorer et parcourir vos données à l'aide de cubes et de tableaux de bord.
  • Créer une application Web et fournir une interface utilisateur (par exemple Angular) pour cela, vous pouvez exploiter des packages tels que RESTForms2 pour générer automatiquement des API REST pour vos classes persistantes.
  • Et pourquoi garder en base l'information indiquant les recettes que vous aimez et celles que vous n'aimez pas, puis d'essayer de déterminer si une nouvelle recette vous plaira ? Vous pourriez essayer une approche IntegratedML, ou même une approche LLM fournissant des exemples de données et construisant un cas d'utilisation RAG (Retrieval Augmented Generation).

Quelles autres choses pourriez-vous essayer ? Laissez-moi savoir ce que vous pensez!

0
0 208