#InterSystems IRIS for Health

0 关注者 · 862 帖子

InterSystems IRIS for Health™ 是全球第一个也是唯一一个专门为医疗应用程序的快速开发而设计的数据平台,用于管理全世界最重要的数据。它包括强大的开箱即用的功能:事务处理和分析、可扩展的医疗保健数据模型、基于 FHIR 的解决方案开发、对医疗保健互操作性标准的支持等等。所有这些将使开发者能够快速实现价值并构建具有突破性的应用程序。了解更多信息

文章 Qiao Peng · 十月 26, 2023 10m read

CDS Hooks是FHIR生态下一个决策支持架构,是SMART(Substitutable Medical Applications and Reusable Technologies, 可替代的医学应用和可复用技术)下的一个项目。

FHIR标准下也有一个决策支持相关的模块 - FHIR的Clinical Reasoning模块。它和CDS Hooks是有区别的:

FHIR的Clinical Reasoning模块提供一系列资源模型和工件,用于构建决策支持相关的规则、医嘱集、临床协议和质量指标,并基于此对特定患者和人群进行评估,进而产生决策行为。它构建的是本地决策支持体系。

而CDS Hooks提供一个决策支持架构,打通外部决策支持系统和本地的决策数据源、业务流程。

CDS Hooks是开源的,基于知识共享 CC BY 4.0,因此也获得了广泛采纳。

CDS Hooks的架构

CDS Hooks是打通外部决策支持系统和客户端应用的决策支持架构,完整的架构包括:

CDS客户端:通常是用户的业务系统,如HIS或电子病历

CDS服务:这是CDS Hooks提供的核心组件,向客户端发布的决策支持服务

FHIR服务器:这是用户侧的FHIR服务器,保存的是用户侧的FHIR资源数据。CDS服务通过访问FHIR服务器获得用户侧的决策依据的完整数据

0
0 166
公告 Michael Lei · 十月 24, 2023

终止对 CentOS 的支持

自 InterSystems IRIS 2023.3 发布起,CentOS 将不再是受支持的开发平台。

CentOS 一直是一个受支持的开发平台,为开发人员提供了相当于 Red Hat Enterprise Linux (RHEL) 的免费版本,用于 IRIS 开发。您可能知道,Red Hat 对 CentOS 进行了重大更改,CentOS 已成为 RHEL 的“上游”。这意味着它具有 RHEL 中尚未包含的错误和功能,这可能会给在该平台上构建的开发人员带来问题。

我们鼓励使用 CentOS 的开发人员利用 Red Hat 的免费开发人员计划来获得 RHEL 的免费开发许可证。

CentOS 继续支持 IRIS 2023.2(及更早版本)。

0
0 108
文章 Qiao Peng · 十月 23, 2023 12m read

FHIR标准提供灵活的扩展与再约束机制 - Profile。到底Profile机制如何工作?什么样的扩展需要用到Profile?怎么建立Profile?


 

FHIR核心资源模型  - FHIR Core

FHIR发布的资源模型是按80/20原则设计的 - 最常用那80%的用例中需要的数据会被涵盖在FHIR核心资源模型中,这些数据需求可能只是所有用例需要数据的20%;通过对核心资源的扩展和再约束,可以让它们适用于不常见的20%用例和未被涵盖的80%的数据需求。

FHIR发布的资源模型是FHIR核心资源模型(FHIR Core),它们有如下特点:

1. 对象模型 - 有继承关系。所有资源都继承自DomainResource

2. 为了保证最大的适用度,资源中的绝大多数属性的最小基数都是0,意味着它们都可以为空

3. 资源的属性可以通过code(值集)、coding、CodeableConcept(术语)进行取值范围约束

4. 为了防止医疗错误,所有的属性都没有且不能有默认值

当需要对核心资源模型进行扩展和再约束时,FHIR提供了profile机制对所做的扩展和再约束进行画像(描述),这就是profile的意思。

这里把对FHIR资源模型的用户自定义扩展区分为“扩展”和“再约束”,差异是:

  • 扩展指需要要增加新的资源属性
  • 再约束指修改核心资源模型的属性的基数、值集绑定、必须支持、切片等
0
0 416
公告 Jeff Liu · 十月 18, 2023

你好社区,

观看此视频,了解如何将 FHIR、CDS Hooks 和低代码医疗保健规则编辑器组合成一个易于使用、功能强大的平台,以帮助确保以最佳方式传递信息:

FHIR 临床警报和通知:将医疗保健行动引擎纳入 2023 年全球峰会工作流程

<iframe src="//player.bilibili.com/player.html?aid=704852301&bvid=BV12Q4y1s71g&cid=1303145533&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

🗣演讲者@Frank Pandolfe,InterSystems 临床产品经理

订阅我们的Bilibili 频道InterSystems Developers以获取最新更新!

0
0 126
公告 Jeff Liu · 十月 18, 2023

嘿开发者,

欣赏Bilibili InterSystems 中国上的新视频:

如何在 2023 年全球峰会上定制 InterSystems IRIS for Health FHIR 存储库

<iframe allowfullscreen="true" border="0" frameborder="no" framespacing="0" scrolling="no" src="//player.bilibili.com/player.html?aid=704839935&bvid=BV1kQ4y1s7fd&cid=1303147878&p=1"></iframe>

InterSystems IRIS for Health 不仅提供世界一流的 FHIR 存储库,还提供灵活性和可扩展性。了解自定义 FHIR 存储库的选项,并了解如何通过几个具体用例来实现它们,例如强制标识符的唯一性和引用完整性。

🗣  演讲者: @Teunis.Stolker,InterSystems 高级销售工程师 

享受这个视频并继续关注更多视频! 👍

0
0 101
文章 Qiao Peng · 十月 17, 2023 14m read

2023年6月底,世卫组织(WHO)和HL7签署了合作协议,利用HL7 FHIR提供互操作性,来支撑WHO的SMART指南(SMART Guideline)愿景 - 使用数智化的方式推动并加速一致化的健康干预措施建议,让世界上每个人都能立即从临床、公卫和数据使用建议中充分受益。

作为WHO的《2020-2025 年全球数字卫生战略》的一部分,SMART 指南使用 FHIR 、HL7的临床质量语言 (CQL) 和ICD标准以表达 WHO 的各种健康和临床指南,实现数据互操作、决策支持与指标、术语的一致性。这些标准被进一步利用来为各国及其合作伙伴开发一个由软件库、服务和工具组成的支持生态系统,并作为数字公共产品服务全球卫生健康事业。

为什么世卫组织会采用FHIR作为卫生信息互操作的标准在全球推广其一致化的健康干预措施建议?因为FHIR不仅标准成熟适用,而且还具有一个极具生命力的生态。

一个有生命力的标准会吸引生态的构建,而完善的生态将促进标准的成熟和演进。HL7 FHIR作为新一代的卫生信息互操作标准,其生态已经初具规模并蓬勃发展。

HL7 FHIR的知识产权类型

0
0 838
文章 Qiao Peng · 十月 9, 2023 4m read

市场上有太多的技术体系和应用开发架构,C/S、三层架构、面向服务架构… 以三层架构为例,展现层可能是网页或Java/.net客户端、应用层可能是java、.net、Python,数据层可能是SQL、NoSQL、NewSQL。但大多建立的是单体架构应用 – 为特定业务目标从底层数据模型到业务逻辑再到用户界面的一体化设计,也就是孤岛型应用。

单体架构应用最大问题是没有哪一部分是以复用为主要目的设计和建设的,而且和其开发技术体系绑定:

  • 应用只能运行在其开发的技术体系下,无法跨技术体系复用
  • 由于数据模型、术语、行业服务和API标准的缺失及应用范围不足,即便采用相同技术体系的应用和功能也没法为别的用户使用。以患者管理为例,每个业务系统都有患者管理,但没有一个系统将患者管理功能分享给别的业务系统使用,我们不得不在不同的业务系统间集成和同步患者信息
  • 而应用一旦不满足需求了,新应用要重新建设所有三层,任何一层都没法复用、原来的数据也随之下线,造成宝贵的数据资产损失

我们的医疗信息化建设的现状就是在不断重复建设不能复用和分享的单体架构应用 - 架构很重、开发周期长、开发成本很高、后期集成难度大、数据被孤岛化、应用效果不佳。

0
0 283
文章 Qiao Peng · 十月 9, 2023 7m read

英国国民医疗保健服务(NHS)简介

国民医疗保健服务(NHS)是英国的公共资助的医疗保健系统的总称,覆盖英格兰的、苏格兰和威尔士。它是世界上第二大单一付款人医疗保健系统,针对英国常住居民提供免费的、全面的卫生服务。这些卫生服务不仅是医疗服务,还包含社区护理服务、精神健康、临终关怀等。

NHS是最大的分级诊疗体系:先看全科医生或急诊,再由他们转诊到医院看专科医生、住院或者手术。它管理着9千万患者记录和65百万份病历;每天有100万的就诊、200万电子处方和75万电子转诊。

NHS200万员工,是世界最大的、非军队的单一机构。一直被评为让英国人最自豪的英国机构,击败了皇室、武装部队和英国广播公司。

NHS面临的挑战和应对

作为政府买单的全国性医疗保健系统,提高治疗效果、提升效率、降低费用是NHS始终面临的挑战。

NHS广泛使用InterSystems的TrakCare作为电子病历系统以获得统一的、最新的患者视图;使用HealthShare作为医疗机构间健康信息共享和交换平台,合并和共享患者信息、治疗计划和临终愿望计划,让授权的医护人员查看患者完整、及时的护理记录小结;使用InterSystems IRIS医疗行业版支撑包括基于机器学习的辅助决策的创新应用,例如对阿尔茨海默氏症的早期发现与诊断。NHS还提供全国的电子处方服务 - 直接将电子处方发送到患者选择的药房,和电子转诊服务。

0
0 719
文章 王喆 👀 · 九月 21, 2023 12m read

前言

  生产环境下我们部署和使用IRiS引擎,往往采用其主备镜像模式,虽然此架构简单但是往往我们需要持续在电脑前点击或者操作1到2小时,如果中间有个环节出现了问题有时我们可能需要部署一天.

  接下来我分享的是IRIS自带的一个功能帮助我们部署---manifest-安装清单。他的主要使用方式是提前通过配置约定好我们期望的安装设置,在安装的过程中由IRIS程序直接执行脚本,简化IRIS集群的部署,减少运维人员的操作步骤,让我们有更多的精力放在实际项目和业务上。

1 简介

  %Installer 实用程序允许您定义描述和配置特定 InterSystems IRIS 配置的安装清单,而不是分步安装过程。为此,我们需要创建一个类,其中包含描述所需配置的 XData 块,使用包含通常在安装期间提供的信息(超级服务器端口、操作系统等)的变量。我们还可以在类中包含一个使用 XData 块生成代码以配置实例的方法。本文提供了安装清单的示例,您可以复制和粘贴这个示例尝试使用。

定义清单后,可以在安装期间、从终端会话或代码调用它。注意:清单必须在 %SYS 命名空间中运行。

2 Manifest的最终成品

此成品展示的是一个一键安装主、备、仲裁的机器命令,此方法的使用可以便捷快速的安装主备环境,其基本每一行都有注释其说明:

5
0 390
文章 Qiao Peng · 十月 7, 2023 19m read

卫生信息和其它信息化一样,经历了数码化、数字化到当今的数字化转型,卫生信息互操作一直伴随左右。

数码化(digitization):国内90年代开始,HIS全面铺开,卫生信息进入数码化时代。数码化初期业务集中在HIS上,互操作需求不高,点对点接口可以满足绝大多数需求。

数字化(digitalization):在2000年之后,各种专科系统、尤其是电子病历的诞生,医保和新农合的实施,要求卫生信息共享交换,以提高流程自动化水平。互操作需求爆发,2007年集成平台开始进入市场,卫生信息化进入数字化时代。

数字化转型(digital transformation):2014年,国内正式进入移动互联网时代;次年《全国医疗卫生服务体系规划纲要(2015—2020年)》发布,卫生信息化的服务对象(服务于医护技到服务于患者)和业务形态(临床管理到患者服务)都发生了翻天覆地的变化,开始步入数字化转型的时代。它对互操作提出了更高的要求 - 利用互操作,增强全员参与,为卫生服务创造新价值、发展新业务,推动医疗机构持续数字化转型。

可以说,卫生信息互操作在整个的卫生信息产业中愈发重要。

国际卫生信息互操作发展了30年,国内也发展了20年,但卫生信息互操作依然是一个挑战。

知史而明鉴,识古而知今。我们看看国际卫生信息互操作发展的历程,对未来的卫生信息互操作有什么借鉴。

卫生信息互操作标准的要素

0
0 553
文章 姚 鑫 · 九月 20, 2023 2m read

[toc]

第三十三章 Objects - OREFs

OREFs

对象类的 %New() 方法创建一个内部内存结构来包含对象的数据,并返回指向该结构的 OREF(对象引用)。 OREFIRIS 中的一种特殊值。应该记住以下几点:

  • 在终端中,OREF 的内容取决于所使用的语言:
    • ObjectScript 中,会看到一个由数字、@ 符号和类名称组成的字符串。
    • Python 中,会看到一个包含类名和内存中 18 个字符的唯一位置的字符串。

例如:

TESTNAMESPACE>set myobj=##class(Sample.Person).%New()
 
TESTNAMESPACE>w myobj
3@Sample.Person 
>>> myobj=iris.cls("Sample.Person")._New()
>>> print(myobj)
<iris.Sample.Person object at 0x000001A1E52FFD20>
  • 如果没有使用预期的 OREF 或者使用了错误类型的 OREFIRIS 将返回错误。此错误与 ObjectScript 终端和 Python 终端不同:
TESTNAMESPACE>set x=2

TESTNAMESPACE>set x.Name="Fred Parker"

SET x.Name="Fred Parker"
^
<INVALID OREF>
>>> x=2
>>> x.Name="Fred Parker"
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'int' object has no attribute 'Name'

认识到这种错误是有帮助的。这意味着变量不是OREF,但应该是OREF

  • 创建 OREF 只有一种方法:使用返回 OREF 的方法。返回 OREF 的方法在对象类或其子类中定义。

下面的代码不会创建OREF,而是创建一个看起来像OREF的字符串:

TESTNAMESPACE>set testthis="4@Sample.Person"
>>> testthis="<iris.Sample.Person object at 0x000001A1E52FFD20>"
  • ObjectScript中,可以通过编程确定变量是否包含OREF。如果变量包含OREF,函数$IsObject返回1 (true);否则返回0 (false)。

注意:对于持久化类,像%OpenId()这样的方法也会返回oref。

0
0 150
文章 姚 鑫 · 九月 18, 2023 2m read

第三十一章 Classes - 继承规则

继承规则

与其他基于类的语言一样,可以通过继承组合多个类定义。 类定义可以扩展(或继承)多个其他类。这些类又可以扩展其他类。

请注意,类不能继承 Python 中定义的类(即 .py 文件中包含的类定义),反之亦然。

以下小节提供了中类继承的基本规则。

继承顺序

使用以下继承顺序规则:

  1. 默认情况下,如果在多个超类中定义了给定名称的类成员,则子类将从超类列表中最左边的类中获取定义。
  2. 如果类定义包含 Inheritance = right,则子类从超类列表中最右侧的类中获取定义。

由于历史原因,大多数类都包含 Inheritance = right

主要的超类

任何扩展其他类的类都有一个主要超类。

无论类使用哪种继承顺序,主超类都是第一个,从左到右阅读。

对于任何类级编译器关键字,给定类使用其主超类中指定的值。

对于持久化类来说,主超类尤其重要。

最具体的类型类Most-Specific Type Class

尽管一个对象可以是属于多个类extent的实例(例如各种超类的extent),但它始终具有最特定的类型类 (MSTC)。当该对象是该类的实例但不是该类的任何子类的实例时,类是该对象的最具体类型。

重写方法

类从其一个或多个超类继承方法(类方法和实例方法),可以覆盖这些方法。如果这样做,必须确保方法定义中的签名与要重写的方法的签名匹配。子类方法的每个参数必须使用与超类方法的参数相同的数据类型,或者该数据类型的子类。但是,子类中的方法可以指定超类中未定义的其他参数。

可以使用 Python 方法覆盖以 ObjectScript 编写的方法,反之亦然,只要方法签名匹配即可。

在子类的方法中,可以引用它在超类中重写的方法。要在 ObjectScript 中执行此操作,请使用 ##super() 语法。例如:

//overrides method inherited from a superclass
Method MyMethod() [ Language = objectscript ]
{
  //execute MyMethod as implemented in the superclass
  do ##super()
  //do more things....
}

注意:##super 不区分大小写。

0
0 86
文章 姚 鑫 · 九月 17, 2023 2m read

第三十章 Classes - 方法生成器

方法生成器

方法生成器是类编译器在类编译期间调用的程序。它的输出是该方法的实际运行时实现。方法生成器提供了一种继承方法的方法,可以生成根据继承类或属性的需要定制的高性能、专用代码。在 IRIS 库中,方法生成器广泛用于数据类型和存储类。

Class Queries

类可以包含类查询。类查询定义可由该类使用的 SQL 查询,并指定用作查询容器的类。下面显示了一个示例:

Query QueryName(Parameter As %String) As %SQLQuery
{
SELECT MyProperty, MyOtherProperty FROM MyClass
 WHERE (MyProperty = "Hello" AND MyOtherProperty = :Parameter)
 ORDER BY MyProperty
}

定义类查询以提供预定义的查找以供在应用程序中使用。例如,可以按某些属性(例如按名称)查找实例,或提供满足一组特定条件的实例列表,例如从巴黎到马德里的所有航班。此处显示的示例使用参数,这是提供灵活查询的常用方法。请注意,可以在任何类中定义类查询;不需要在持久类中包含类查询。

扩展数据块 XData Blocks

由于 XML 通常是表示结构化数据的有用方法,因此 类包含一种机制,允许包含格式良好的 XML 文档,以满足可能有的任何需要。为此,需要包含一个 XData 块,它是另一种类成员。

XData 块用于某些特定目的,这些可能会给关于自己的应用程序的想法:

  • IRIS Web 服务和 Web 客户端的 WS-Policy 支持。在这种情况下,XData 块描述了安全策略。
  • 在商业智能中,可以使用 XData 块来定义多维数据集、主题区域、KPI 和其他元素。

类定义中的宏和包含文件

在类定义中,可以在 ObjectScript 方法中定义宏并在该方法中使用它们。然而,更常见的是,在包含文件中定义它们,可以将其包含在任何类定义的开头。例如:

Include (%assert, %callout, %occInclude, %occSAX)

/// Implements an interface to the XSLT Parser. XML contained in a file or binary
/// stream may be transformed
Class %XML.XSLT.Transformer Extends %RegisteredObject ...

然后,该类中的任何 ObjectScript 方法都可以引用该包含文件或其包含的包含文件中定义的任何宏。

宏是继承的。也就是说,子类可以访问与其超类相同的所有宏。

0
0 113
文章 姚 鑫 · 九月 14, 2023 2m read

第二十八章 Classes - 引用其他类的方法

引用其他类的方法

在方法(或例程)中,使用下面的语法来引用其他类中的方法:

要调用类方法并访问其返回值,请使用如下表达式:

 ##class(Package.Class).MethodName(arguments)
iris.cls("Package.Class").MethodName(arguments)

例如:

 Set x=##class(Util.Utils).GetToday()
x=iris.cls("Util.Utils").GetToday()

也可以调用一个类方法而不访问它的返回值,如下所示:

 Do ##class(Util.Utils).DumpValues()
iris.cls("Util.Utils").DumpValues()

注意:##class不区分大小写。

  • 要调用实例方法,创建一个实例,然后在ObjectScriptPython中使用如下表达式来调用该方法并访问其返回值:
instance.MethodName(arguments)

例如:

 Set x=instance.GetName()
x=instance.GetName()

你也可以在不访问返回值的情况下调用实例方法,方法如下:

 Do instance.InsertItem("abc")
instance.InsertItem("abc")

并非所有方法都有返回值,因此请选择适合情况的语法。

对当前实例的引用

在实例方法中,有时需要引用当前实例本身,而不是实例的属性或方法。例如,在调用其他代码时,可能需要将当前实例作为参数传递。

ObjectScript中,使用特殊变量$THIS来引用当前实例。在Python中,使用变量self来引用当前实例。

 Set sc=header.ProcessService($this)
sc=header.ProcessService(self)
0
0 139
文章 Weiwei Gu · 九月 14, 2023 2m read

InterSystems 还发布了容器化部署的IRIS。这篇文章旨在演示 InterSystems IRIS 和依赖 IRIS 后端的应用程序如何打包到镜像中并在容器中的其他计算机中运行,以及这样做有多么简单。

容器运行包含所有必需的可执行文件、二进制代码、库和配置文件的镜像。镜像可以从一台机器移动到另一台机器,像 Docker Hub 这样的镜像存储库可以简化这个过程。

我在本演示中使用了 Open Exchange 的应用程序。

演示视频:https://www.loom.com/share/93f9a760b5f54c0a8811b7a212387b9d

IRIS 数据平台社区版的镜像(image)可以在 InterSystems 容器注册表中找到:

https: //containers.intersystems.com/contents

为了在主机中使用 IRIS 的容器化实例,应在运行时拉取它。

为此,Dockerfile 需要具有以下命令,如下所示:

Dockerfile:

Dockerfile

0
0 208
文章 姚 鑫 · 九月 13, 2023 2m read

第二十七章 Classes - 引用其他类成员

引用其他类成员

在方法中,使用下面的语法来引用其他类成员:

  • 要引用ObjectScript中的参数,使用如下表达式:
 ..#PARAMETERNAME

只能使用ObjectScript直接访问参数。要从Python访问参数,请使用ObjectScript包装器方法返回参数,并在需要时调用此方法。例如:

Class User.Employee Extends %RegisteredObject
{

Parameter ADDRESS = "123 Main St.";

ClassMethod AddressWrapper() As %String [ Language = objectscript ]
{
    return ..#ADDRESS
}

ClassMethod OfficeLocation() [ Language = python ]
{
    import iris
    location=iris.cls("User.Employee").AddressWrapper()
    print("This office is located at", location)
}

Method EmployeeLocation() [ Language = python ]
{
    location=self.AddressWrapper()
    print("This employee works at", location)
}

}

要从Python访问一个类方法,可以在所有上下文中使用iris.cls("Package.Class"). classmethodname()语法。在Python实例方法中,还可以使用更短的self.classMethodName()语法。

提供的类中,按照惯例,所有参数都以大写字母定义,但代码不需要这样做。

  • 要引用另一个实例方法,使用这样的表达式:
 ..methodname(arguments)
self.methodname(arguments)

注意,不能在类方法中使用此语法来引用实例方法。

  • 要引用另一个类方法,请使用以下语法:
 ..classmethodname(arguments)
# technique 1
iris.cls("Package.Class").classmethodname(arguments)

# technique 2
iris.cls(__name__).classmethodname(arguments)

请注意,不能使用Python self语法访问类方法。相反,可以使用__name__属性来获取当前类的名称,如上面的示例所示。

  • (仅在实例方法中)要引用实例的属性,使用这样的表达式:
 ..PropertyName
self.PropertyName

类似地,要引用对象值属性的属性,使用如下表达式:

 ..PropertyNameA.PropertyNameB
self.PropertyNameA.PropertyNameB

ObjectScript示例中使用的语法称为点语法。

此外,还可以调用对象值属性的实例方法或类方法。例如:

 Do ..PropertyName.MyMethod()
self.PropertyName.MyMethod()
0
0 73
文章 Weiwei Gu · 九月 13, 2023 1m read

我们最近发布了 IRIS 2023.2版本。 此版本从此类“HS.HC.Util.Installer”中删除了“InstallFoundation”。 这是一个没有记录在官方文档中的私有的方法,但它被社区广泛用来安装 FHIR 服务器。 所以如果你遇到这个错误:<METHOD DOES NOT EXIST> *InstallFoundation,HS.HC.Util.Installer 在构建我们自己的 FHIR 服务器的演示时,您可以通过替换此行来修复它: 把do ##class(HS.HC.Util.Installer).InstallFoundation (namespace) 替换成 Do ##class(HS.Util.Installer.Foundation).Install(namespace) `

0
0 88
文章 姚 鑫 · 九月 12, 2023 1m read

第二十六章 Classes - Methods

Methods

方法有两种:实例方法和类方法(在其他语言中称为静态方法)。

指定方法关键字

在方法定义中,可以包含影响方法行为的可选编译器关键字。以下列表显示了一些最常见的方法关键字:

Language

IRIS 中,可以用 ObjectScriptPython 编写方法。要指定编写方法所用的语言,请使用以下语法:

Method MyMethod() [ Language = objectscript ]
{
    // implementation details written in ObjectScript
}
Method MyMethod() [ Language = python ]
{
    # implementation details written in Python
}

如果方法不使用 Language 关键字,编译器将默认该方法是用 ObjectScript 编写的。

必须以全部小写字母编写方法的语言,如示例中所示。

Private

该关键字指定该方法是私有的,并且只能与 ObjectScript 方法一起使用。子类继承 Private 关键字的值并且不能覆盖它。

默认情况下,方法是公共的并且可以在任何地方访问。可以将方法标记为私有(通过 Private 关键字)。如果你这样做:

  • 只能通过它所属类的方法来访问。
  • 没有出现在类参考中。

然而,它是继承的并且在定义该方法的类的子类中可用。其他语言通常将此类方法称为受保护方法。

0
0 55
文章 姚 鑫 · 九月 11, 2023 3m read

第二十五章 Classes - 基于数据类型的属性

基于数据类型的属性

当定义属性并将其类型指定为数据类型类时,可以使用特殊选项来定义和使用该属性,如本节中所述。

数据类型类

数据类型类使能够强制执行有关属性值的规则集。

IRIS 提供的数据类型类包括 %Library.String%Library.Integer%Library.Numeric%Library.Date等等。因为 %Library 包的类名可以缩写,所以可以缩写其中的许多类;例如, %Date%Library.Date的缩写。

每个数据类型类都具有以下特征:

  • 它指定编译器关键字的值。对于属性,编译器关键字可以执行以下操作:

    • 使属性成为必需的
    • 指定属性的初始值
    • 控制如何将属性映射到 SQLODBCJava 客户端
  • 它指定影响细节的参数值,如下所示:

    • 数据类型允许的最大和最小逻辑值
    • 字符串可以包含的最大和最小字符数
    • 小数点后的位数
    • 如果字符串超过最大字符数是否截断
    • 显示格式
    • 如何转义任何特殊的 XMLHTML 字符
    • 可在任何用户界面中使用的逻辑值和显示值的枚举列表
    • 字符串必须匹配的模式(自动使用模式匹配运算符)
    • 导入或导出到 XML 时是否尊重或忽略 UTC 时区
  • 它提供了一组方法来在存储(磁盘上)、逻辑(内存中)和显示格式之间转换文字数据。

可以添加自己的数据类型类。例如,以下显示了 %Library.String的自定义子类:

Class MyApp.MyType Extends %Library.String
{

/// The maximum number of characters the string can contain.
Parameter MAXLEN As INTEGER = 2000;

}

覆盖数据类型类的参数

当定义属性并将其类型指定为数据类型类时,可以覆盖该数据类型类定义的任何参数。

例如,数据类型类中的 %Integer 定义了类参数 (MAXVAL),但没有为此参数提供任何值。可以在属性定义中覆盖它,如下所示:

Property MyInteger As %Integer(MAXVAL=10);

对于此属性,最大允许值为 10

(在内部,这是有效的,因为数据类型类的验证方法是方法生成器;当编译器为类生成代码时,将使用提供的参数值。

同样,每个 %String 类型的属性都有一个排序规则类型,它确定值的排序方式(例如大小写是否有效)。默认排序规则类型是 SQLUPPER

再例如,数据类型类定义 DISPLAYLISTVALUELIST 参数,可以使用它们来指定要在用户界面中显示的选项及其相应的内部值:

Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");

使用其他属性方法

属性有许多自动关联的方法。这些方法由数据类型类生成,可以从 ObjectScript 访问。

例如,如果定义一个具有三个属性的类 Person

Class MyApp.Person Extends %Persistent
{
Property Name As %String;
Property Age As %Integer;
Property DOB As %Date;
}

每个生成的方法的名称都是属性名称与继承类中的方法名称相连接。可以从 ObjectScript 访问这些生成的方法,如下例所示。可以通过直接从继承的类调用关联的方法来从 Python 访问相同的信息。例如,类中的 %Date 以及 DOB 属性关联的一些方法是:

 Set x = person.DOBIsValid(person.DOB)
 Write person.DOBLogicalToDisplay(person.DOB)
x = iris.cls("%Date").IsValid(person.DOB)
print(iris.cls("%Date").LogicalToDisplay(person.DOB))

其中 IsValid 是属性类的方法,LogicalToDisplay 是数据类型类中 %Date的方法。

0
0 122
文章 姚 鑫 · 九月 10, 2023 2m read

第二十四章 Classes - 指定属性关键字

指定属性关键字

在属性定义中,可以包含影响属性使用方式的可选属性关键字。以下列表显示了一些最常见的关键字:

Required

指定可以将此类实例之前设置的属性值存储到磁盘。默认情况下,属性不是必需的。在子类中,可以将可选属性标记为必需,但不能执行相反的操作。

InitialExpression

指定属性的初始值。默认情况下,属性没有初始值。子类继承InitialExpression关键字的值并且可以覆盖它。指定的值必须是有效的 ObjectScript 表达式。

Transient

指定该属性不存储在数据库中。默认情况下,属性不是瞬态的。子类继承 Transient 关键字的值并且不能覆盖它。

Private

指定该属性是私有的。子类继承 Private 关键字的值并且不能覆盖它。

默认情况下,属性是公共的并且可以在任何地方访问。可以将属性标记为私有(通过 Private 关键字)。如果是这样,则只能通过其所属对象的方法来访问它

IRIS 中,私有属性始终是继承的,并且对定义该属性的类的子类可见。

在其他编程语言中,这些通常称为受保护的属性。

Calculated

指定在实例化包含该属性的对象时,没有为其分配内存存储。默认情况下,不计算属性。子类继承了Calculated关键字并且不能重写它。

MultiDimensional

指定属性是多维的。该属性与其他属性的不同之处如下:

  • 没有关联的方法。
  • 当验证或保存对象时,会被忽略。
  • 不会保存到磁盘,除非应用程序包含专门保存它的代码。
  • 不能暴露给客户端技术。
  • 不能存储在 SQL 表中或通过 SQL 表公开。

多维属性很少见,但有时对于临时包含对象状态信息很有用。

0
0 101
文章 姚 鑫 · 九月 9, 2023 2m read

第二十三章 Classes - 属性

形式上 IRIS 有两种属性:

  • 属性,保存值。该值可以是以下任意值:

    • 单个文字值,通常基于数据类型。
    • 对象值(包括集合对象和流对象)。
    • 多维数组。这种情况不太常见。

    属性一词通常仅指作为propertiesattributes,而不是指具有关联的属性。

  • 关系,保持对象之间的关联。

可以在包含 ObjectScript 方法、Python 方法或两者组合的类中定义属性。但是,无法从 Python 方法访问关系。本节展示了一个示例类,其中包含显示以下一些变体的属性定义:

Class MyApp.Main.Patient Extends %Persistent
{

Property PatientID As %String [Required];

Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");

Property BirthDate As %Date;

Property Age As %Numeric [Transient];

Property MyTempArray [MultiDimensional];

Property PrimaryCarePhysician As Doctor;

Property Allergies As list Of PatientAllergy;

Relationship Diagnoses As PatientDiagnosis [ Cardinality = children, Inverse = Patient ]; 
}

请注意以下事项:

  • 在每个定义中,As 后面的项目是属性的类型。每种类型都是一个类。语法 As List Of 是特定集合类的简写。

%String%Date%Numeric 是数据类型类。

%String是默认类型。

  • Diagnoses是一种关系属性;其余的是属性属性。
  • PatientIDGenderBirthDateAge 只能包含简单的文字值。
  • PatientID 是必需的,因为它使用必需关键字。这意味着如果没有为此属性指定值,则无法保存此类的对象。
  • 与其他文字属性不同,Age不会保存到磁盘。这是因为它使用了 Transient 关键字。
  • MyTempArray 是一个多维属性,因为它使用 MultiDimensional 关键字。默认情况下,此属性不保存到磁盘。
  • PrimaryCarePhysicianAllergies 是对象值属性。
  • Gender 属性定义包括属性参数的值。这些是该属性使用的数据类型类中的参数。

此属性仅限于值 MF。当查看显示值(如在管理门户中)时,会看到 MaleFemale。每个数据类型类都提供 LogicalToDisplay() 等方法。

0
0 102
文章 姚 鑫 · 九月 8, 2023 2m read

第二十二章 Classes - 调用类方法的快捷方式

调用类方法的快捷方式

使用 ObjectScript 调用类方法时,在以下情况下可以省略包(或更高级别的包):

  • 引用是在一个类内,并且被引用的类在同一个包或子包中。
  • 引用位于类内,并且该类使用 IMPORT 指令导入包含引用的类的包或子包。
  • 该引用位于方法内,并且该方法使用 IMPORT 指令导入包含引用的类的包或子包。

ObjectScriptPython 调用类方法时,在以下情况下可以省略包(或更高级别的包):

  • 指的是 %Library 包中的一个类,该类是经过特殊处理的。可以将类 %Library.ClassName 引用为 %ClassName。例如,可以将 %Library.String引用为 %String
  • 指的是 User 包中的一个类,该类是经过特殊处理的。例如,可以将 User.MyClass 引用为 MyClass

User 包中不提供任何类,这些类是保留给使用的。

在所有其他情况下,必须始终使用完整的包和类名称来调用类方法。

类参数

类参数定义一个对于给定类的所有对象都相同的值。除了极少数例外,该值是在编译类时确定的,并且不能在运行时更改。将类参数用于以下目的:

  • 定义一个在运行时无法更改的值。
  • 定义有关类定义的用户特定信息。类参数只是一个任意的名称-值对;可以使用它来存储您喜欢的有关课程的任何信息。
  • 自定义各种数据类型类用作属性时的行为(例如提供验证信息);这将在下一节中讨论。
  • 为要使用的方法生成器方法提供参数化值。
  • 可以在包含 ObjectScript 方法、Python 方法或两者组合的 IRIS 类中定义参数。下面显示了一个带有多个参数的类:
Class GSOP.DivideWS Extends %SOAP.WebService
{

Parameter USECLASSNAMESPACES = 1;

///  Name of the Web service.
Parameter SERVICENAME = "Divide";

///  SOAP namespace for the Web service
Parameter NAMESPACE = "http://www.mynamespace.org";

/// let this Web service understand only SOAP 1.2
Parameter SOAPVERSION = "1.2";

 ///further details omitted
}

注意:类参数也可以是表达式,可以在编译时或运行时计算。

0
0 103
文章 姚 鑫 · 九月 5, 2023 2m read

第十九章 ObjectScript - 执行例程

执行例程

执行例程时,使用DO命令,如下所示:

 do ^routinename

要执行一个过程、函数或子程序(不访问其返回值),可以使用以下命令:

 do label^routinename

 do label^routinename(arguments)

要执行过程、函数或子例程并引用其返回值,可以使用$$label^routinename$$label^routinename(参数)形式的表达式。例如:

 set myvariable=$$label^routinename(arguments)

在所有情况下,如果标签位于同一个例程中,则可以省略插入符号和例程名称。例如:

 do label
 do label(arguments)
 set myvariable=$$label(arguments)

在所有情况下,传递的参数可以是文字值、表达式或变量名。

New 命令

IRIS提供了另一种机制,使能够控制例程中变量的作用域:NEW命令。此命令的参数是一个或多个变量名,以逗号分隔的列表表示。变量必须是公共变量,不能是Global

该命令为变量建立一个新的有限上下文(可能已经存在,也可能不存在)。例如,考虑下面的例程:

 ; demonew 
 ; routine to demo NEW
 NEW var2
 set var1="abc"
 set var2="def"
 quit

运行完这个例程后,变量var1可用,变量var2不可用,如下例所示:

TESTNAMESPACE>do ^demonew
 
TESTNAMESPACE>write var1
abc
TESTNAMESPACE>write var2
 
write var2
^
<UNDEFINED> *var2

如果该变量在使用NEW之前已经存在,那么在NEW作用域结束后,该变量仍然存在,并保留其先前的值。例如,考虑下面的Terminal会话,它使用前面定义的例程:

TESTNAMESPACE>set var2="hello world"
 
TESTNAMESPACE>do ^demonew
 
TESTNAMESPACE>write var2
hello world
0
0 160
文章 姚 鑫 · 九月 4, 2023 3m read

第十八章 ObjectScript - 使用例程

例程

可以将例程视为 ObjectScript 程序。例程可以从头开始编写,也可以在编译类时自动生成。

Procedures, Functions, and Subroutines 过程、函数和子程序

ObjectScript 例程中,标签定义以下代码单元之一的起点:

  • Procedures过程(可选地返回一个值)。过程中定义的变量是该过程私有的,这意味着它们不可用于其他代码。对于函数和子例程来说,情况并非如此。

过程也称为过程块。

  • 函数(返回值)。
  • 子例程(不返回值)。

建议使用过程Procedures,因为这可以简化控制变量范围的任务。然而,在现有代码中,可能还会看到函数和子例程,并且能够识别它们非常有用。以下列表显示了所有这些形式的代码的外观。

procedure

label(args) scopekeyword {
    zero or more lines of code 
    QUIT returnvalue
    }

或者

label(args) scopekeyword {
    zero or more lines of code 
    }

label 是过程的标识符。

args 是可选的以逗号分隔的参数列表。即使没有参数,也必须包含括号。

可选的scopekeyword是以下之一(不区分大小写):

  • Public - 如果指定 Public,则该过程是公共的,并且可以在例程本身之外调用。
  • Private(过程的默认值)。如果指定 Private,则该过程是私有的,只能由同一例程中的其他代码调用。如果尝试从另一个例程访问该过程,则会发生<NOLINE> 错误。

returnvalue 是一个可选的、要返回的单个值。要返回值,必须使用 QUIT 命令。如果不想返回值,可以省略 QUIT 命令,因为大括号表示过程结束。

过程可以将变量声明为公共变量,尽管这种做法并不被认为是现代的程序推荐。为此,可以在紧邻范围关键字之前的方括号中包含以逗号分隔的变量名称列表。

function

label(args) scopekeyword
    zero or more lines of code 
    QUIT optionalreturnvalue

args 是可选的以逗号分隔的参数列表。即使没有参数,也必须包含括号。

可选的作用域关键字是 Public(函数的默认值)或 Private

subroutine

label(args) scopekeyword
    zero or more lines of code 
    QUIT

args 是可选的以逗号分隔的参数列表。如果没有参数,则括号是可选的。

可选的作用域关键字是 Public(子例程的默认值)或 Private

下表总结了例程、子例程、函数和过程之间的差异:

 RoutineSubroutineFunctionProcedure
可以接受参数noyesyesyes
可以返回值nonoyesyes
可以在例程之外调用(默认情况下)yesyesyesno
其中定义的变量在代码执行完成后可用yesyesyes取决于变量的性质

变量可用性和范围有更多详细信息。

注:在日常用法中,通常称呼“子例程subroutine”可以表示过程procedure、函数function或子例程subroutine

0
0 113
文章 姚 鑫 · 九月 3, 2023 2m read

第十七章 ObjectScript - 使用宏和包含文件

使用宏和包含文件

如前所述,可以定义宏并稍后在同一类或例程中使用它们。更常见的是,在包含文件中定义它们。

Macros

ObjectScript 支持定义替换的宏。定义可以是一个值、整行代码或(使用 ##continue 指令)多行。

要定义宏,请使用#define 指令或其他预处理器指令。例如:

#define macroname <definition> 

要引用宏,请使用以下语法:

$$$macroname

或者:

$$$macroname(arguments)

使用宏来确保一致性。例如:

 #define StringMacro "Hello, World!"

 write $$$StringMacro

为了让了解宏可以做什么,以下示例显示了内部使用的宏的定义:

 #define CALL(%C,%A) $$$INTCALL(%C,%A,Quit sc) 

这个宏接受参数,就像许多宏一样。它还引用了另一个宏。

一些系统类广泛使用宏。

预处理器指令记录在 ObjectScript 宏和使用 ObjectScript 中的宏预处理器中。

注意:管理门户列出了包含例程的Include files 。然而,Include files 实际上并不是例程,因为它们不可执行。

Include Files

可以在类或例程中定义宏,并稍后在同一类或例程中使用它们。更常见的是,在中心位置定义它们。为此,需要创建并使用包含文件。包含文件定义宏,并且可以包含其他包含文件,并且是扩展名为 .inc 的文档。

创建包含文件后,可以执行以下操作:

  • 在任何例程的开始处包含include file。该例程可以引用包含文件中定义的宏。
  • 在任何类的开始处包含include file。该类中的方法可以引用宏。
  • 在任何方法的开始处包含include file。该方法可以引用宏。

下面显示了系统包含文件的部分内容:

/// Create a success %Status code
#define OK                     1
 
/// Return true if the %Status code is success, and false otherwise
/// %sc - %Status code
#define ISOK(%sc)              (+%sc)
 
/// Return true if the %Status code if an error, and false otherwise
/// %sc - %Status code
#define ISERR(%sc)             ('%sc)

要在例程或方法中包含INC,请使用#include 指令。 例如:

#include myincludefile

要在类定义的开头包含INC,该指令不包含井号。例如:

Include myincludefile

或者

Include (myincludefile, yourincludefile)
0
0 82
文章 姚 鑫 · 九月 2, 2023 2m read

第十六章 ObjectScript - 日期和时间值

日期和时间值

当地时间

要访问当前进程的日期和时间,可以使用 $HOROLOG 特殊变量。因此,在许多 IRIS 应用程序中,日期和时间都以此变量使用的格式存储和传输。这种格式通常称为$H 格式或$HOROLOG 格式。

$HOROLOG 从操作系统检索日期和时间,因此始终位于本地时区。

IRIS 类库包含以更常见的格式(例如 ODBC)表示日期的数据类型类,许多应用程序使用这些数据类型而不是 $H 格式。请注意,通过数据类型类中的 %Library.PosixTime支持 POSIX 时间,新应用程序应使用该类来表示日期/时间值。

UTC Time

IRIS 还提供 $ZTIMESTAMP 特殊变量,其中包含 $H 格式的协调世界时值形式的当前日期和时间。这是全球时间和日期标准;该值很可能与本地时间(和日期)值不同。

日期和时间转换

ObjectScript 包含用于转换日期和时间值的函数。

给定 $H 格式的日期,函数 $ZDATE 返回一个表示指定格式的日期的字符串。

例如:

TESTNAMESPACE>WRITE $ZDATE($HOROLOG,3)
2010-12-03

给定 $H 格式的日期和时间,函数 $ZDATETIME 返回一个表示指定格式的日期和时间的字符串。

TESTNAMESPACE>WRITE $ZDATETIME($HOROLOG,3)
2010-12-03 14:55:48
  • 给定其他格式的字符串日期和时间,函数 $ZDATEH$ZDATETIMEH 将它们转换为 $H 格式。
  • 函数 $ZTIME$ZTIMEH 将时间与 $H 格式相互转换。

$H 格式的详细信息

$H 格式是一对用逗号分隔的数字。例如:54321,12345

  • 第一个数字是自 18401231 日以来的天数。也就是说,第 1 天是 184111 日。该数字始终是整数。
  • 第二个数字是自给定日期午夜以来的秒数。

某些函数(例如 $NOW())提供小数部分。

0
0 84
文章 Jingwei Wang · 九月 1, 2023 2m read

JWT Authentication 原理及验证流程

原理

JWT 是一种结构紧凑、URL 安全的身份验证、授权或信息交换方式。在身份验证的情况下,服务器会向已通过身份验证的客户端提供一个 JWT,这样客户端在 JWT 过期之前就无需再提供密码来访问服务器上受保护的资源。

验证流程:

  1. 客户端发送Login到服务端
  2. 服务端返回 JWT给客户端
  3. 客户端校验JWT签名
  4. 客户端发送带有JWT签名的request到服务端
  5. 服务端检查JWT签名的有效期,在有效期内,则返回response给客户端,不在有效期内,返回error

JWT 配置步骤

  1. 创建REST服务
  2. 配置Web Application
  3. 安全配置
  4. 客户端发送Login,从服务器获取JWT
  5. 配置成功,发送带有JWT的request

1. 创建REST服务

在InterSystems IRIS中,可以使用/api/mgmnt自动创建REST的 .disp .impl 和 .spec 类,本篇文章不介绍具体创建REST服务的流程,具体内容请参考社区文章创建REST 服务

2. 配置Web Application

IRIS管理门户:系统管理 -> 安全 -> 应用程序 -> Web 应用程序

0
0 238
文章 Michael Lei · 八月 31, 2023 1m read

InterSystems 常见问题解答

通过在持久类(=table)定义中提供的%BuildIndices() 方法的参数中指定要重建索引的 ID 的开始值和结束值,您可以仅重建该范围内的索引。

例如,要仅针对 ID=10 到 20 重建 Sample.Person 类中的 NameIDX 索引和 ZipCode 索引,请执行以下代码(ID 范围在第 5 个和第 6 个参数中指定)。

set status = ##class (Sample.Person). %BuildIndices ( $LB ( "NameIDX" , "ZipCode" ), 1 ,, 1 , 10 , 20 )

$LB() 是$ListBuild() 函数。 %BuildIndices() 方法使用它来指定索引名称。

有关如何重建索引的更多信息,请参阅文档

2018.1版本请参考此文档

0
0 176
文章 姚 鑫 · 八月 31, 2023 2m read

第十四章 ObjectScript - 系统函数

系统函数

本节重点介绍 ObjectScript 中一些最常用的系统函数。

这些函数的名称不区分大小写。

类库还提供了大量实用方法,可以像使用函数一样使用它们。

Value Choice

在给定一些输入的情况下,可以使用以下函数来选择一个值:

  • $CASE 将给定的测试表达式与一组比较值进行比较,然后返回与匹配的比较值关联的返回值。例如:
TESTNAMESPACE>set myvar=1
 
TESTNAMESPACE>write $CASE(myvar,0:"zero",1:"one",:"other")
one
  • $SELECT 检查一组表达式并返回与第一个 true 表达式关联的返回值。例如:
TESTNAMESPACE>set myvar=1
 
TESTNAMESPACE>write $SELECT(myvar=0:"branch A",1=1:"branch B")
branch B

存在函数

可以使用以下函数来测试变量或变量节点是否存在。

  • 要测试特定变量是否存在,请使用 $DATA 函数。

对于包含多个节点的变量,该函数可以指示给定节点是否存在,以及给定节点是否有值和子节点。

  • 要获取变量的值(如果存在)或获取默认值(如果不存在),请使用 $GET 函数。

列表函数

ObjectScript 提供本机列表格式。可以使用以下函数来创建和使用这些列表:

  • $LISTBUILD 返回一种称为列表的特殊字符串。有时这称为 $LIST 格式,以将此类列表与其他类型(例如逗号分隔列表)区分开。

使用 $LIST 列表的唯一受支持的方法是使用 ObjectScript 列表函数。此类列表的内部结构没有记录,如有更改,恕不另行通知。

  • $LIST 返回列表元素或可用于替换列表元素。
  • $LISTLENGTH 返回列表中的元素数量。
  • $LISTFIND 返回给定列表中给定元素的位置。

还有其他列表功能。

如果使用的列表函数的值不是列表,会收到 <LIST>错误。

注意:系统类 %Library.List 相当于 $LISTBUILD 返回的列表。也就是说,当类中具有 %Library.List 类型的属性时,可以使用此处命名的函数来处理该属性。可以通过其短名称 %List中引用此类。

IRIS 提供了与 $LISTBUILD 返回的列表不同的其他列表类。如果更喜欢使用类,这些将非常有用。

0
0 89