清除过滤器
文章
Lele Yang · 三月 31, 2023
《WebGateway系列(4): 配置HTTPS访问IRIS的Web服务》中介绍了在Web服务器中配置SSL/TLS以实现从客户端浏览器到Web服务器之间的安全连接,从Web服务器到IRIS之间是否也可以通过配置SSL/TLS建立起安全连接呢?尤其是在Web服务器与IRIS没有安装在同一台Server上的情况下,这段连接的安全性也是需要考虑的。答案是肯定的,接下来我们就来介绍下配置Web Gateway使用SSL/TLS连接到IRIS的基本步骤。
1.首先,我们先准备一下所需要的证书。通讯的双方为Web Gateway 和 IRIS Super Server, 双方都需要准备好各自的证书和key。IRIS自带的Public Key Infrastructure(PKI)功能内置了OpenSSL,可以用来生成服务器端及客户端的证书和key。在使用此功能时,IRIS可以同时作为CA Server和CA Client,作为CA Server时可以生成自签名的证书,可以批准CA Client的证书申请并将证书下发给CA Client。
1)配置本地证书颁发机构服务器,生成sever端的证书和key。
2)配置本地证书颁发机构客户端,如下
3)将证书签名请求提交到证书颁发机构服务器
4)进程未决证书签名请求
发放证书。
至此,Client以及Server端证书和key都已准备完成。
以下证书和key将用于Web Gateway,
/intersystems/irishealth/mgr/cac.cer
/intersystems/irishealth/mgr/cac.key
以下证书和key将用于IRIS Super Server
/intersystems/irishealth/dev/CAcerts/cas.cer
/intersystems/irishealth/dev/CAcerts/cas.key
当然也可以去申请商用的证书,也可以不使用PKI直接使用OpenSSL自己去生成。
2. 配置SSL/TLS, 名为%SuperServer
3. Enable Superserver SSL/TLS Support,
4. 在Web Server中配置Web Gateway。
本示例中所使用的Web Server为Apache2.4.6,操作系统为Redhat7.9。注意以下Web Gateway管理页面打开端口为默认的80。另外,上面生成好的证书拷贝至了/tmp/下。
对应的CSP.ini中内容如下,
[IRISHEALTH]
Ip_Address=localhost
TCP_Port=1972
Username=CSPSystem
Password=]]]c3lz
Minimum_Server_Connections=3
Maximum_Session_Connections=6
Connection_Security_Level=10
Product=2
SSLCC_Protocol=8@
SSLCC_Key_Type=2
SSLCC_Cipher_Suites=ALL:!aNULL:!eNULL:!EXP:!SSLv2
Env_Parameters=EV6
SSLCC_Certificate_File=/tmp/cac.cer
SSLCC_Certificate_Key_File=/tmp/cac.key
SSLCC_CA_Certificate_File=/tmp/cas.cer
SSLCC_Private_Key_Password=]]]MTIz
SSLCC_Verify_Peer=1
5. Web Gateway中Test Connection, 报错Server Unavailable。
CSP.log报错如下,
>>> Time: Wed Mar 29 12:00:36 2023; RT Build: 2101.1776 (linux/apapi:srv=2.4.6/apr=1.4.8/apu=1.5.2/mpm=prefork); Log-Level: -1; Gateway-PID: 4315; Gateway-TID: 139634317305600; Connection-No: 0; Server: IRISHEALTH; InterSystems IRIS-PID: 0; Request-ID: 249b
IRISCONNECT : Error Connecting to InterSystems IRIS : Unable to read SSL configuration
Cannot read SSL certificate file: /tmp/cac.cer
>>> Time: Wed Mar 29 12:00:36 2023; RT Build: 2101.1776 (linux/apapi:srv=2.4.6/apr=1.4.8/apu=1.5.2/mpm=prefork); Log-Level: 0; Gateway-PID: 4315; Gateway-TID: 139634317305600
Information: Terminate Connection
Connection closed by Gateway: Connection-No=0:0; Server=IRISHEALTH; InterSystems IRIS PID=0; Context=205;
>>> Time: Wed Mar 29 12:00:36 2023; RT Build: 2101.1776 (linux/apapi:srv=2.4.6/apr=1.4.8/apu=1.5.2/mpm=prefork); Log-Level: 0; Gateway-PID: 4315; Gateway-TID: 139634317305600; Connection-No: ; Request-ID: 249b; Session-ID: uoyakptQAD; Remote-Addr: ; Page: GET /csp/bin/RunTime/Module.cxw
Diagnostic
Failed to connect to 'IRISHEALTH' - Reason: -201 (SSL Configuration error) (No Retry)
解决办法,
将证书和key文件放置在Web Gateway安装路径下之后问题解决。
SSLCC_Certificate_File=/opt/webgateway/cac.cer
SSLCC_Certificate_Key_File=/opt/webgateway/cac.key
SSLCC_CA_Certificate_File=/opt/webgateway/cas.cer
[root@BJSRHELSUP webgateway]# ll
total 16
drwxr-xr-x. 2 root root 23 Sep 17 2021 apache
drwxr-xr-x. 2 root root 4096 Sep 17 2021 bin
-rwxr-xr-x 1 root root 1233 Mar 29 14:48 cac.cer
-rwxr-xr-x 1 root root 1834 Mar 29 14:49 cac.key
-rwxr-xr-x 1 root root 1164 Mar 29 14:49 cas.cer
drwxrwxr-x. 2 apache root 56 Aug 30 2022 conf
drwxrwxr-x. 2 apache root 57 Nov 4 2021 logs
drwx------. 2 apache root 6 Mar 29 14:41 temp
drwxr-xr-x. 2 root root 20 Sep 17 2021 util
6. Web Gateway中再次Test Connection,成功。
参考文档,
InterSystems Public Key Infrastructure
Configuring the Web Gateway to Connect to InterSystems IRIS Using TLS
文章
Jingwei Wang · 三月 28, 2023
IRIS 配置和用户帐户包含需要跟踪的各种数据元素,许多人难以在 IRIS 实例之间复制或同步这些系统配置和用户帐户。那么如何简化这个过程呢?
在软件工程中,CI/CD 或 CICD 是持续集成 (CI) 和(更常见的)持续交付或(较少见的)持续部署 (CD) 的组合实践集。 CI/CD 能消除我们所有的挣扎吗?
我在一个开发和部署 IRIS 集群的团队工作。我们在 Red Hat OpenShift 容器平台上的容器中运行 IRIS。
如果您当前没有使用 Kubernetes,请不要停止阅读。即使您没有使用 Kubernetes 或在容器中运行 IRIS,您也可能会遇到与我和我的团队面临的挑战类似的挑战。
我们决定将代码与配置分开,并将它们放在不同的 GitHub 存储库中。每次在代码库中进行提交时,都会触发管道运行。结果,从代码库中的文件构建了一个新image。
我们通过将 YAML 文件和其他配置工件添加到部署 GitHub 存储库,将配置定义为以 GitOps 方式使用的代码。 GitOps 是一个软件开发框架,它使组织能够持续交付软件应用程序,同时使用 Git 作为单一事实来源有效地管理 IT 基础设施(以及更多)。 GitOps 的好处之一是能够轻松回滚。您所需要做的就是恢复到 Git 中的先前状态。
DevOps 是软件开发和 IT 行业的一种方法论。作为一套实践和工具使用,DevOps 将软件开发(Dev) 和IT 运营(Ops) 的工作集成并自动化,作为改进和缩短系统开发生命周期的一种手段。 [1]
我在维基百科上读到持续交付是“当团队在短周期内以高速和频率生产软件时,以便可以随时发布可靠的软件,并在决定部署时采用简单且可重复的部署过程。”
同时,维基百科将持续部署定义为“当新软件功能完全自动推出时”。
我们已决定将 YAML 文件存储在部署 GitHub 存储库中。
iris-cpf(上面的第 19 行)指的是一个 ConfigMap,其中包含用于 CPF Merge 的文件。
有多种可用的 CD 管道工具可以将配置作为代码推送部署,而不必手动应用文件。
例如,我的团队使用Argo CD 。它是一个 GitOps 工具,作为 Kubernetes 扩展部署在集群中。它很特别,因为它在集群中具有可见性。它的用户界面在浏览器中显示应用程序状态,因为 Argo CD 是 Kubernetes 扩展。
与仅启用基于推送的部署的外部 CD 工具不同,Argo CD 可以从 Git 存储库中拉取更新的(类似)代码并将其直接部署到 Kubernetes 资源。
像 Argo CD 这样的拉动部署工具将我们的 Kubernetes 集群的实际状态与我们的部署 repo 中描述的期望状态进行比较。
Argo CD 监视我们的部署 repo 和我们的 Kubernetes 集群。我们的部署repo 是唯一的真实来源。如果 GitHub 存储库中发生某些更改,Argo CD 将更新集群以匹配存储库中定义的所需状态。
Argo CD 代理同步 GitHub 存储库和 Kubernetes 集群。如果我们手动应用一个更改,当 Argo CD 将已部署的应用程序同步到 Git 中定义的所需状态时,它将被删除。
为了将不同的配置部署到不同的集群,我们使用Kustomize 。我们在部署仓库中定义了一个基本配置。我们还在部署 GitHub 存储库中定义了覆盖,以便为开发、SQA、阶段和生产等各种环境配置不同的系统默认设置和不同的images。
在第 417 行中,我们确定基于环境的系统默认设置存储在 SDS_ENV.xml 中。
那些没有使用 Kubernetes 的情况呢?我创建了许多可在 Open Exchange 中使用的应用程序。我学习了如何使用 Installer 类在 GitHub 存储库中定义 IRIS 配置,然后构建image并运行容器。
然而,如果在部署应用程序后需要对配置或用户帐户进行一些修改,情况会怎样呢?当涉及到持久卷时,事情就变得复杂了。发生这种情况是因为我们不想丢失存在于持久卷上的数据。
存储在持久卷上的所有这些东西是什么? IRIS 配置保存在数据目录的 mgr 目录中。 CPF Merge 功能应该使我们能够修改 iris.cpf 中的任何配置设置。
我的团队已将大量代码添加到 %ZSTART routines中,这些routines在 IRIS 计算或数据实例启动时执行。我们担心的一个问题是所谓的零大小 CPF 错误。我们经常遇到 IRIS 实例因大小为零的 CPF 文件而崩溃的情况。不幸的是,我们尚未发现该问题的根本原因。我们怀疑 CPF 合并操作以及在 %ZSTART routine中添加和删除的大量Routine、Global和包映射会导致零大小的 CPF 错误。
我们编写了代码来删除所有系统默认设置,并从作为卷安装在 IRIS 容器中的 Kubernetes ConfigMap 中导入它们。事实上,我们有两组系统默认设置:一组是在所有环境中导入的基本设置,另一组是因环境而异的环境特定设置。
我们决定从 XML 文件中导入用户。有时,当我们直接从 %ZSTART routine 执行这段代码时,我们会遇到问题。我们根据 InterSystems 的建议将此代码移至计划任务中。显然,我们发现了一个在某些情况下可能会破坏全局安全性的错误。无论如何,出于某种我现在不记得的原因,当用户帐户导入由计划从 %ZSTART routine 按需运行的任务执行时,此问题不再是问题。这一定是时间问题。计划任务晚于 %ZSTART routine运行。
我们创建了一个自定义密码验证routine来强制执行密码规则。
当我们需要一个新的 Web 应用程序时,我们应该怎么做?除了 CPF Merge,CSP Merge 怎么样?
我相信 Web 应用程序存储在 %SYS IRIS.dat 文件中。我考虑尝试在可以使用 ConfigMap 挂载的文件中定义 Web 应用程序。我们可以将代码添加到 %ZSTART 例程或添加另一个计划任务来查找文件并创建 IRIS 中尚不存在的任何 Web 应用程序。
使用 InterSystems Kubernetes Operator 部署的 Webgateway 容器具有一个持久数据卷,其中包含 CSP.conf 和 CSP.ini。但是,我们还没有实现在添加新的 Web 应用程序时根据需要自动更新这些文件的方法。
Lorenzo Scalese 创建了可在 Open Exchange 中使用的 config-api 和 config-copy 应用程序。他建议在您的应用程序安装程序模块中使用 IRS-Config-API 库。
IRIS-Config-API 可以在一个环境将 IRIS 配置导出到 JSON 文档,并在另一个环境中从 JSON 文档导入 IRIS 配置。
Lorenzo 创建了 iris-config-copy 工具,用于从一个 InterSystems IRIS 实例导出配置并将其导入另一个实例。如果我们在源实例和目标实例上都安装 iris-config-copy,则目标实例使用 REST 从源实例获取配置。
我们需要在源实例上创建一个 Web 应用程序,以使目标实例能够从源实例中检索 IRIS 配置。
Iris-config-copy 可以导出本地实例或远程实例的 IRIS 配置。
有一些方法可以导入特定的配置文件。我们可以导入Security、包含 SQL 连接的globals、CPF 配置数据或任务。
文章
Kelly Huang · 三月 28, 2023
嗨大家好!
最近我需要使用 IRIS For Health 设置本地 FHIR 服务器,我认为我找到了有史以来最简单的方法!
只需在终端中运行以下两行:
docker run --rm --name my-iris -d --publish 9091:1972 --publish 9092:52773 intersystemsdc/irishealth-community
和
docker exec -it my-iris iris session iris -U "USER" '##class(%ZPM.PackageManager).Shell("install fhir-server")'
您将在 http://localhost:9092/fhir/r4 本地运行 FHIR 服务器。
就是这么简单!
FHIR 服务器将使用最新版本的 InterSystems IRIS for Health Community Edition,并将通过 FHIRSERVER 命名空间中的 IPM 包从该应用程序部署 FHIR 服务器。
这是针对 Mac OS的,所以请在评论中添加它在 Windows 中的工作方式。
这是一篇非常短的文章,因为使用 InterSystems IRIS for Health 和IPM Package Manager 设置本地 FHIR 服务器真的很容易。
原文来自于 @ Evgeny Shvarov
文章
water huang · 三月 27, 2023
一、背景
1.1 我遇到了几个项目,他们的接口服务器崩溃了。 项目上希望尽快恢复服务器。他们的服务器在局域网上运行,他们不能使用git,服务器中有多个命名空间运行不同的服务,而且通常只有一台平台服务器。
1.2 如果消息中有字符流类型的属性,消息搜索页面不支持使用字符流属性进行过滤,因此很难找到想要的消息。
1.3 其他同事可能会更新服务器上的代码,代码中可能有些错误。
2.挑战
2.1 如何快速恢复?
2.2 如何支持字符流属性过滤消息?
2.3 如何在编译类时自动备份?
3.解决方案
1.编译时自动导出为备份文件
首先,我们定义一个名为“SYS.base”的类,它只有一个名为“ CLSBAKPATH”的参数,并设置它的值
Class SYS.Base Extends %RegisteredObject
{
Parameter CLSBAKPATH = "D:\IRIS\CLSBAK" ;
}
然后,定义一个名为“SYS.Projection”的类,它继承了 base和%Projection.AbstractProjection,添加“Projection Reference As SYS.Projection”,重写类方法“CreateProjection”;
代码如下:
Class SYS.Projection Extends ( %Projection.AbstractProjection , Base)
{
Projection Reference As SYS.Projection ;
ClassMethod CreateProjection(classname As %String , ByRef parameters As %String , modified As %String , qstruct) As %Status
{ w ! s changetime=^oddDEF(classname,63)
s changetime=$zdt(changetime,3)
w "class"_classname_" is modified at "_changetime_" !",!
s CLSBAKPATH=..#CLSBAKPATH
i CLSBAKPATH[ "/" d
.s PL= "/"
e d
.s PL= "\"
s:$e(CLSBAKPATH,*)'=PL CLSBAKPATH=CLSBAKPATH_PL
s sc= $SYSTEM.OBJ.Export(classname_".cls",CLSBAKPATH_classname_$tr(changetime,":-","")_ ".xml" )
q $$$OK
}
}
执行该方法后,被编译的类将直接导出到目标路径“CLSBAKPATH”,它的名称将类似于“类名20230217130218.xml”
最后,如何使用它?
选择一个要自动备份的类,让它继承“SYS.Projection”。当类被编译时,它会被导出。如果你不修改重新编译它,它会覆盖旧的备份文件。
顺便说一句,我认为关键点是 %Projection.AbstractProjection,有了“CreateProjection”,我们可以做更多,如果你想在生产环境中更新一些代码,并且又不想让人再手动去执行一些目标方法代码,这是个好方法。他需要做的是将xml文件导入studio,并编译它,如果勾选“Compile Imported Items”框,那就不再需要单独编译。也就是导入的时候就会自动编译,编译的时候就自动执行,相当于就是导入后自动执行!
到目前为止,它只备份了一个类文件。如果我们想要备份更多怎么办?
方法来了!简单来说,挂任务!
通常用于备份接口代码和数据。
在本教程中,我们在本地驱动器中备份文件。
首先,我们定义一个名为“Common.SYS”的类
然后添加一个名为“ Export ”的类方法,它是主要方法,它将调用其他功能方法。 A导出类,B导出凭证,C导出GLB。
类看起来像:
Class Common.SYS Extends %RegisteredObject
{
/// Exportclass
ClassMethod ExportAllClassesIndividual(NS As %String = "" )
{
s Drive=..#Drive s currentns= $ZUTIL ( 67 , 6 , $j )
i NS'= "" d
.w:'$d(^["%sys"]CONFIG("Namespaces",NS)) "namespace "_NS_" is not existed,please check it!" ,!
.q:'$d(^[ "%sys"]CONFIG("Namespaces",NS))
.zn NS
.s FilePath=Drive_":/BakFile/"_NS_"/"
.i '##class(%File).DirectoryExists(FilePath) d
..d ##class(%File).CreateDirectoryChain(FilePath)
.s sc= $system .OBJ.ExportAllClassesIndividual(FilePath,"b",.el,"","CDYZone,Sample,User" )
.i sc'=1 d
..w " namespace "_NS_" get an error when export class! "_$System.Status.GetErrorText(sc),!
e d
.s alns=""
.f s alns=$o(^["%sys"]CONFIG("Namespaces",alns)) q:alns="" d
..q:$e(alns,1)="%"
..q:(alns="ENSDEMO")||(alns="ENSEMBLE")||(alns["-")
..q:'$d(^[alns]CacheMsg("Confirm"))
..zn alns
..s FilePath=Drive_":/BakFile/"_alns_"/"
..i '##class(%File).DirectoryExists(FilePath) d
...d ##class(%File).CreateDirectoryChain(FilePath)
..s sc=$system.OBJ.ExportAllClassesIndividual(FilePath,"b",.el,"","Common,SYS" )
..i sc'=1 d
...w " namespace "_alns_" get an error when export class! "_ $System.Status.GetErrorText(sc),!
zn currentns
q $$$OK
}
/// Ens.Config.Credentials
ClassMethod ExportAllCredentials(NS As %String = "" )
{
s Drive=..#Drive
s currentns= $ZUTIL ( 67 , 6 , $j )
i NS'= "" d
. w :' $d (^[ "%sys" ]CONFIG( "Namespaces" ,NS)) "namespace " _NS_ " is not existed,please check it!" ,!
. q :' $d (^[ "%sys" ]CONFIG( "Namespaces" ,NS))
. q :' $d (^[NS]Ens.Conf.CredentialsD)
. zn NS
. s Data=[]
. s FilePath=Drive_ ":/BakFile/" _NS_ "/Ens_Config_Credentials"
.i ' ##class ( %File ).DirectoryExists(FilePath) d
..d ##class ( %File ).CreateDirectoryChain(FilePath)
. s Data=[]
. s CID= ""
.f s CID= $o ( ^Ens .Conf.CredentialsD(CID)) q :CID= "" d
..s obj= ##class (Ens.Config.Credentials). %OpenId (CID)
..q :' $IsObject (obj)
..s data={}
..s data.SystemName=obj.SystemName
..s data.Username=obj.Username
..s data.Password=obj.Password
..d Data. %Push (data)
. d :Data. %Size ()> 0 ..SaveFile (FilePath,Data. %ToJSON ())
e d
. ;w currentns,!
. s alns= ""
.f s alns= $o (^[ "%sys" ]CONFIG( "Namespaces" ,alns)) q :alns= "" d
..q : $e (alns, 1 )= "%"
..q :(alns= "ENSDEMO" )||(alns= "ENSEMBLE" )||(alns[ "-" )
..q :' $d (^[alns]CacheMsg( "Confirm" ))
..q :' $d (^[alns]Ens.Conf.CredentialsD)
..zn alns
..s FilePath=Drive_ ":/BakFile/" _alns_ "/Ens_Config_Credentials"
..i ' ##class ( %File ).DirectoryExists(FilePath) d
. ..d ##class ( %File ).CreateDirectoryChain(FilePath)
..s Data=[]
..s CID= ""
..f s CID= $o ( ^Ens .Conf.CredentialsD(CID)) q :CID= "" d
. ..s obj= ##class (Ens.Config.Credentials). %OpenId (CID)
. ..q :' $IsObject (obj)
. ..s data={}
. ..s data.SystemName=obj.SystemName
. ..s data.Username=obj.Username
. ..s data.Password=obj.Password
. ..d Data. %Push (data)
..d :Data. %Size ()> 0 ..SaveFile (FilePath,Data. %ToJSON ())
zn currentns
q $$$OK
}
ClassMethod SaveFile(FilePath, Data)
{
s file= ##class ( %FileCharacterStream ). %New ()
s file.Filename=FilePath_ "/Credentials.JSON"
d file. Write (Data)
s sc=file. %Save ()
i sc'= 1 d
. w FilePath_ " save Credential failed! " _ $System .Status.GetErrorText(sc),!
e d . w FilePath_ " save Credential success! " ,!
q $$$OK
}
ClassMethod SaveGLB(NS)
{
s Drive=..#Drive
w :' $d (^[ "%sys" ]CONFIG( "Namespaces" ,NS)) "namespace " _NS_ " is not existed,please check it!" ,!
q :' $d (^[ "%sys" ]CONFIG( "Namespaces" ,NS)) 1
s rset = ##class ( %ResultSet ). %New ( "%SYS.GlobalQuery:NameSpaceList" )
q :'rset.QueryIsValid() "invalid Query:"
d rset.Execute(NS, "CDY*" )
s Flag= 0
while (rset.Next()){
s HasData=rset.GetDataByName( "HasData" )
i HasData= 1 d
. s Name=rset.GetDataByName( "Name" )
. q :Name[ "PushConfigListD" ;some needed globals
. s Data(Name)= 1
. s Flag= 1
}
w :Flag= 0 NS_ " namespace doesn't have global to be exported" ,!
q :Flag= 0 NS_ " namespace doesn't have global to be exported"
s FilePath=Drive_ ":/BakFile/" _NS_ "/GLB/"
i ' ##class ( %File ).DirectoryExists(FilePath) d
. d ##class ( %File ).CreateDirectoryChain(FilePath)
q ##class ( %Library.Global ).Export(NS,.Data,FilePath_ "SYS.gof" )
}
/// ExportAll CDY* Globals
ClassMethod ExportAllCDYGLB(NS As %String = "" )
{
s currentns= $ZUTIL ( 67 , 6 , $j )
i NS'= "" d
. w :' $d (^[ "%sys" ]CONFIG( "Namespaces" ,NS)) "namespace " _NS_ " is not existed,please check it!" ,!
. q :' $d (^[ "%sys" ]CONFIG( "Namespaces" ,NS))
. s sc= ..SaveGLB (NS)
.i sc'= 1 d
..w " namespace " _NS_ " get an error when export global! " _ $System .Status.GetErrorText(sc),!
e d
. s alns= ""
.f s alns= $o (^[ "%sys" ]CONFIG( "Namespaces" ,alns)) q :alns= "" d
..q : $e (alns, 1 )= "%"
..q :(alns= "ENSDEMO" )||(alns= "ENSEMBLE" )||(alns[ "-" )
..q :' $d (^[alns]CacheMsg( "Confirm" ))
..s sc= ..SaveGLB (alns)
..i sc'= 1 d
. ..w " namespace" _alns_ " get an error when export global! " _ $System .Status.GetErrorText(sc),!
zn currentns
q $$$OK
}
/// location to store backuped file
Parameter Drive = "d" ;
ClassMethod Export()
{
s NS= "" ///namespace
d ..ExportAllClassesIndividual (NS) ///class file(include package)
d ..ExportAllCredentials (NS) ///Credential information
d ..ExportAllCDYGLB (NS) ///Global file, or data
q $$$OK
}
}
在 iris 中添加一个自定义任务,你就能保留最新的代码和数据。
优化消息搜索
当我得到使消息搜索页面支持使用字符流类型的属性进行过滤的解决方案时(为了解决这个问题,我问 intersystems 的工程师,她告诉我,使用“EnsPortal.MsgFilter.Assistant”,覆盖类方法“GetSQLCondition”。所以我做了一个类扩展 EnsPortal.MsgFilter.Assistant.it 似乎已经解决了问题。在编译类之后然后 s ^EnsPortal.Settings("MessageViewer","AssistantClass")=class
).
我写的代码如下:
Class ENSLIB.MsgFilterAssistant Extends EnsPortal.MsgFilter.Assistant
{
ClassMethod GetSQLCondition(pOperator As %String , pProp As %String , pValue As %String , pDisplay As %Boolean = 0 ) As %String
{
if (pValue = "" ) || ((pOperator '= "Like" ) && (pOperator '= "NotLike" )) quit ##super (pOperator, pProp, pValue, pDisplay)
if ( "%%" = $extract (pValue, *- 2 , *- 1 ))
{
set pValue = "'" _ $extract (pValue, 1 , *- 3 ) _ "' ESCAPE '" _ $extract (pValue, *) _ "'"
} else {
set pValue = "'" _ $replace (pValue, "'" , "''" ) _ "'"
}
quit "substring(" _ pProp _ ", 1, 3000000) " _ $case (pOperator, "Like" : "LIKE" , "NotLike" : "NOT LIKE" ) _ " " _ pValue
}
/// w ##class(ENSLIB.MsgFilterAssistant).SetMV()
ClassMethod SetMV()
{
s ^EnsPortal .Settings( "MessageViewer" , "AssistantClass" )= "ENSLIB.MsgFilterAssistant"
q $$$OK
}
}
导入代码后,必须有人执行'##class(ENSLIB.MsgFilterAssistant).SetMV()',然后它才能工作!所以我想如果有一种方法可以在导入或编译后自动运行 SetMV,我寻找解决方案,从论坛到开放交换,最后我想到可以用 Projection,代码更改为:
Class ENSLIB.MsgFilterAssistant Extends (EnsPortal.MsgFilter.Assistant, %Projection.AbstractProjection )
{
Projection Reference As MsgFilterAssistant ;
ClassMethod GetSQLCondition(pOperator As %String , pProp As %String , pValue As %String , pDisplay As %Boolean = 0 ) As %String
{
if (pValue = "" ) || ((pOperator '= "Like" ) && (pOperator '= "NotLike" )) quit ##super (pOperator, pProp, pValue, pDisplay)
if ( "%%" = $extract (pValue, *- 2 , *- 1 ))
{
set pValue = "'" _ $extract (pValue, 1 , *- 3 ) _ "' ESCAPE '" _ $extract (pValue, *) _ "'"
} else {
set pValue = "'" _ $replace (pValue, "'" , "''" ) _ "'"
}
quit "substring(" _ pProp _ ", 1, 3000000) " _ $case (pOperator, "Like" : "LIKE" , "NotLike" : "NOT LIKE" ) _ " " _ pValue }
/// w ##class(ENSLIB.MsgFilterAssistant).SetMV()
ClassMethod SetMV()
{
s ^EnsPortal .Settings( "MessageViewer" , "AssistantClass" )= $this
q $$$OK
}
ClassMethod CreateProjection(cls As %String , ByRef params) As %Status
{
w ! w "开始执行" ,!
d ..SetMV ()
w "执行完成" ,!
q $$$OK
}
}
类编译完成后会自动执行SetMV!是否有更好的实现方式呢?
如果你有更好的方法,请分享!
4.更多
我将继续寻找更好的方法来复制源类和配置数据。 为黄老师点赞!
问题
j ay · 三月 22, 2023
1、默认samples空间没有Backup.General无法进行外部备份
2、%SYS空间有Backup.General
Backup.General怎么在其他空间里创建这个类 我没明白问题, 外部备份是在%sys命名空间执行的呀, 为什么要在在sample里执行备份呢? 1、我对这个cache不太理解,第一次做这个,我目前做的外部备份是:
前提:所有数据都是用sample命名空间进行添加的
a. 用sample命名空间,去连接cache,调用Backup.General ExternalFreeze进行冻结
b. 备份mgr目录下面sample数据库文件CACHE.DAT
c. 调用ExternalThaw解冻
问题:1.如果我用%SYS命名空间去冻结解冻,备份mgr目录下面sample数据库文件CACHE.DAT,数据是恢复不了的
2.日志journal备份后在重新写入恢复,cache会启动不了
我不知道这样的备份恢复流程对不对,能说一下正确的外部备份流程吗 冻结其实是控制系统的写进程,让它暂时挂起来,在数据库日志上做个标记。这些都不是那一个数据库比如sample的事情,是整个系统的操作。
你的问题1: 如果我用%SYS命名空间去冻结解冻,备份mgr目录下面sample数据库文件CACHE.DAT,数据是恢复不了的。 怎么恢复不了?那一步出错了?
问题2: 你是先恢复数据库, 再恢复日志的是吗?出的什么错误?
这样, 你先看看这两个链接, 如果在有问题, 我找我们的专家和你私聊。第2个帖子有点长,里面连冻结解冻的脚本都包括了, 很详细 ,:)
https://cn.community.intersystems.com/post/faq-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E7%B3%BB%E5%88%97-%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E7%AF%87-%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%87%E4%BB%BD
https://community.intersystems.com/post/intersystems-data-platforms-and-performance-%E2%80%93-vm-backups-and-cach%C3%A9-freezethaw-scripts
公告
Michael Lei · 三月 22, 2023
大家好!
第二次数字健康互操作与FHIR创业孵化器——Caelestinus,今日启动!
今天,21 支选定的队伍将在 Caelestinus 开始为期八个月的旅程。在孵化期间,团队将数字健康互操作性引入到他们的互联医疗服务或医疗设备创新中,并添加对 FHIR、HL7、DICOM、CDA、X12 和其他数字健康标准的支持,并使用InterSystems IRIS for Health和FHIR Server进行转型在经验丰富的 InterSystems 团队的帮助下。
我很高兴邀请大家观看 Caelestinus 2023 启动活动直播,您可以在其中了解哪些团队被选中以及他们的创新想法。
请从欧洲中部时间下午 3 点开始通过www.caelestinus.tech观看流媒体。
很高兴在在线上与您相见。
祝 Caelestini 初创公司好运!
问题
j ay · 三月 22, 2023
1、java如何连接cache2016数据库
2、java如何调用cache的函数
"Backup.General", "ExternalFreeze", Using the JDBC Driver | Using Java with InterSystems Software | InterSystems IRIS for Health 2023.1请参阅这个文档来使用jdbc 链接cache 数据库,
Native SDK for Java | InterSystems IRIS for Health 2023.1 如果要调用任何的 cache 服务器端的代码,可以使用Native SDK for Java 使用方法请参阅上面的文档
文章
Michael Lei · 三月 21, 2023
InterSystems IRIS 是一个高性能、可靠且可扩展的数据平台,用于为医疗保健、金融服务和其他行业构建和部署关键任务应用程序。它提供了广泛的功能,包括数据管理、集成、分析等。
IRIS 提供的功能之一是能够将 Python 代码嵌入到 ObjectScript 代码中。这意味着您可以在 IRIS 应用程序中使用 Python 库和函数,让您可以访问大量的工具和资源。在本文中,我们将了解如何在 InterSystems IRIS 中使用嵌入式 Python。
设置嵌入式 Python
在 IRIS 中开始使用嵌入式 Python 之前,您需要设置环境。这涉及安装 Python 解释器和配置 IRIS 以识别它。
第一步是安装 Python。您可以从官方网站 ( https://www.python.org/downloads/ ) 下载最新版本的 Python。安装 Python 后,需要将其添加到系统的 PATH 环境变量中。这允许 IRIS 找到 Python 解释器。
接下来,您需要配置 IRIS 以识别 Python。为此,您需要创建一个 Python 网关。网关是一个在 IRIS 之外运行的进程,充当 IRIS 和 Python 之间的桥梁。
要创建网关,请打开一个终端窗口并导航到 Python 安装目录。然后运行以下命令:
python -m irisnative
此命令启动 Python 网关并创建到 IRIS 的连接。您应该看到类似于以下内容的输出:
Python Gateway Version: 0.7 Python Version: 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0] Connected to: IRIS
这表明 Python 网关正在运行并连接到 IRIS。
在 IRIS 中使用嵌入式 Python
现在您已经设置了环境,您可以开始在 IRIS 中使用 Python。为此,您需要使用 ##class(%Net.Remote.Gateway).%New() 方法创建到 Python 网关的连接。此方法返回对可用于执行 Python 代码的 Python 对象的引用。
以下是如何使用嵌入式 Python 计算两个数字之和的示例:
Set gateway = ## class (%Net.Remote.Gateway).% New () Set result = gateway.% Execute ( "2 + 3" ) Write "Result: " , result , !
在此示例中,我们使用 %New() 方法创建到 Python 网关的连接。然后我们执行Python代码"2 + 3",返回结果5。我们将结果存储在result-变量中并输出到控制台。
在 IRIS 中使用 Python 库
在 IRIS 中使用嵌入式 Python 的好处之一是能够使用 Python 库。 Python 拥有庞大的库生态系统,用于数据处理、机器学习等。通过使用这些库,您可以扩展 IRIS 应用程序的功能。
要在 IRIS 中使用 Python 库,您首先需要使用 pip包管理器安装该库。例如,要安装 numpy 库,请运行以下命令:
pip install numpy
安装该库后,您可以通过使用 Python 网关导入它来在 IRIS 应用程序中使用它。以下是如何使用 numpy库创建矩阵的示例:
vbnet
Set gateway = ##class(%Net.Remote.Gateway).%New() Set np = gateway.%Get("numpy") Set matrix = np.%New("array", 10, 10)
在这个例子中,
我们使用 %New()方法创建到 Python 网关的连接。然后我们使用 -%Get() 方法检索对 numpy 库的引用。我们使用 numpy 库中的 array 方法创建一个新矩阵,大小为 10 x 10。我们将矩阵存储在matrix 变量,然后我们可以在我们的 IRIS 应用程序中使用它。
结论
在本文中,我们了解了如何在 InterSystems IRIS 中使用嵌入式 Python。我们已经了解了如何在 IRIS 中设置环境、执行 Python 代码和使用 Python 库。使用嵌入式 Python 可以扩展 IRIS 应用程序的功能,使您能够访问大量的工具和资源。通过将 Python 的强大功能与 IRIS 的性能和可靠性相结合,您可以构建满足组织需求的关键任务应用程序。
文章
Tingting Jiang · 三月 21, 2023
注意:请投递时,发送英文简历!
工作概述
每年夏天InterSystems都会招聘实习生在中国办公室工作,从事专门围绕InterSystems产品设计的项目。我们信任实习生团队在导师的指导下可独立的工作。除了在项目中工作外,实习生还能融入我们的团队,与我们的全职员工一起解决所面对的工作问题。
InterSystems的带薪暑期实习项目可以让学生接触到在重要的职业生涯中出类拔萃所需的各种技术和软技能。
我们希望实习生可以累计工作时长4个月,预计于2023年6月份开始。
工作职责
参加必要的培训课程,成功完成实习期间分配的项目。
在导师和其他InterSytems员工的指导下,成功地完成分配给他们团队的项目。
向高层领导和InterSystems的员工展示他们的项目。
遵守实习计划的所有要求(包括出勤、着装、行为)。
遵守公司关于实习的合理指示。
在公司规定的时间内可以进行活动。
如果在实习期间有任何计划外的缺席,请及时通知人力资源部门。
遵守适合公司的职业行为标准。
遵守公司的政策和程序,包括那些与WHS和就业公平和多样性有关的政策和程序。
在任何时候都要适当地、负责任地使用公司的资源。
承担所有与实习有关的评估活动。
对在实习期间获得的有关公司、员工、客户和公司业务的信息进行保密。
公司可能不时地指示其他职责。
任职条件
优先有以下一种或多种编码经验:Python、InterSystems ObjectScript、Node.js、SQL、XSLT和AngularJS在敏捷团队中工作,或类似的经验。
技术上的好奇心。
对复杂的技术挑战有创造力。
协作的团队心态。
在不断变化的工作环境中表现出灵活的态度。
主动为自己的职业生涯打下技术基础。
专业要求
计算机等相关专业的本科生、硕士生或者博士在读学生。
薪资
本科生:RMB6,000/月;硕士生:RMB7,000/月;博士生:RMB8,000/月。
工作地点
北京市朝阳区建国门外大街1号银泰中心写字楼C座2701
如何申请
请点击链接InterSystems Careers, 或在2023年4月30日前发送邮件至recruitment.asiapacific@intersystems.com。
不知道我可不可以 你可以给实习生当老师 哈哈哈哈
公告
Claire Zheng · 三月 15, 2023
Hi 开发者社区的成员们,大家好!
欢迎关注我们第4期 InterSystems Ideas News!
我们将分享如下:
如何支持你们team的想法和投票。
在编程大赛中,用户实践Idea(创意)并获得技术奖励。
InterSystems 开发者社区的深色主题版本:是或否(Yay or Nay?)?
最近添加的Idea(创意)。
最重要的消息是,在上一届编程大赛中,有 5 名参赛者因实践InterSystems Ideas 门户网站的创意而获得加分!他们是:
开发者
应用名称
实施的Idea(创意)
@Lorenzo Scalese
OpenAPI-Suite
添加类似于 SOAP 向导的向导,以根据 OpenAPI 规范生成 REST 客户端
@José Roberto Pereira @Henrique Dias @Henry Pereira
iris-tripleslash
添加有助于为 ObjectScript 类生成单元测试的项目
@Sergey Mikhailenko
gateway-sql, apptools-admin
创建一个 UI,以便将项目(类、全局变量、应用程序、用户、角色、特权、授权、命名空间映射、SQL 网关、库等)方便、轻松地传输到其他系统实例以进行快速部署。
我们添加了一个新过滤器“我的组织(My organization)”。从现在开始,来自同一公司的人可以过滤来自同一组织的人的想法和投票。
前几天,@Guillaume Rongier 发布了关于为开发者社区添加深色主题的Idea(创意)。我们非常期待您参与 Ideas Portal 主页上的“民意测验”提供意见反馈,或对该想法进行投票和评论。
最近添加的想法
InterSystems Community 深色版本
为 DC 上的工作机会部分添加工作地点
新功能的可搜索索引
通过环境变量设置密码
安排在 DC 站点上发布文章
在 DC 文本编辑器上支持 JSON
支持 DC 文本编辑器上的 linux bash 语言
使用 SQL 命令将数据从 IRIS 捕获更改为 kafka
跨生产互操作消息、服务和操作
ISC 产品的附加数据类型
DTL、BPL 和规则集中 XData 的自动 XML 格式化
断言 CodeAssist 提示
OpenAI API 的 IRIS 类
在消息属性选项卡上显示 UserValues 内容
虹膜即服务
允许在 VS 代码中对互操作性组件 BPL、DTL 和业务规则进行图形编辑
为所有 IRIS 互操作性组件添加源代码控制
审计查找表
为 WRC 门票添加“观察名单”(问题、问题)
连接 InterSystems 文档和开发人员社区
在 npm 上发布适用于 Node.js 的 InterSystems IRIS Native SDK
像往常一样,在InterSystems Ideas上发布您的想法,对现有想法进行投票和评论,并实践Community Opportunity 的Idea(创意)。
请继续关注我们的下一个新闻公告!
文章
Claire Zheng · 三月 14, 2023
本文根据InterSystems中国技术总监乔鹏( @Peng.Qiao )的演讲“互联互通套件赋能数据利用与应用创新”整理而成。
IRIS医疗版互联互通套件的缘起与发展演进
来源HL7:正在到来的挑战
http://hl7.org/fhir/change.html
这是来自HL7官网上的一张图,描述了我们在医疗卫生行业面临的一些挑战,以及信息化建设在应对挑战中发挥的作用。当今,医疗卫生、生物学、信息技术有很强的融合趋势,加之社会变革带来的经济方面的需求,同时构成颠覆传统医疗卫生行业的因素。
这张图显示了从“被动医疗”转向“主动医疗”过程中信息的爆炸式增长,信息共享交换推动了我们对信息的利用,在这一进程中,医疗卫生信息化起着核心作用——而让信息更具价值,赋予信息标准化和互操作能力的过程,这也是InterSystems一直努力的方向,我们在国内支持大量医院实现了互联互通建设。在建设过程中,我们注意到项目的定量部分的建设成本占比是比较高的,很多的工作都花在了合规性和相关管理工具的开发上——应用标准的实施是有成本的,而对于标准的理解在各个项目上水平不尽相同,这就进一步影响了互联互通项目的建设成果。有鉴于此,2021年我们发布了InterSystems IRIS医疗版互联互通套件1.0版,初衷在于将我国的互联互通建设标准放到我们自己的技术平台里,为用户提供开箱即用的、标准合规性的基础和相应工具——这套工具包括了我们的医疗卫生信息模型、文档模型与管理、互联互通服务接口等,从而可以降低用户的实施成本和相应的实施风险。
在互联互通套件1.0版,我们提供了这样一些能力:
· 在医疗卫生信息模型部分,我们提供了完整的卫生数据元与值集管理、数据集管理,并且提供了本地术语注册,以及针对于本地术语和标准术语之间的转换服务。
· 在文档部分,我们提供了电子病历文档模型和模型管理能力、电子病历文档的校验、数据源质量的分析,以及自动生成合规的互联互通文档。
· 在服务部分,我们提供了互联互通标准服务接口、互联互通标准消息模型、ESB服务总线,以及通用的服务发布/订阅功能。
我们知道,互联互通评测的目标之一就是“以评促用”,实现合规仅仅是第一步,我们希望可以为用户提供更多能力,让用户可以真正把符合互联互通标准的医院信息平台应用起来。于是我们继续发布了InterSystems IRIS医疗版互联互通套件2.0版。
传统数据中心建设面临的一个普遍问题是标准缺乏,导致数据中心的建设成本相对较高,而且复用性很差,很难形成生态。因为缺乏标准,所以数据治理、上面可以运行的数据应用,大多都是由数据厂商自己开发的,这就像早期不同的手机厂商提供的功能手机,就那么几个应用可以用,它不是智能手机,功能是非常有限的。
所以2.0版强调的是生态。在规划2.0版的时候,我们将重点放在了核心数据资产上——我们希望在2.0中建设、治理、保存核心数据资产,助力用户应用好数据资产,并且通过基于标准的开放能力,推动医疗卫生信息化的生态建设。
我们在2.0版打通了国内互联互通和FHIR两大生态,希望通过这种生态融合提升数据资产的价值。我们借助FHIR来治理数据资产,令互联互通消息和互联互通文档都能够转换成FHIR资源,直接保存在FHIR资源仓库里面。
我们使用FHIR资源模型来提供统一的行业语义,通过FHIR API,包括InterSystems提供的互联互通服务,向用户提供统一的、基于行业语义的互操作能力,这样一来,用户能够以生态的方式来扩展数据资产的利用,体现数据资产的核心价值。
我们也注意到,行业中的确已经有很多关于微服务架构的思考。在2.0版本上,我们还扩展了服务架构,新增了对新的应用开发架构——微服务架构——的支持,这对于微服务架构在行业中的落地肯定是有推动作用的。
此外,我们增加了全面的API网关能力,用户可以通过 API网关的形式,对访问互联互通的医院信息平台的这些客户端来进行流量控制、认证管理等,实现服务的全生命周期管理。
在2.0版中,我们还提供了一个完整的FHIR服务器,以打通FHIR生态与国内互联互通生态。在决策支持上,FHIR生态已经提供决策支持架构和利用机器学习的一些用例,我们也基于FHIR为决策者提供完整的、关联的、实时的决策要素,比如说通过底层互操作架构来提供整个流程闭环的基础,通过内置的机器学习、自然语言处理、商业智能等工具,为用户提供数据决策支持工具。
在平台监控方面,2.0版新增了互联互通监控指标,以及针对通用的互操作性的指标监控能力。
在实际工作中,我们注意到互联互通项目建成之后,有一些项目的建设成果并没有得到全面地利用。例如,根据最近一位北京专家的调研结果,很多用户在电子健康档案的相关项目建设上面花费了巨额经费,但是在数据调阅频次上面却“低得出人意料”——我想这是相当一部分项目的现状。
互联互通建设的成果是我们的医院信息平台,我们是以医院互联互通为标准来建设医院信息平台的,那么医院信息平台上的数据利用应该是我们的核心。
因此在3.0的版本里,我们希望以最佳实践的方式来展现如何充分利用我们的互联互通的生态,提升互联互通价值,通过向用户提供一些用例,抛砖引玉地引导用户来正确使用互联互通建设成果,真正发挥出数据的价值。我们规划了两类互联互通应用方向:一个是数据利用,另一个是应用创新。
数据利用可以有很多方向,例如数字孪生,我们可以通过更完整、更实时的数据来建立准确、实时的患者画像;例如数据编织(data fabric),我们可以把所有数据来源进行统一编织,建立一个跨数据来源的、统一的语义平台;例如在数据流通领域发挥核心价值。
在应用创新上,借助打通FHIR和互联互通发展生态,我们可以利用FHIR应用能力来建设互联互通的应用生态。例如在FHIR生态里有Smart on FHIR,这是一个全新的、即插即用的软件开发的架构;再如基于FHIR生态的CDS Hooks决策支持架构等。这些都是我们可以来参考、引进和学习的。
我借助两则近期的新闻来介绍一下如何利用互联互通建设生态来满足数据利用和应用创新。
“数据二十条”:打破数据垄断、实现数据要素价值
2022年12月19日,国务院发布了《中共中央 国务院关于构建数据基础制度更好发挥数据要素作用的意见》(以下简称“《意见》”)。
这份意见为数据流通奠定了一个政策基础。简单梳理一下这份重要的意见里面关键词可以发现其核心就是打破数据垄断、实现数据要素价值。
关键词梳理,依据《中共中央国务院关于构建数据基础制度更好发挥数据要素作用的意见》
在实现方法上,我们就要重视对数据质量标准化体系的建设,基于信息安全和标准化的数据采集,整合互联互通和互操作性,《意见》在实现方法上面提出了一些非常重要的观点,如原始数据不出域,数据可用不可见等等这样的一些关键点,都是我们未来在医疗卫生信息数据流通上的指导思想和指导原则。
那么互联互通套件如何来支持这种政策要求?
在互联互通套件2.0架构里面,我们治理后的医疗卫生信息保存在FHIR资源仓库里。FHIR这种对象模型非常适合表达医疗卫生的复杂数据模型,但是对类似数据分析上报这些传统应用来说,通常会使用基于SQL的数据分析和操作工具,如果使用FHIR资源,操作起来是很难的。此外,要让用户直接使用FHIR资源仓库,也不符合《意见》提到的“原始数据不出域”的要求。
所以互联互通套件提供了FHIR SQL构建器,这是一个图形化的工具,用户可以将FHIR资源按需求映射成不同的SQL表——例如数据上报需要用到数据的一部分内容,可能内部数据用户对于数据需求范围是比较大的,外部用户对于数据需求范围可能就会更窄一些——不管是用户需求是什么样的,都可以通过映射的方式提供相应的SQL表。这种方式既满足了数据用户,使他们能够通过熟悉的工具(SQL)获得数据和操作数据,同时也满足了“原始数据不出域”的要求。
另外需要强调的一点是,SQL映射不是创建一份数据拷贝。它并没有把FHIR资源仓库原始数据拷贝给用户,而是通过映射的方式,映射出来一份虚拟SQL表。用户可以以SQL的访问方式来操作它——通过这种模式提供的数据是实时的、完整的、按需提供的。
Epic的生态创新:以标准为基础,推动应用建设的专业化
互联互通赋能应用创新这部分,面临着很多基于标准的问题和限制。
以美国为例,美国国家卫生IT协调员办公室研究发现,只有29%的用户能够将外部来源的卫生信息和应用整合到自己的电子健康档案中,也就是说美国是没有实现“应用通”的,只有不到1/3的电子健康档案是可以使用别的厂商开发的应用的。
2022年12月还有一个非常重要的新闻,12月9日的这则新闻来自全球电子病历领头羊Epic,Epic发布了名为“Connection Hub”的平台,这个平台向所有开发者开放。
这意味着什么?
我们来看看Epic目前拥有的能力。作为一个电子病历厂商,Epic有自己的应用市场,类似于智能手机的应用市场。
截至2022年12月22日,这个应用市场里共有619个应用,这些应用都是不同厂商开发的,这些应用都可以作为一个即插即用的应用直接下载并安装在Epic的电子健康档案系统上,所以这是一个非常有意思的事情。
作为行业里最重要的电子病历厂商之一,Epic对这些应用的开发趋势,包括它持有的这种开放的、应用的生态理念,我相信会为行业应用创新带来很多价值。
回顾一下我们面临的现状,我们的数据中心是缺乏标准的,每个厂商的数据中心都是不同的数据模型,提供厂商自定义的数据接口,所以当基于这些数据来进行应用开发的时候,我们做的是低水平重复建设和无法复用的应用建设。
例如,几乎每个项目的数据中心产品里都会部署一个患者360视图或类似应用,但这个应用每个厂商、甚至每个项目都会重新开发一次,所以这是一个低水平重复建设的典型应用。而且即便觉得好,如果换一个数据中心产品,这个应用也无法直接移植过去。
在缺乏标准的情况下,这些数据中心及相关的应用建设变得非常昂贵。如果我们整个行业能够采用一个标准的语义来建设数据中心或者电子健康档案,那么通过提供基于行业统一语义的数据和基于标准的数据接口,就可以让应用开发厂商只需关注在业务,潜心开发高水平应用。而且基于生态标准的应用可以运行在任何基于标准的数据中心(或电子健康档案)上,这就为释放数据应用价值奠定了非常好的基础。
回到前面这则新闻,Epic的标准是什么?Epic采用了FHIR标准,它基于最新的R4开放了55个资源和450个FHIR API,这样一来,它就可以运行类似于“儿童生长发育曲线”这类的Smart on FHIR应用,加速应用创新。
Epic能做到的,我相信我们也可以借鉴,InterSystems IRIS医疗版互联互通套件已经提供了针对FHIR仓库的能力,并且打通了互联互通与FHIR生态。
InterSystems IRIS医疗版
互联互通套件能力
以互联互通为基础,让医院信息平台成为数字化转型的核心
我想借助这张IDC于2019年发布的“数字化转型平台”示意图作为结尾。这张图是一张概念图,描述了我们数字化转型平台的功能,以及通过无限循环的路径来摆脱传统的技术栈的思维模式。
它将数字化转型平台定义为一个加速企业数字化转型的技术架构,用来支撑我们快速创建面向市场的数字化的服务和体验的平台。同时通过它来积极推动机构内部IT环境的现代化,使它成为将数据运用于业务的智能核心——基于互联互通将数据、算法、代码和模型进行资产化管理、整理、复用和共享。
数字化转型已经颠覆了很多行业,我相信医疗卫生信息行业也不会例外。我们希望通过互联互通套件,以互联互通为基础,让医院信息平台成为医疗卫生行业数字化转型的智能核心。
文章
Claire Zheng · 三月 14, 2023
数字化转型已经颠覆了很多行业,相信医疗卫生信息行业也不会例外。我们希望通过InterSystems IRIS医疗版互联互通套件,以互联互通为基础,让医院信息平台成为医疗卫生行业数字化转型的智能核心。
文章
Michael Lei · 三月 10, 2023
InterSystems IRIS 2022.2 具有适用于 Python 的原生 SDK (https://docs.intersystems.com/iris20222/csp/docbook/Doc.View.cls?KEY=PAGE_python_native)。
我们知道如何使用 IRIS Object Script $Order 函数遍历Global数据结构。
SET key= "" FOR { SET key= $ORDER ( ^myglobal (key)) QUIT :key= "" WRITE !, ^myglobal (key) }
如何使用 IRIS Native SDK 从 Python 执行相同的操作?这里有一个代码示例:
import iris
args = { 'hostname' : '127.0.0.1' , 'port' : 51772 , 'namespace' : 'USER' , 'username' : '_SYSTEM' , 'password' : 'SYS' }
conn = iris.connect(**args)
# Create an iris object
irispy = iris.createIRIS(conn)
# Create a global array in the USER namespace on the server
irispy.set( 'A' , 'root' , 'foo' , 'SubFoo' )
irispy.set( 123 , 'root' , 'bar' , 'lowbar' , 'UnderBar' )
irispy.set( 124 , 'root' , 'bar' , 'lowbar' , 'UnderBar2' )
irispy.set( "hi" , 'root' , 'bar' , 'lowbar' )
irispy.set( "hi again" , 'root' , 'bar3' )
# Read the values from the database and print them
subfoo_value = irispy.get( 'root' , 'foo' , 'SubFoo' )
underbar_value = irispy.get( 'root' , 'bar' , 'lowbar' , 'UnderBar' )
underbar2_value = irispy.get( 'root' , 'bar' , 'lowbar' , 'UnderBar2' )
lowbar_value = irispy.get( 'root' , 'bar' , 'lowbar' )
bar3_value = irispy.get( 'root' , 'bar3' )
print( 'Created two values: ' )
print( ' root("foo","SubFoo")=' , subfoo_value)
print( ' root("bar","lowbar","UnderBar")=' , underbar_value)
print( ' root("bar","lowbar","UnderBar2")=' , underbar2_value)
print( ' root("bar","lowbar")=' , lowbar_value)
print( ' root("bar3")=' , bar3_value)
direction = 0 # direction of iteration (boolean forward/reverse)
next_sub = chr( 0 ) # start at first possible subscript
subs = []
print( "\n Iterating root \n" )
isDef = irispy.isDefined( 'root' , *subs)
while isDef:
next_sub = irispy.nextSubscript( False , 'root' , *subs, next_sub) # get first subscript
if next_sub == None : # we finished iterating nodes on this tree branch, move a level up
if len(subs) == 0 : # no more things to iterate
break
next_sub = subs.pop( -1 ) # pop last subscript in order to continue iterating this level
if irispy.isDefined( 'root' , *subs, next_sub) == 11 :
print( 'root(' ,*subs, next_sub, ')=' ,irispy.get( 'root' , *subs, next_sub))
continue
continue
isDef = irispy.isDefined( 'root' , *subs, next_sub)
if isDef in [ 10 , 11 ]: # keep building subscripts for depth first search
subs.append(next_sub)
next_sub = chr( 0 )
continue
elif isDef == 1 : # reached a leaf node, print it
print( 'root(' ,*subs, next_sub, ')=' ,irispy.get( 'root' , *subs, next_sub))
else : # def 0 is not really expected
print( "error" )
irispy.kill( 'root' )
conn.close()
exit( -1 )
# Delete the global array and terminate
irispy.kill( 'root' ) # delete global array root
conn.close()
公告
Michael Lei · 三月 8, 2023
你好社区,
在上次激烈的编程比赛之后,我们很高兴宣布下一场 InterSystems 技术文章写作比赛!
✍️技术文章竞赛:InterSystems IRIS 教程✍️
写一篇可以被视为 InterSystems IRIS 教程的文章 任何级别的程序员:3月1日至3月31日初级/中级/高级。
🎁 人人有奖:参加比赛的每位作者都可获得一份特别奖品包!
🏆 主要奖品:共有6个奖品可供选择。
奖品
1. InterSystems技术论文大赛人人有奖!任何在比赛期间写文章的会员都将获得特别奖品:
🎁 品牌有机帆布手提袋
🎁 Moleskine 内衬笔记本
2. 专家奖——文章将由 InterSystems 专家评判:
🥇 第一名:Mars Pro 蓝牙音箱 / AirPods Max
🥈 第二名:带无线充电盒的 Apple AirPods Pro /
JBL Pulse 4 灯光秀音箱
🥉 第三名:适用于 iPad 的妙控键盘保护套 / Bose Soundlink 微型蓝牙音箱
或者作为替代方案,任何获胜者都可以从比他自己的奖品级别低的奖品中选择一个奖品。
3.开发者社区奖——点赞数最多的文章。获胜者将可以选择以下奖品之一:
🎁 iPad 妙控键盘保护套
🎁 Bose Soundlink 微型蓝牙扬声器
笔记:
作者每个类别只能获得一次(作者总共将获得 2 个奖项:一个专家奖,一个社区奖)
如果出现平局,则专家对平局文章的投票数将被视为打破平局的标准。
谁可以参加?
任何开发人员社区成员,InterSystems 员工除外。 创建一个帐户!
比赛期间
📝 3月1日-3月31日:文章发表及投票时间。
在此期间发表一篇文章。 DC 成员可以通过 Likes 为已发表的文章投票——在社区奖中投票。
注意:您越早发表文章,您收集专家和社区投票的时间就越多。
有什么要求?
❗️凡是在比赛期间所写的文章,满足以下要求,将自动进入比赛:
文章必须是有关 InterSystems IRIS 主题的教程*。它可以适用于初学者、中级或高级开发人员。
文章必须是英文的。
文章必须是 100% 新的(它可以是现有文章的延续)。
该文章不能是已在其他社区发表的文章的翻译。
文章必须包含Tutorial 标签。
文章大小:最少 400 字(链接和代码不计入字数限制)。
同一作者最多允许 3 个条目。
允许发表关于同一主题但具有来自不同作者的不同示例的文章。
* 教程提供开发人员可以遵循以完成特定任务或一组任务的分步说明。
🎯 额外奖励
这次我们决定增加额外的奖金来帮助您赢得奖品!请欢迎:
奖金
标称
细节
话题奖
5个
如果您的文章与建议主题列表(如下所列)中的主题相关,您将获得 5 票专家票的奖励(相对于专家选择的第一名 = 3 票) 。
视频奖
3个
文章内容的呈现形式:除了发布文章外,还制作一个解释性视频。
讨论奖
1个
包含最有用讨论的文章,由 InterSystems 专家决定。只有 1 篇文章将获得此奖金。
翻译奖金
1个
在任何区域社区上发布您文章的翻译。 了解更多。
注意:每篇文章只能投一票。
新会员奖励
3个
如果您没有参加过之前的比赛,您的文章将获得 3 票专家票。
拟议主题
以下是建议的主题列表,这些主题将为您的文章提供额外的奖励:
✔️ 从 C# 使用 IRIS✔️ 从 Java 使用 IRIS✔️ 从 Python 使用 IRIS✔️ 使用嵌入式 Python✔️ 使用 Python API✔️ 使用嵌入式 SQL✔️ 使用 ODBC/JDBC✔️ 使用 %Query/%SQLQuery✔️ 使用索引✔️ 使用触发器✔️ 使用 JSON✔️ 使用 XML✔️ 使用休息✔️ 使用容器✔️ 使用 kubernetes
注意:允许来自不同作者的同一主题的文章。
➡️ 加入InterSystems Discord讨论规则、话题和奖金。
所以,
是时候展示你的写作技巧了!祝你好运✨
重要提示:奖品的交付因国家/地区而异,其中一些可能无法交付。可以从@Liubka.Zelenskaia 索取有限制的国家/地区列表
欢迎关注中文社区成员 @ 王喆 的作品:Develop IRIS using SSH (https://community.intersystems.com/node/537756)
文章
Michael Lei · 三月 2, 2023
在这里,您将找到一个在 IRIS 环境中使用 Python 的简单程序,以及另一个在 Python 环境中使用 ObjectScript 的简单程序。另外,我想分享一些我在学习实践时遇到的麻烦。
IRIS 环境中的 Python
比方说,您在 IRIS 环境中想要解决一个您认为使用 Python 更容易或更有效的问题。
您可以简单地更改环境:像创建任何其他方法一样创建您的方法,并在其名称和规范的末尾添加 [Language = python]:
您可以在该方法中使用任何类型的参数,并且要访问它们,您可以执行与在 COS 中完全相同的操作:
假设您有这个 %String 参数 Arg 和一个来自自定义类的参数 OtherArg。这个其他类可能具有标题和作者等属性。您希望像这样访问:
此方法提供如下输出:
而且,对于访问类方法,它几乎是一样的。假设我们在 Demo.Books.PD.Books 中有一个名为“CreateString”的方法,它将标题和作者连接成类似于“Title: <Title>; Author: <Author>”的内容。
将其添加到我们的 python 方法的末尾:
将提供以下输出:
(要访问该方法,您可以使用 OtherArg.CreateString(),但我选择将 OtherArg 中的相同值传递给 CreateString 方法,以便输出看起来相似并且代码看起来更简单)
Python 环境中的 ObjectScript
此外,在 Python 环境中,您也可能希望能用上ObjectScript 的代码或资源。
首先,您需要勾选此列表中的一些项目,以便能够以多种方式从 Python 环境访问您的 COS 文件(我不一定会在这里使用所有这些):
你有先决条件吗? 在这里查看
你可以使用 python 外部服务器吗? 在这里查看
你有你需要的驱动吗?在此处下载它们或在此处了解更多信息
如果您觉得有帮助,可以随时返回这些链接或检查我在首次使用 COS 创建 python 文件时遇到的错误。
那么让我们开始编程吧!
首先,我们必须将一些东西从 COS 调整到 Python。幸运的是,InterSystems 已经做到了,我们只需输入“import iris”即可访问所有内容!
在下一步中,我们创建到所需命名空间的连接,使用包含主机、端口和命名空间的路径 (host:port/namespace),并提供用户和密码:
请注意我们最后是如何创建一个 IRIS 对象的,因此我们可以使用此连接来访问该命名空间中我们想要的所有内容。
最后,就可以编写你想要写的内容:
您可以通过提供类名、方法名和参数来使用 irispy.classMethodValue() 访问方法,使用 .set() (用于属性)和许多其他可能性操作对象,同时按照您喜欢的方式处理 python 上的所有内容。
更多iris提供的功能和使用方法,查看Native SDK for Python简介
在这个例子中,我在第 16 行实例化了一个 Persistent 类,在接下来的几行中将它的属性 Title 和 Author 设置为指环王和 Tolkien。
在第 20 行,我从另一个类中调用了一个方法,该方法将对象保存到一个表中,如果有效则返回一个状态。最后,我在第 23 行打印状态。
混合环境
在 ObjectScript 环境中,您可能希望使用 Python 的已知库或您自己的带有函数和例程的自定义文件。
您可以将“导入”命令与 Numpy、SciPy 和任何您想要的东西一起使用(前提是您已正确安装它们: 在此处检查如何执行此操作)
而且,如果您想访问您的本地文件,有几种方法可以做到这一点,并且很容易找到相关教程,因为 Python 非常流行。
对我来说,最容易使用的是以下内容:
在这里,我从位于 C:/python 的文件 testesql.py 中导入了所有内容,并打印了 select() 函数的结果
彩蛋——我遇到的麻烦
SHELLS :使用 Shell 时,请记住 Windows PowerShell 是作为基于 UNIX 的系统工作的(因为它基于 .NET),而命令提示符将与官方文档中的 Windows 示例一起使用。对于一些更有经验的程序员来说,这听起来很基础,但如果您没有给予足够的重视,您可能会在这上面浪费很多时间,所以我发现写一些关于它的内容很重要。
用户和权限:在 Python 环境中使用 ObjectScript 进行编码的当前用户需要拥有命名空间资源的权限。请记住,如果您不选择任何用户,则当前为 UnknownUser,如果您不选择任何名称空间,则当前为 USER。因此,在最简单的访问中,您可能需要遵循:管理门户 > 系统管理 > 安全 > 用户 > 未知用户 > 角色并选择 %DB_USER 并保存。
我不知道发生了什么:要检查有关您遇到的错误的更多信息,您可能需要关注管理门户 > 系统资源管理器 > SQL 并键入“SELECT * FROM %SYS.Audit ORDER BY UTCTimeStamp Desc”以获取最近的审计。在那里你会找到错误的原因,比如 IRIS_ACCESSDENIED() 以及更多你甚至可能在 IRIS 环境之外得到的错误。
PYTHON COMPILING ERROR:您将希望避免方法名称,例如 try() 或已在 Python 中构建的函数。编译器不会理解从方法到函数的区别。
感谢您的阅读,请随时分享建议、评论、疑问或您正在开发的任何内容!