清除过滤器
文章
姚 鑫 · 三月 15, 2021
# 第十章 SQL排序(二)
# 查询排序
InterSystems SQL提供了排序规则功能,可用于更改字段的排序规则或显示。
# 第十章 SQL排序(二)
# 查询排序
InterSystems SQL提供了排序规则功能,可用于更改字段的排序规则或显示。
## 查询明细排序
将排序功能应用于查询选择项会更改该项目的显示。
- 字母大小写:默认情况下,查询显示带有大写和小写字母的字符串。例外情况是对排序规则类型`SQLUPPER`的字段进行`DISTINCT`或`GROUP BY`操作。这些操作以所有大写字母显示该字段。可以使用`%EXACT`排序功能来反转此字母大小写转换,并以大写和小写字母显示该字段。不应在选择项列表中使用`%SQLUPPER`排序规则函数以所有大写字母显示字段。**这是因为`%SQLUPPER`在字符串的长度上添加了一个空格字符。请改用`UPPER`函数:**
```SQL
SELECT TOP 5 Name,$LENGTH(Name) AS NLen,
%SQLUPPER(Name) AS UpCollN,$LENGTH(%SQLUPPER(Name)) AS UpCollLen,
UPPER(Name) AS UpN,$LENGTH(UPPER(Name)) AS UpLen
FROM Sample.Person
```

- 字符串截断:可以使用`%TRUNCATE`排序函数来限制显示的字符串数据的长度。 `%TRUNCATE`比`%SQLUPPER`更可取,后者会在字符串的长度上添加一个空格字符。
```SQL
SELECT TOP 5 Name,$LENGTH(Name) AS NLen,
%TRUNCATE(Name,8) AS TruncN,$LENGTH(%TRUNCATE(Name,8)) AS TruncLen
FROM Sample.Person
```

请注意,不能嵌套排序规则函数或大小写转换函数。
- `WHERE`子句比较:大多数`WHERE`子句谓词条件比较使用字段/属性的排序规则类型。因为字符串字段默认为`SQLUPPER`,所以这些比较通常不区分大小写。可以使用`%EXACT`排序规则功能使它们区分大小写:
-
下面的示例返回`Home_City`字符串匹配项,无论字母大小写如何:
```SQL
SELECT Home_City FROM Sample.Person WHERE Home_City = 'albany'
```

以下示例返回区分大小写的`Home_City`字符串匹配:
```SQL
SELECT Home_City FROM Sample.Person WHERE %EXACT(Home_City) = 'albany'
```

`SQL Follows`运算符(`]`)使用字段/属性归类类型。
但是,无论字段/属性的排序规则类型如何,SQL `Contains`运算符(`[`)都使用EXACT排序规则:
```SQL
SELECT Home_City FROM Sample.Person WHERE Home_City [ 'c'
ORDER BY Home_City
```

`%MATCHES`和`%PATTERN`谓词条件使用EXACT排序规则,而不管字段/属性的排序规则类型如何。 `%PATTERN`谓词提供区分大小写的通配符和不区分大小写的通配符(`'A'`)。
`ORDER BY`子句:`ORDER BY`子句使用名称空间默认排序规则对字符串值进行排序。因此,`ORDER BY`不会基于字母大小写进行排序。可以使用`%EXACT`排序规则根据字母大小写对字符串进行排序。
## `DISTINCT`和`GROUP BY`排序规则
默认情况下,这些操作使用当前的名称空间排序。默认的名称空间排序规则是`SQLUPPER`。
- `DISTINCT`:`DISTINCT`关键字使用名称空间默认排序规则来消除重复值。因此,`DISTINCT Name`返回所有大写字母的值。可以使用`EXACT`排序规则返回大小写混合的值。 `DISTINCT`消除仅字母大小写不同的重复项。**要保留大小写不同的重复项,但要消除确切的重复项,请使用`EXACT`排序规则。** 以下示例消除了精确的重复项(但不消除字母大写的变体),并以混合的大写和小写形式返回所有值:
```SQL
SELECT DISTINCT %EXACT(Name) FROM Sample.Person
```

`UNION`涉及隐式`DISTINCT`操作。
- `GROUP BY`:`GROUP BY`子句使用名称空间默认排序规则来消除重复的值。因此,`GROUP BY Name`返回所有大写字母的值。**可以使用`EXACT`排序规则返回大小写混合的值。** `GROUP BY`消除仅字母大小写不同的重复项。若要保留大小写不同的重复项,但要消除完全相同的重复项,必须在`GROUP BY`子句(而不是`select-item`)上指定`%EXACT`归类函数。
下面的示例返回大小写混合的值; `GROUP BY`消除重复项,包括字母大小写不同的重复项:
```SQL
SELECT %EXACT(Name) FROM Sample.Person GROUP BY Name
```

下面的示例返回大小写混合的值; `GROUP BY`消除了精确的重复项(但不消除字母大写的变体):
```SQL
SELECT Name FROM Sample.Person GROUP BY %EXACT(Name)
```

# 旧版排序类型
InterSystems SQL支持多种旧式排序规则类型。它们已被弃用,不建议与新代码一起使用,因为它们的目的是为遗留系统提供持续的支持。他们是:
- **`%ALPHAUP` — 除去问号(`“?”`)和逗号(`“,”`)之外的所有标点符号,并将所有小写字母转换为大写字母。主要用于映射旧全局变量。由`SQLUPPER`代替。**
- **`%STRING` —将逻辑值转换为大写,去除所有标点符号和空格(逗号除外),并在字符串的开头添加一个前导空格。它将所有仅包含空格(空格,制表符等)的值作为SQL空字符串进行整理。由`SQLUPPER`代替。**
- **`%UPPER` —将所有小写字母转换为大写字母。主要用于映射旧全局变量。由`SQLUPPER`代替。**
- `SPACE` — `SPACE`排序将单个前导空格附加到一个值,强制将其作为字符串求值。要建立`SPACE`排序规则,`CREATE TABL`E提供一个`SPACE`排序规则关键字,而ObjectScript在`%SYSTEM.Util`类的`Collation()`方法中提供一个`SPACE`选项。没有相应的SQL排序规则功能。
**注意:如果使用`EXACT`,`UPPER`或`ALPHAUP`排序定义了字符串数据类型字段,并且查询在此字段上应用了`%STARTSWITH`条件,则可能导致不一致的行为。如果指定给`%STARTSWITH`的子字符串是规范数字(尤其是负数和/或小数),则`%STARTSWITH`可能会根据字段是否被索引而给出不同的结果。如果未对列进行索引,则`%STARTSWITH`应该会按预期执行。如果该列已建立索引,则可能会发生意外的结果。**
# SQL和NLS排序
上面描述的SQL排序规则不应与InterSystems IRIS NLS排序规则功能混淆,后者提供符合特定本国语言排序规则要求的下标级别编码。这是提供分页的两个独立系统,它们在产品的不同级别上工作。
InterSystems IRIS NLS排序可以具有当前过程的过程级别排序,并且可以具有特定全局变量的不同排序。
为了确保使用InterSystems SQL时的正常运行,要求进程级NLS排序规则与所涉及的所有全局变量的NLS排序规则完全匹配,包括表所使用的全局变量以及用于临时文件(例如进程专用全局变量和IRIS TEMP)的全局变量。否则,查询处理器设计的不同处理计划可能会得出不同的结果。在发生排序的情况下,例如`ORDER BY`子句或范围条件,查询处理器将选择最有效的排序策略。它可以使用索引,可以在进程专用的全局文件中使用临时文件,可以在本地数组中排序,也可以使用`“]]”`(之后排序)比较。所有这些都是下标类型的比较,遵循有效的InterSystems IRIS NLS归类,这就是为什么所有这些类型的全局变量都必须使用完全相同的NLS归类的原因。
系统使用数据库默认排序规则创建全局变量。可以使用`%Library.GlobalEdit`类的`Create()`方法来创建具有不同排序规则的全局变量。唯一的要求是指定的归类可以是内置的(例如InterSystems IRIS标准),也可以是当前语言环境中可用的国家归类之一。
公告
Jeff Liu · 三月 30, 2022
大家好,欢迎来到2022年3月开发者社区更新!
我们最近在InterSystems社区对开发者们的体验做了一些改进:
全新的社区内容搜索功能
综合社区数据
链接你的脸书账号
帖子页面更新:标签、作者块、草稿突出显示
下面让我们仔细看看。
社区搜
我们已经在社区网站上部署了一个全新的搜索引擎。有两个搜索选项:
快速搜索
高级搜索
通过DC快速搜索,你可以很容易地找到一个帖子/标签/用户并直接进入该网页。
在建议的选项中没有找到合适的东西?
试着通过点击🔍按钮使用DC高级搜索:
在这里,你可以轻松地为你的搜索查询添加高级参数:
按特定用户的帖子搜索
通过特定标签搜索
按特定的帖子类型或只按你的帖子搜索
你还可以按时间段和相关性对结果进行排序:
综合社区数据
现在你可以看到InterSystems开发社区的数据统计了:
链接你的脸书账号
在你的DC资料中添加Facebook链接,以认识新朋友,拉近彼此的距离。
进入你的DC用户资料-->编辑-->其他信息-->Facebook资料
帖子页面更新:标签、作者块、草稿突出显示
你问了 - 我们做到了! 现在DC标签出现在帖子的正文中。
另外,在帖子页面,你现在可以在右边的块中看到作者的联系信息:
DC网站上的草稿现在是蓝色突出显示:
希望你喜欢我们的更新
在DC GitHub上提交您的改进请求和错误报告。或者在本帖的评论中发表您的建议。
请继续关注!
公告
Claire Zheng · 一月 10, 2023
亲爱的社区开发者们,
我很高兴地向大家介绍一位我们的新版主 @牛宇翔!
@牛宇翔 目前担任首都医科大学附属北京友谊医院信息中心临床组组长。
以下是@牛宇翔 的自我介绍:
本人有接近10年的医疗信息化经验,目前在我院,带领一个微型小团队,基于Ensemble数据库做医院信息系统(Hospital Information System, HIS)应用端研发,我们团队熟悉HTML、CSS、JavaScript及衍生前端语言,日常工作主要根据用户需求开发对应功能,结合临床业务难点痛点,不断优化程序功能。经过两年的学习和努力,我们团队已完成临床新增功能和优化需求共计一千余条,随着科室人力的发展,我们的开发力量会越来越强,可以更好地保证临床需求的及时响应,不断优化和完善系统BUG,提高临床工作效率。与此同时,我还担任应急小组成员,负责进行数据库运维和问题处理,保证第一时间排查故障。
InterSystems 提供了一个非常优秀的集成平台,借助该技术,给我们业务带来了非常大的便利。我也希望这么优秀的技术,能给更多的兄弟单位和合作伙伴创造价值。我也希望能够在社区与大家一起交流,分享自己的一些实践经验;同时也希望借助这个平台,向大家学习一些优秀的实践。我们一起成长,共同进步!
再次欢迎我们的新版主 @牛宇翔👏🏼👏🏼👏🏼👏🏼👏🏼
期待你在InterSystems开发者社区成长为一名优秀版主! 热烈欢迎!期待更多大作!@牛宇翔
文章
姚 鑫 · 五月 3, 2021
# 第二章 全局变量结构(一)
本章描述全局变量的逻辑视图,并概述全局变量是如何在磁盘上物理存储的。
# 全局变量的逻辑结构
全局变量是存储在物理InterSystems IRIS®数据库中的命名多维数组。
在应用程序中,全局变量到物理数据库的映射基于当前名称空间——名称空间提供一个或多个物理数据库的逻辑统一视图。
## 全局命名约定和限制
全局名称指定其目标和用途。有两种类型的全局变量和一组单独的变量,称为“进程私有全局变量”:
- 全局变量 - 这就是所谓的标准全局变量;通常,这些变量被简称为全局变量。它是驻留在当前命名空间中的永久性多维数组。
- **扩展全局引用-这是位于当前命名空间以外的命名空间中的全局引用。**
- **进程私有全局变量-这是一个数组变量,只有创建它的进程才能访问。**
全局变量的命名约定如下:
- 全局变量名称以脱字符(`^`)前缀开头。这个插入符号区分全局变量和局部变量。
- 全局变量名称中脱字符(`^`)前缀后的第一个字符可以是:
- 字母或百分号字符(%)-仅适用于标准全局变量。对于全局变量名称,字母被定义为`ASCII 65`到`ASCII 255`范围内的字母字符。如果全局名称以`“%”`开头(但不是`“%Z”`或`“%z”`),则此全局名称供InterSystems IRIS系统使用。`%GLOBAL`通常存储在IRISSYS或IRISLIB数据库中。
- 竖线(`|`)或左方括号(`[`)-表示扩展全局引用或进程专用全局变量。使用取决于后续字符。
- 全局变量名称的其他字符可以是字母、数字或句号(`.`)字符。
百分比(`%`)字符不能使用,除非作为全局名称的第一个字符。
`“.”`字符不能作为全局名称的最后一个字符。
- **全局名称最长可达31个字符(不包括脱字符前缀)。可以指定更长的全局名称,但InterSystems IRIS只将前31个字符视为重要字符。**
- 全局名称区分大小写。
- InterSystems IRIS对全局引用的总长度施加限制,而该限制又对任何下标值的长度施加限制。
**在IRISSYS数据库中,InterSystems将除以`“z”`、`“Z”`、`“%z”`和`“%Z”`开头的所有全局变量名称保留给自己。在所有其他数据库中,InterSystems保留所有以`“ISC”`开头的全局名称。和`“%isc.”`。**
## 示例全局名称及其用法
以下是各种全局名称的示例以及每种名称的用法:
- `^globalname` - 标准全局变量
- `^|"environment"|globalname` - 扩展全局变量引用的环境语法
- `^||globalname` - 进程私有全局变量
- `^|"^"|` - 进程私有全局变量
- `^[namespace]globalname` - 扩展全局变量引用中显式命名空间的括号语法
- `^[directory,system]globalname` - 扩展全局变量引用中隐含命名空间的括号语法
- `^["^"]globalname` - 进程私有全局变量
- `^["^",""]globalname` - 进程私有全局变量
注意:全局名称只能包含有效的标识符字符;默认情况下,这些字符如上所述。但是,NLS(国家语言支持)定义了一组不同的有效标识符字符集。全局名称不能包含`Unicode`字符。
因此,以下都是有效的全局名称:
```java
SET ^a="The quick "
SET ^A="brown fox "
SET ^A7="jumped over "
SET ^A.7="the lazy "
SET ^A1B2C3="dog's back."
WRITE ^a,^A,^A7,!,^A.7,^A1B2C3
KILL ^a,^A,^A7,^A.7,^A1B2C3 // keeps the database clean
```
## 全局节点和下标简介
全局通常有多个节点,通常由一个下标或一组下标标识。下面是一个基本示例:
```java
set ^Demo(1)="Cleopatra"
```
此语句引用全局节点`^Demo(1)`,它是`^Demo`全局节点中的一个节点。此节点由一个下标标识。
再举一个例子:
```java
set ^Demo("subscript1","subscript2","subscript3")=12
```
该语句指的是全局节点`^Demo("subscript1","subscript2","subscript3")`,它是同一全局中的另一个节点。此节点由三个下标标识。
再举一个例子:
```java
set ^Demo="hello world"
```
该语句引用不使用任何下标的全局节点`^Demo`。
全局的节点形成分层结构。ObjectScript提供了利用此结构的命令。例如,可以删除节点或删除节点及其所有子节点。
## 全局变量下标
下标有以下规则:
- 下标数值区分大小写。
- **下标值可以是任何ObjectScript表达式,前提是该表达式的计算结果不是空字符串(`""`)。**
**该值可以包括所有类型的字符,包括空格、非打印字符和Unicode字符。(请注意,非打印字符在下标数值中不太实用。)**
- 在解析全局引用之前,InterSystems IRIS计算每个下标的方式与计算任何其他表达式的方式相同。在下面的示例中,我们设置了`^Demo`全局的一个节点,然后以几种等效的方式引用该节点:
```java
DHC-APP>s ^Demo(1+2+3)="a value"
DHC-APP>w ^Demo(3+3)
a value
DHC-APP>w ^Demo(03+03)
a value
DHC-APP>w ^Demo(03.0+03.0)
a value
DHC-APP>set x=6
DHC-APP>w ^Demo(x)
a value
```
- InterSystems IRIS对全局引用的总长度施加限制,而该限制又对任何下标值的长度施加限制。
**注意:上述规则适用于IRIS支持的所有排序规则。对于出于兼容性原因仍在使用的旧归类,如`“pre-ISM-6.1”`,下标的规则有更多限制。例如,字符下标不能以控制字符作为其初始字符;整数下标中可以使用的位数也有限制。**
## 全局变量节点
在应用程序中,节点通常包含以下类型的结构:
1. 字符串或数字数据,包括本机`Unicode`字符。
2. 具有由特殊字符分隔的多个字段的字符串:
```java
SET ^Data(10) = "Smith^John^Boston"
```
可以使用ObjectScript `$PIECE` 函数来拆分这些数据。
3. InterSystems IRIS `$LIST` 结构中包含多个字段。`$LIST`结构是包含多个长度编码值的字符串。它不需要特殊的分隔符。
4. 空字符串 (`""`)。在下标本身用作数据的情况下,实际节点中不存储任何数据。
5. 一个位串。如果全局变量用于存储位图索引的一部分,那么存储在节点中的值就是位字符串。位串是包含`1`和`0`值的逻辑压缩集的字符串。可以使用`$BIT`函数构造位串。
6. 更大的数据集的一部分。例如,对象和SQL引擎将流(`BLOB`)存储为全局中连续的`32K`节点系列。通过流接口,流的用户不知道流是以这种方式存储的。
请注意,任何全局节点都不能包含长度超过字符串长度限制的字符串,字符串长度限制非常长。
## 全局变量排序规则
在全局中,节点按排序(排序)顺序存储。
**应用程序通常通过将转换应用于用作下标的值来控制节点的排序顺序。例如,SQL引擎在为字符串值创建索引时,会将所有字符串值转换为大写字母,并在前面加上一个空格字符,以确保索引不区分大小写并且以文本形式排序(即使数值存储为字符串)。**
# 全局变量引用的最大长度
**全局变量引用(即对特定全局节点或子树的引用)的总长度限制为`511`个编码字符(少于`511`个键入字符)。**
要保守地确定给定全局变量引用的大小,请使用以下准则:
1. 全局变量名称:每个字符加`1`。
2. 对于纯数字下标:每个数字、符号或小数点加`1`。
3. 对于包含非数字字符的下标:为每个字符添加`3`。
如果下标不是纯数字的,则根据用于编码字符串的字符集的不同,下标的实际长度会有所不同。一个多字节字符最多可以占用`3`个字节。
请注意,ASCII字符可能占用`1`或`2`字节。
如果排序规则进行大小写折叠,那么`ASCII`字符可以使用`1`个字节表示字符,`1`个字节表示消除歧义字节。
如果排序不执行大小写折叠,`ASCII`字符占用`1`字节。
4. 每个下标加`1`。
如果这些数字的总和大于`511`,则引用太长。
由于确定限制的方式,如果必须使用长下标或全局名称,这有助于避免使用大量下标级别。
相反,如果使用多个下标级别,则应避免长全局名称和长下标。
因为无法控制正在使用的字符集,所以保持全局名称和下标更短是很有用的。
当对特定引用有疑问时,创建与最长预期全局变量引用长度相等(甚至稍长一点)的全局变量引用的测试版本是有用的。
这些测试的数据为构建应用程序之前可能修订的命名约定提供了指导。
文章
姚 鑫 · 五月 23, 2021
# 第四章 收发电子邮件
本主题描述如何使用InterSystems IRIS发送和接收`MIME`电子邮件消息。
注意:本主题中的示例是经过组织的,因此管理电子邮件的方法可以用于不同的电子邮件服务器,这在测试和演示期间非常有用。这不一定是最适合生产需要的代码组织。
# 支持电子邮件协议
电子邮件使用标准协议通过Internet发送消息。
InterSystems IRIS支持以下三种协议:
- InterSystems IRIS提供`MIME`电子邮件的对象表示形式。它支持文本和非文本附件、单部分或多部分邮件正文,以及`ASCII`和非`ASCII`字符集的标题。
- 可以通过`SMTP`服务器发送电子邮件。`SMTP`(简单邮件传输协议)是发送电子邮件的Internet标准。
- 还可以通过`POP3`从电子邮件服务器检索电子邮件,`POP3`是从远程服务器检索电子邮件的最常用标准。
注意:InterSystems IRIS不提供邮件服务器。相反,它提供了连接到邮件服务器并与之交互的功能。
# InterSystems IRIS如何表示`MIME`电子邮件
首先,了解InterSystems IRIS如何表示`MIME`电子邮件非常有用。
通常,多部分`MIME`邮件由以下部分组成:
- 一组邮件标头,每个标头都包含邮件发送到的地址等信息。这还包括整个消息的`Mime-Type`标头和`Content-Type`标头。
对于多部分消息,`Content-Type`头必须是多部分/混合或多部分的其他子类型;`MIME`标准有许多变体。
- 多个消息部分,每个消息部分由以下部分组成:
- 一组内容标头,包括`Content-Type`标头和特定于此部件的其他标头。
- 一种正文,它可以是文本或二进制,并且可以使用与其它部分的正文不同的字符集。
InterSystems IRIS使用两个类来表示电子邮件:`%Net.MailMessage`和`%Net.MailMessagePart`,即`%Net.MailMessage`的超类。下图显示了这些类之间的关系:

- 要表示普通的、由一部分组成的消息,请使用`%Net.MailMessage`
- 要表示多部分消息,请使用`%Net.MailMessage`作为父消息,并使用`%Net.MailMessagePart`的多个实例作为其部分。
# 创建由单个部分组成的电子邮件
要创建由单个部分组成的电子邮件,请使用`%Net.MailMessage`类。要创建邮件,请执行以下操作:
1. 创建`%Net.MailMessage`的实例。
提示:可以将字符集指定为`%New()`;的参数,如果这样做,则会设置消息的`CharSet`属性。
2. 设置实例的`To`、`From`和`Subject`属性。
- `To`收件人-此邮件将发送到的电子邮件地址列表。此属性是标准的InterSystems IRIS列表类;要使用它,需要使用标准列表方法:`Insert()`、`GetAt()`、`RemoveAt()`、`Count()`和`Clear()`。
- `From`发件人-此邮件的发件人电子邮件地址。
- `Subject`主题-邮件的主题(如果您使用的SMTP服务器需要该主题)。
3. 可以选择设置日期、抄送、密件抄送和其他属性。
4. 如果邮件不是纯文本,请设置以下属性以指示您要创建的邮件的类型:
- 如果这是一封HTML邮件,请将`IsHTML`属性设置为1。
- 如果这是二进制消息,请将`IsBinary`属性设置为1。
5. 若要指定消息及其标头的字符集,请根据需要设置`CharSet`属性。
重要提示:在添加消息内容之前指定字符集非常重要。
6. 添加消息内容:
- 对于纯文本或`HTML`,请使用`TextData`属性,该属性是`%FileCharacterStream`的实例。不需要指定此流的`TranslateTable`属性;当指定邮件的字符集时,该属性会自动发生。
- 对于二进制数据,请使用`BinaryData`属性,该属性是`%FileBinaryStream`的实例。
提示:指定流的`Filename`属性时,请确保使用用户有权写入的目录。
要使用这些属性,请使用标准流方法:`Write()`、`WriteLine()`、`Read()`、`ReadLine()`、`Rewind()`、`MoveToEnd()`和`Clear()`。还可以使用流的`Size`属性,该属性提供消息内容的大小。
注意:应该了解正在使用的`SMTP`服务器的要求。例如,某些`SMTP`服务器要求包含主题标头。同样,某些`SMTP`服务器不允许任意`FROM`标头。
类似地,一些`SMTP`服务器识别优先级报头,而其他服务器则识别`X-Priority`。
示例1:`CreateTextMessage()`
以下方法创建一条简单消息并为其指定地址:
```java
ClassMethod CreateTextMessage() As %Net.MailMessage
{
Set msg = ##class(%Net.MailMessage).%New()
set msg.From = "test@test.com"
Do msg.To.Insert("xxx@xxx.com")
Do msg.Cc.Insert("yyy@yyy.com")
Do msg.Bcc.Insert("zzz@zzz.com")
Set msg.Subject="subject line here"
Set msg.IsBinary=0
Set msg.IsHTML=0
Do msg.TextData.Write("This is the message.")
Quit msg
}
```
示例2:`SimpleMessage()`
在实际发送邮件时指定地。上例的以下变体生成一条没有地址的文本消息:
```java
ClassMethod SimpleMessage() As %Net.MailMessage
{
Set msg = ##class(%Net.MailMessage).%New()
Set msg.Subject="Simple message "_$h
Set msg.IsBinary=0
Set msg.IsHTML=0
Do msg.TextData.Write("This is the message.")
Quit msg
}
```
`Samples`命名空间中还有其他示例。要查找它们,请在该命名空间中搜索`%Net.MailMessage`。
# 创建多部分电子邮件
要创建由多部分组成的电子邮件,请执行以下操作:
1. 创建`%Net.MailMessage`的实例,并将其`To`、`From`和`Subject`属性设置为。可以选择设置其他属性以指定其他邮件标头。
2. 将`IsMultiPart`属性设置为1。
3. 将`MultiPartType`属性设置为以下值之一: `"related"`, `"alternative"`, 或 `"mixed"`。这会影响整个消息的`Content-Type`标头。
4. 对于邮件应包含的每个部分,创建`%Net.MailMessagePart`的实例并指定其属性,如从步骤4开始的“创建由单个部分组成的电子邮件”中所述。
5. 对于父电子邮件,设置`Parts`属性,该属性是一个数组。将每个子消息部分插入到此数组中。
发送邮件时,`%Net.SMTP`类会根据需要自动设置邮件的`Content-Type`标头(给定`MultiPartType`属性值)。
# 指定电子邮件标题
如前所述,消息本身和消息的每个部分都有一组标头。
`%Net.MailMessage`和`%Net.MailMessagePart`类提供的属性使可以轻松访问最常用的标头,但可以添加所需的任何标头。本节提供有关所有标头以及如何创建自定义标头的信息。
给定消息部分的标头使用由该部分的`CharSet`属性指定的字符集。
注意:应该了解正在使用的`SMTP`服务器的要求。例如,某些`SMTP`服务器要求包含主题标头。同样,某些`SMTP`服务器不允许任意`FROM`标头。
类似地,一些`SMTP`服务器识别优先级报头,而其他服务器则识别`X-Priority`。
# 指定基本电子邮件标题
设置以下属性(仅在`%Net.MailMessage`中)以设置邮件本身最常用的标头:
- `To`-(必填)此邮件将发送到的电子邮件地址列表。此属性是标准的InterSystems IRIS列表;要使用它,请使用标准列表方法:`Insert()`、`GetAt()`、`RemoveAt()`、`Count()`和`Clear()`。
- From-(必填)发送此邮件的电子邮件地址。
- Date-此消息的日期。
- Subject-(必选)包含此邮件主题的字符串。
- Sender-邮件的实际发件人。
- Cc-此邮件将发送到的抄送地址列表。
- Bcc-此邮件将被发送到的密件副本地址列表。
## 内容类型标题
发送邮件时,邮件和每个邮件部分的`Content-Type`标头会自动设置如下:
- 如果消息是纯文本(`IsHTML`等于0,`IsBinary`等于0),则`Content-Type`标头被设置为 `"text/plain`。
- 如果消息是`HTML`(`IsHTML`等于1,`IsBinary`等于0),则`Content-Type`标头设置为`“text/html”`。
- 如果消息是二进制的(`IsBinary`等于1),则`Content-Type`报头设置为如果消息是二进制的(`IsBinary`等于1),则`Content-Type`报头设置为`"application/octet-stream"`.
- 如果邮件是多部分邮件,则会为`MultiPartType`属性的值适当设置`Content-Type`标头。
`%Net.MailMessage`和`%Net.MailMessagePart`都提供了`contentType`属性,使可以访问`Content-Type`标头。
## 内容传输编码标头
`%Net.MailMessage`和`%Net.MailMessagePart`都提供了`ContentTransferEncoding`属性,该属性提供了一种指定消息或消息部分的`Content-Transfer-Encoding`头的简单方法。
此属性可以是以下属性之一:`"base64" "quoted-printable" "7bit" "8bit"`
默认值如下:
对于二进制消息或消息部分:`"base64"`
**重要提示:请注意,如果内容为`“Base64”`编码,则不能包含任何Unicode字符。如果要发送的内容包括Unicode字符,请确保使用`$ZCONVERT`将内容转换为`UTF-8`,然后对其进行`base-64`编码。例如:**
```java
set BinaryText=$ZCONVERT(UnicodeText,"O","UTF8")
set Base64Encoded=$system.Encryption.Base64Encode(BinaryText)
```
收件人必须使用相反的过程来解码文本:
```java
set BinaryText=$system.Encryption.Base64Decode(Base64Encoded)
set UnicodeText=$ZCONVERT(BinaryText,"I","UTF8")
```
对于文本消息或消息部分:`"quoted-printable"`
## 自定义标题
使用`%Net.MailMessage`和`%Net.MailMessagePart`,可以通过访问`Headers`属性设置或获取自定义标题,该属性是一个具有以下结构的数组:
数组键 |数组值
---|---
标头的名称,如`“Priority”` | 标头的值
此属性用于包含其他标头,如`X-Priority`和其他标头。例如:
```java
do msg.Headers.SetAt(1,"X-Priority")
do msg.Headers.SetAt("High","X-MSMail-Priority")
do msg.Headers.SetAt("High","Importance")
```
不同的电子邮件服务器和客户端可以识别不同的标头,因此设置多个相似的标头以确保服务器或客户端接收到的邮件具有它可以识别的标头是很有用的。
文章
姚 鑫 · 五月 30, 2021
# 第十一章 发送和接收IBM WebSphere MQ消息
InterSystems IRIS为IBM `WebSphere MQ`提供了一个接口,可以使用该接口在InterSystems IRIS和IBM `WebSphere MQ`的消息队列之间交换消息。要使用此接口,必须能够访问IBM `WebSphere MQ`服务器,并且IBM `WebSphere MQ`客户端必须与InterSystems IRIS在同一台计算机上运行。
该接口由`%Net.MQSend`和`%Net.MQRecv`类组成,这两个类都是`%Net.abstractMQ`的子类。这些类使用由InterSystems IRIS在所有合适的平台上自动安装的动态链接库。(这是Windows上的`MQInterface.dll`;其他平台的文件扩展名不同。)。反过来,InterSystems IRIS动态链接库需要IBM `WebSphere MQ`动态链接库。
该界面仅支持发送和接收文本数据,不支持二进制数据。
# 使用IBM WebSphere MQ的RIS接口
通常,要使用IBM `WebSphere MQ`的InterSystems IRIS接口,请执行以下操作:
1. 确保有权访问`IBM WebSphereMQv7.x`或更高版本。具体而言:
- IBM `WebSphere MQ`客户端必须与InterSystems IRIS安装在同一台计算机上。请注意,安装程序会根据需要更新`PATH`环境变量并添加其他系统变量。
- 确保在安装客户端后重新启动计算机,以便InterSystems IRIS能够识别该客户端。
- 客户端必须能够访问IBM `WebSphere MQ`服务器。
- 将用来访问服务器的用户名必须具有使用队列管理器和计划使用的队列的权限。
2. 创建`%Net.MQSend`或`%Net.MQRecv`的新实例,具体取决于要发送还是接收消息。
3. 连接到IBM `WebSphere MQ`服务器。执行此操作时,您需要提供以下信息:
- 队列管理器的名称。
- 要使用的队列的名称。
- 与该队列通信的通道。可以指定IBM `WebSphere MQ`服务器的通道名称、传输机制以及IP地址和端口。
如果正在使用IBM `WebSphere MQ`的身份验证功能,还可以提供名称和密码。
4. 调用`%Net.MQSend`或`%Net.MQRecv`的相应方法来发送或接收消息。
注意:要在64位Linux平台上使用IBM `Websphere MQ`,必须设置`LD_LIBRARY_PATH`以包括`MQ`库的位置。因为必须为任何使用`MQ`接口的InterSystems IRIS进程设置路径,所以如果正在运行后台进程,则必须在启动InterSystems IRIS之前设置该路径,并在运行IRIS终端之前在任何UNIX®终端中设置该路径。
## 获取错误代码
`%Net.MQSend`和`%Net.MQRecv`的方法如果成功则返回1,如果不成功则返回0。在出现错误的情况下,调用`%GetLastError()`方法,该方法返回IBM `WebSphere MQ`给出的最后一个原因代码。
# 创建连接对象
在可以通过IBM `WebSphere MQ`发送或接收消息之前,必须创建一个`Connection`对象,该对象可以建立到队列管理器的连接、打开通道和打开队列以供使用。有两种方法可以做到这一点:
- 可以使用`%Init`方法,该方法接受指定所有所需信息的参数。
- 可以在首次设置指定所有所需信息的属性后使用`%Connect`方法。
## 使用%Init()方法
要使用`%Init()`方法创建连接对象,请执行以下操作:
1. 创建`%Net.MQSend`(如果要发送消息)或`%Net.MQRecv`(如果要接收消息)的实例。本主题将此实例称为连接对象。
注意:如果收到 ``错误,则表示缺少动态链接库,并且`messages.log`文件(在系统管理器的目录中)有更多详细信息。
2. 如果需要身份验证,请设置`Connection`对象的以下属性:
- 用户名-指定有权使用此频道的用户名。
- 密码-指定给定用户的密码。
3. 调用`Connection`对象的`%Init()`方法。此方法按顺序接受以下参数。
a. 指定队列名称的字符串;这应该是指定队列管理器的有效队列。
b. 指定队列管理器的字符串;它应该是IBM `WebSphere MQ`服务器上的有效队列管理器。
如果省略此参数,系统将使用IBM `WebSphere MQ`中配置的默认队列管理器。或者,如果IBM `WebSphere MQ`已配置为队列管理器由队列名称确定,则系统将使用适合给定队列名称的队列管理器。
c. 指定频道规范的字符串,格式如下:
```java
"channel_name/transport/host_name(port)"
```
这里,`channel_name`是要使用的通道的名称,`Transport`是通道使用的传输,`host_name`是运行IBM `WebSphere MQ`服务器的服务器名称(或IP地址),`port`是该通道应该使用的端口。
传输可以是以下之一:`TCP`、`LU62`、`NETBIOS`、`SPX`
例如:
```java
"CHAN_1/TCP/rodan(1401)"
```
```java
"CHAN_1/TCP/127.0.0.1(1401)"
```
如果省略此参数,系统将使用IBM `WebSphere MQ`中配置的默认通道规范。或者,如果系统已配置为通道由队列名称确定,则系统使用适合给定队列名称的通道。
d. 一个可选字符串,它指定要向其中写入错误消息的日志文件。默认情况下,不进行日志记录。
4. 检查`%Init()`方法返回的值。如果该方法返回1,则表明连接已成功建立,可以使用`Connection`对象发送或接收消息(具体取决于使用的类)。
## 使用%Connect()方法
在某些情况下,可能更喜欢单独指定连接的所有详细信息。为此,请使用`%Connect()`方法,如下所示:
1. 创建`%Net.MQSend`(如果要发送消息)或`%Net.MQRecv`(如果要接收消息)的实例。如前所述,本主题将此实例称为连接对象。
注意:如果收到`` 错误,则表示缺少动态链接库,并且`messages.log`文件(在系统管理器的目录中)有更多详细信息。
2. 设置`Connection`对象的以下属性:
- `QName`-(必选)指定队列名称;这应该是指定队列管理器的有效队列。
- `QMgr`-指定要使用的队列管理器;它应该是IBM `WebSphere MQ`服务器上的有效队列管理器。
如果省略此参数,系统将使用IBM `WebSphere MQ`中配置的默认队列管理器。或者,如果IBM `WebSphere MQ`已配置为队列管理器由队列名称确定,则系统将使用适合给定队列名称的队列管理器。
3. 或者,通过设置`Connection`对象的以下属性来指定要使用的频道:
- `Connection` - 指定IBM `WebSphere MQ`服务器的主机和端口。例如:`"127.0.0.1:1401"`。
- `Channel` - 指定要使用的频道的名称。这必须是IBM WebSphere MQ服务器上的有效通道。
- `Transport` - 指定通道使用的传输。此属性可以是以下之一: `"TCP"`, `"LU62"`, `"NETBIOS"`, `"SPX"`
如果省略这些参数,系统将使用IBM `WebSphere MQ`中配置的默认通道规范。或者,如果系统已配置为通道由队列名称确定,则系统使用适合给定队列名称的通道。
4. 如果频道需要身份验证,请设置`Connection`对象的以下属性:
- 用户名-指定有权使用此频道的用户名。
- 密码-指定给定用户的密码。
5. 调用`Connection`对象的`%ErrLog()`方法。此方法接受一个参数,即要用于此连接对象的日志文件的名称。
6. 检查`%ErrLog()`方法返回的值。
7. 调用`Connection`对象的`%Connect()`方法。
8. 检查`%Connect()`方法返回的值。如果该方法返回1,则表明连接已成功建立,可以使用`Connection`对象发送或接收消息(具体取决于您使用的类)。
# 指定字符集(CCSID)
要设置用于消息转换的字符集,请调用`Connection`对象的`%SetCharSet()`方法。指定在IBM `WebSphere MQ`中使用的整数编码字符集`ID(CCSID)`。
- 如果正在发送消息,这应该是这些消息的字符集。如果不指定字符集,则MQ系统假定消息使用为`MQ`客户端指定的默认字符集。
- 如果要检索邮件,则这是要将这些邮件翻译为的字符集。
要获取当前正在使用的`CCSID`,请调用`%charset()`方法。此方法通过引用返回`CCSID`,并返回1或0以指示是否成功.
# 指定其他消息选项
要指定消息描述符选项,可以选择设置连接对象的以下属性:
- `ApplIdentityData`指定应用程序标识消息描述符选项。
- `PutApplType`指定`PUT Application Type`消息描述符选项。
## 发送消息
要发送邮件,请执行以下操作:
1. 按照“创建连接对象”中的说明创建连接对象。在这种情况下,请创建`%Net.MQSend`的实例。`Connection`对象有一个消息队列,可以向该队列发送消息。
2. 根据需要调用以下方法:
- `%put()`-给定一个字符串,此方法将该字符串写入消息队列。
- `%PutStream()`-给定初始化的文件字符流,此方法将该字符串写入消息队列。请注意,必须设置流的`Filename`属性才能对其进行初始化。不支持二进制流。
- `%SetMsgId()`-给定一个字符串,此方法使用该字符串作为发送的下一条消息的消息ID。
3. 检查调用的方法返回的值。
4. 检索完消息后,调用`Connection`对象的`%Close()`方法以释放动态链接库的句柄。
示例1:`SendString()`
下面的类方法使用队列管理器`QM_antigua`和名为 `S_antigua`的队列通道向队列`mqtest`发送一条简单的字符串消息。通道使用TCP传输,IBM `WebSphere MQ`服务器运行在名为`Antigua`的机器上,并侦听端口1401。
```java
///Method returns reason code from IBM WebSphere MQ
ClassMethod SendString() As %Integer
{
Set send=##class(%Net.MQSend).%New()
Set queue="mqtest"
Set qm="QM_antigua"
Set chan="S_antigua/TCP/antigua(1414)"
Set logfile="c:\mq-send-log.txt"
Set check=send.%Init(queue,qm,chan,logfile)
If 'check Quit send.%GetLastError()
//send a unique message
Set check=send.%Put("This is a test message "_$h)
If 'check Quit send.%GetLastError()
Quit check
}
```
示例2:`SendCharacterStream()`
下面的类方法发送文件字符流的内容。它使用的队列与上一个示例中使用的队列相同:
```java
///Method returns reason code from IBM WebSphere MQ
ClassMethod SendCharacterStream() As %Integer
{
Set send=##class(%Net.MQSend).%New()
Set queue="mqtest"
Set qm="QM_antigua"
Set chan="S_antigua/TCP/antigua(1414)"
Set logfile="c:\mq-send-log.txt"
Set check=send.%Init(queue,qm,chan,logfile)
If 'check Quit send.%GetLastError()
//initialize the stream and tell it what file to use
Set longmsg=##class(%FileCharacterStream).%New()
Set longmsg.Filename="c:\input-sample.txt"
Set check=send.%PutStream(longmsg)
If 'check Quit send.%GetLastError()
Quit check
}
```
示例3:从终端发送消息
以下示例显示了向IBM `WebSphere MQ`队列发送消息的终端会话。这只能在配置了IBM `WebSphere MQ`客户端的计算机上运行。
```java
Set MySendQ = ##class(%Net.MQSend).%New()
Do MySendQ.%Init("Q_1", "QM_1","QC_1/TCP/127.0.0.1(1401)","C:\mq.log")
Do MySendQ.%Put("Hello from tester")
Set MyRecvQ =##class(%Net.MQRecv).%New()
Do MyRecvQ.%Init("Q_1", "QM_1","QC_1","C:\mq.log")
Do MyRecvQ.%Get(.msg, 10000)
Write msg,!
```
文章
Michael Lei · 六月 21, 2022
如果您使用InterSystems技术开发了自己的网络应用,现在想在客户端进行验证码验证,以确定用户真实性使其更加安全。有一些现代框架可以解决验证码的问题,然而它们中的大多数需要互联网接入来生成代码,有时实施起来很复杂。考虑到图像识别已经非常成熟,您可以参考本文为基本例子。这就是为什么现在倾向于看到更多的模式识别验证码而不是单纯的阅读验证码。(例如,点击所有有店面的图片)。如果你需要更复杂的东西,请继续开发,改进这个代码并分享它。 继续阅读以了解如何使用这个基本的例子:
Demo.Captcha class
使用这个类,你可以在一个物理目录上创建验证码图像文件,以便在你的应用程序上显示。请注意,创建图像的目录必须是可用的,以便你的Web应用程序访问这些图像。要创建验证码图像,请调用以下方法,将完整的文件名作为一个参数:
创建 image 文件
Set tCount = $Increment(^CacheTemp("CAPTCHA",0)) Set tPath = "C:\InterSystems\Ensemble201710\CSP\user\images\captcha\"If '##class(%File).DirectoryExists(tPath) { Set tSC = ##class(%File).CreateDirectoryChain(tPath) } Set tFileName = %session.SessionId_tCount_".bmp" Set tFullName = tPath_tFileNameSet tCaptcha = ##class(Demo.Captcha).CreateImage(tFullName) Write tCaptcha,!
在 System/系统 > Security Management/安全管理 > Web Applications/Web 应用 > Edit Web Application/编辑Web应用菜单下添加“\images\captcha\” , 请注意 CSP 文件物理路径在上面代码里是一样的。
运行上面的代码来创建验证码图像后,请看一下该路径。你会看到所有生成的验证码图像如下(注意,你需要一个%session对象):
Demo.Captcha类中的CreateImage()方法也将返回生成的验证码,它将允许你在你的Web应用程序上对用户输入的验证码进行验证。
例子
为了使大家的工作简单点,我准备了一个简单的CSP文件,可以渲染一个验证码图像并进行验证。你可以导入所附的XML文件,并根据需要验证和改变路径以匹配你的CSP Web应用。
安装在USER命名空间上,打开Studio并导入XML文件;
在浏览器上打开 captcha.csp 文件;
点击 “change image/换一张” 按钮 来创建和显示新的captcha图像;
在空白输入框中输入图像代码;
点击验证按钮并检查信息;
导入类
打开 Studio;
选择 USER 命名空间;
到Tools/工具->Import Local导入本地 菜单下并选择你下载好的 captcha.xml ;
根据下图导入需要的类;
根据你的CSP Web应用改变验证码图像路径;
在浏览器通过点击浏览网页按钮 打开captcha.csp 文件;
如果你需要改变图像,点击改变图像按钮;
查看验证码图像目录;
在空白输入框中输入验证码,并点击验证;
查看结果;
随意重复这些步骤;
希望这些能帮助到您,欢迎随时联系我们.
Fábio Gonçalves
Sales Engineer - Intersystems Brazil
文章
Jingwei Wang · 九月 20, 2022
1. VMWare快照引起的网络中断导致非计划内主备机切换问题
1.1 问题描述
在创建虚拟机快照时,虚拟机需要短时间的冻结,这个短时间冻结通常指虚拟机静默,在静默过程中网络连接处于中断状态。由于数据库的不断增长,使用VMWare快照的方式对虚拟机进行备份的时长也会不断增加,当对虚拟机进行快照的时长长于InterSystems镜像服务质量 (QoS) 超时时间,即当主机网络中断超过QoS超时时间,仲裁机与备机观察并相互确认与主机的连接丢失后,将发起切换过程,使原备机成为主机并将虚拟IP从主机MAC地址解绑后重绑定到备机的MAC地址上。特别需要注意的是,在这种由于网络中断引起的切换中,仲裁与备机都无法得知主机的实际工作状态。因此,在主机网络连接恢复后,为了为了避免因切换期间主机还在处理数据导致主备机间数据不一致,备机主动发起请求让主机下线,关闭主机,此时主机状态显示为关闭(Down)。
1.2 解决方案
对于由于虚拟机快照引起的网络中断造成的非计划内主备切换问题,请参考以下两种解决方案:
使用数据库冻结/解冻脚本,具体脚本和操作方式请参考社区文章虚拟机备份和 Caché 冻结/解冻脚本,如有其他疑问请联系InterSystems WRC
在镜像集群中增加一个异步镜像成员,使用异步镜像成员创建虚拟机快照,由于此异步镜像成员也会同步获取主机数据,但是不会自动切换,所以在此异步镜像成员中创建虚拟机快照,既可以备份虚拟机,也不会引起非计划内主备机切换问题。
2. VMWare资源不足导致的主备机非计划内切换问题:
2.1 问题描述
当虚拟机的物理资源不足,可能会导致网络中断或者InterSystems IRIS 实例日志守护进程不响应超过 30 秒(或300 秒),导致主备非计划内切换。
2.2 解决方案
请扩展虚拟机的物理资源,且增加对虚拟机的状态进行监控,以防再次出现资源不足情况。
监控网络状态Log
由于网络中断造成的镜像主备切换是非计划内主备切换的重要原因之一,所以为了方便排查问题,可以在仲裁机上加一个ping的脚本,用来ping主机和备机,并将ping的结果放入log中,当发生非计划内主备切换时这个log有利于排查问题。也可以使用此ping脚本来监控网络状态,使用户能够第一时间获得网络状态信息。
文章
姚 鑫 · 五月 14, 2021
# 第六章 临时全局变量和IRISTEMP数据库
对于某些操作,可能需要全局变量的功能,而不需要无限期保存数据。例如,可能希望使用全局对某些不需要存储到磁盘的数据进行排序。对于这些操作,`InterSystems IRIS`提供了临时全局机制。该机制的工作方式如下:
- 对于应用程序名称空间,可以定义一个全局映射,以便将具有特定命名约定的全局变量映射到`IRISTEMP`数据库,该数据库是一个特殊的数据库,如下所述。
例如,可以定义一个全局映射,以便将名称为`^AcmeTemp*`的所有全局变量映射到`IRISTEMP`数据库。
- 当代码需要临时存储数据并再次读取它时,代码将向使用该命名约定的全局变量写入数据,并从全局变量读取数据。
例如,要保存值,代码可能会执行以下操作:
```java
set ^AcmeTempOrderApp("sortedarray")=some value
```
然后,稍后代码可能会执行以下操作:
```java
set somevariable = ^AcmeTempOrderApp("sortedarray")
```
**通过使用临时全局变量,可以利用`IRISTEMP`数据库没有日志记录这一事实。因为数据库没有日记记录,所以使用该数据库的操作不会产生日记文件。日志文件可能会变得很大,并可能导致空间问题**。但是,请注意以下几点:
不能回滚修改`IRISTEMP`数据库中的全局变量的任何事务;此行为特定于`IRISTEMP`。如果需要通过事务管理临时工作,请不要使用`IRISTEMP`中的全局变量来实现此目的。
请注意,仅对不需要保存的工作使用`IRISTEMP`。
# 定义临时全局变量的映射
要定义临时全局变量的映射,请执行以下操作:
1. 选择一个命名约定,并确保所有开发人员都知道这一点。请注意以下几点:
- **考虑是要有多个临时全局变量还是要少一些具有多个节点的临时全局变量。与读取或写入相同数量的独立全局变量相比,`InterSystems IRIS`更容易高效地读取或写入同一全局变量中的不同节点。这种效率差异对于少数全局变量来说可以忽略不计,但当有数百个独立的全局变量时,效率差异就非常明显。**
- 如果计划在多个名称空间中使用相同的全局映射,那么设计一个系统,使一个名称空间中的工作不会干扰另一个名称空间中的工作。例如,可以使用命名空间名称作为全局变量中的下标。
- 类似地,即使在一个命名空间内,也要设计一个系统,使代码的每个部分在同一全局中使用不同的全局或不同的下标,以避免干扰。
- 请勿使用系统保留的全局名称。
2. 在管理门户中,导航到命名空间页面(System Administration > Configuration > System Configuration > Namespaces)。
3. 在应用程序命名空间所在的行中,单击Global Mappings。
4. 在全局映射页面中,单击新建全局映射。
5. 对于全局数据库位置,选择`IRISTEMP`。
6. 对于全局名称,输入以星号(`*`)结尾的名称。不要包括名称的第一个插入符号。
例如: `AcmeTemp*`
此映射会导致名称以`AcmeTemp*`开头的所有全局变量映射到`IRISTEMP`数据库。
7. 单击OK。
注意:>> 显示在新映射行的第一列中,表示已打开映射进行编辑。
8. 要保存映射以便InterSystems IRIS使用它们,请单击保存更改。




# IRISTEMP的系统使用
请注意,InterSystems使用临时全局变量作为临时空间,例如,在执行某些查询(用于排序、分组、计算聚合等)期间用作临时索引。
IRISTEMP中包含的一些系统全局变量包括:
- `^IRIS.Temp*`
- `^mtemp*`
永远不要更改这些全局变量中的任何一个。
文章
Hao Ma · 一月 10, 2021
本文讨论 Windows 写入缓存设置,该设置会使系统在断电或操作系统崩溃的情况下容易发生数据丢失或损坏。 该设置在某些 Windows 配置中默认开启。
为磁盘启用 Windows 写入缓存意味着 Caché(或任何程序)写入该磁盘的某些内容不一定会立即提交到持久性存储(即使 Caché 在其写入阶段的特定关键点刷新从操作系统缓存到磁盘的写入也是如此)。 如果计算机断电,为该设备缓存的任何内容都会丢失,除非该设备的缓存是非易失性的或者由电池供电。 Caché 依靠操作系统来保证数据的持久性。 在这种情况下,保证是无效的。 对于 Caché 来说,这可能会导致数据库损坏或者数据库或日志文件中的数据缺失。
InterSystems 的文档显示,使“写入映像日志”提供的保证失效的一种情况是回写缓存内容丢失(请参见 [http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCDI_wij#GCDI/wij_limits](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCDI_wij#GCDI_wij_limits))。 InterSystems 全球响应中心的数据完整性团队研究了许多 Windows 平台上的数据丢失或损坏案例,这些案例中有证据表明,回写缓存内容丢失是由该设置的值导致的。
值得一提的是,磁盘的缓存可能会有效防止发生此类问题。 如果相关磁盘的缓存是非易失性的或由电池供电,则即使开启该设置,写入磁盘也应该是安全的。 如果相关存储比直接连接的磁盘更复杂,您需要了解在该存储基础架构的何处对写入进行缓存,以及这些缓存是否是易失性的或者是否由电池供电,以评估风险。
您可以转到“设备管理器”,展开“磁盘驱动器”部分,然后查看给定磁盘的属性来查看设置。 我们感兴趣的设置在“策略”选项卡上。

界面上的用词并不总是与您在这里看到的相同,可能因设备类型的不同而有所不同。 不过,这是常见的用词表述,并且 Windows 明确指出,开启该设置后,如果机器断电或崩溃,系统可能会发生数据丢失。
接下来是同一机器上另一个磁盘的示例,其中的影响没有那么明显。在这里选择“更好的性能”将与在另一个示例中选择“启用写入缓存”带来相同问题。

在这两个示例中,您看到的选定设置都是该设备的默认设置,我没有更改过。 您可以看到,在第一个示例中,默认设置使设备处于风险之中,而第二个示例则没有。 据我所知,并没有通用于所有设备类型或 Windows 版本的默认设置。 换句话说,需要在每台设备上检查此设置,以了解设备是否存在此风险。
作为系统管理员,处理这种情况有三种基本方法。 禁用该设置是最简单的方法,可确保不会面临此风险。 但是,禁用该设置可能会对性能产生不可接受的影响。 如果是这种情况,您可能更愿意开启该设置,并将计算机连接到不间断电源。 这样做可以防止断电导致的数据丢失或损坏,因为 UPS 应该可以在断电时提供足够的时间让您从容地关机。 最后一个选择是简单地接受服务器断电或崩溃时数据丢失的风险。 InterSystems 建议不要采用此方式。 消费级 UPS 已相当便宜,而且检测完整性问题并从中恢复可能非常耗时又会产生问题。
InterSystems 建议您在未确保计算机连接到不间断电源的情况下不要开启此设置。 如果存储是外部设备,则该设备也需要连接到 UPS。
文章
Michael Lei · 八月 12, 2021
我最近看到一个客户问题,是使用 Caché 数据库上运行的病毒扫描程序导致应用程序间歇性变慢和用户响应时间不佳。
出乎意料的是,这是一个常见问题,所以本帖就是提个醒,要将主要 Caché 组件排除在病毒扫描之外。
通常,病毒扫描必须排除 CACHE.DAT 数据库文件和 Caché 二进制文件。 如果防病毒软件扫描 CACHE.DAT 和 InterSystems 文件,那么系统性能_将_受到较大影响。
具体来说,防病毒软件必须排除的 Caché 文件包括:
* Caché 数据库 (CACHE.DAT)。
* Ensemble/bin 或 cache/bin 目录中的 Caché 可执行文件。
* 写入映像日志 (WIJ)。
* 日志目录中的日志文件。
更多详细信息,请参见在线文档。
[更多 Caché 文档](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSA_thirdparty)
文章
Johnny Wang · 一月 30, 2022
我的几个孩子都很喜欢手工艺品,您可能会觉得作为一个父亲我会用夸张的表情表扬他们很有创意然后还拍照片发到Pinterest(世界上最大的图片社交分享网站)上去,但是我从来都没这么做过。我肯定爱我的孩子,我也确实认为他们有创意,但老实讲如果你有一个正上小学的孩子,你肯定很清楚他们实际的水平。
首先,要去制作一个手工艺品,你得先在油管上面看五分钟的教学视频,在此之前你可能已经浏览过大量的同类视频,你也知道那些标题党起的“五分钟教你学会”的题目就是在骗你点进去,但你可能刷着刷着手机就过去了五个钟。这类视频无非是一个人拿着一个彩色的塑料瓶,或者一个有光泽的鞋盒,把所有东西切开、用胶带和胶水粘在一起,然后你就获得了一个精美无比但是根本没用的艺术品,但至少拍照片发个朋友圈看起来还蛮不错。
第二步,你小孩看完视频了,也想自己动手做。老实讲你没法拒绝这种能够锻炼他们创意的好机会,这绝对是寓教于乐的好机会,你也把那些瓶子、纸板箱和其他的垃圾重新利用起来了。这些视频往往十分重要,这说不定会影响他们以后成为成功的设计师、建筑师或者行业精英。
再然后,关键的东西来了:胶水。
我家的手工艺品购买预算(您别说真有这么个预算)几乎都花在了买胶水或者胶带上,在过去几年中,我都在用一种叫做“和纸”的带光泽的胶带、用来打胶的胶枪和会发光的百特棒,它贴在厨房或者餐桌等等地方就会很亮。还好我现在的工作让我承担得起这些花费,但同样让人沮丧的是大部分钱都被花在胶带胶水这种辅助工具上,而不是花在提升手工艺品的质量上。
系统之间的数据流成本很高
当我看到企业架构师描述他们的环境时,我经常有一种感觉,同时这种感觉也经常让我觉得挫败。那些架构师将经过验证的开源技术(比如 Postgres 和 MySQL 或他们的云版),与一种或多种花哨的专用技术(如 Clickhouse、TimescaleDB 或 CouchBase)结合到一个数据架构中。从表面上看,这完全有道理。 我们非常感谢那些经过验证的开源技术,作为一名技术专家,我经常对这些用于特殊用途的解决方案所产生的创新印象深刻。 然而,这种方法产生的复合数据架构通常不像预期的那么简单或预算友好,这与我的孩子经常要求增加手工艺品预算的原因相同:胶水不够用了。
一个好的数据管道或 ETL 软件并不便宜,构建这些数据流的数据工程师或顾问也不便宜。 更糟糕的是,就像我孩子的胶带会磨损一样,系统之间的数据流需要昂贵的维护,因为它们需要保持运行的时间也很长,这绝不是一个5分钟的手工艺品视频讲得清楚的事情。
采用统一技术的高效数据架构
像 InterSystems IRIS 这样的统一数据平台提供了事务处理和分析工作负载的数据架构,并通过许多不同的数据模型提供高效的并发访问,所有这些都采用统一技术。 通过在 InterSystems IRIS 上构建你的应用程序、数据仓库和其他解决方案,你可以节省大量粘合和手动工作,而不会牺牲处理您的用例所要求的特殊用途数据,因为没有复制、同步或推送你的数据。 更重要的是,使用这种类型的数据架构,您最终将获得在医疗保健、金融服务和许多其他行业中已经得到证明的弹性,而不是五种不同工具的最小公分母。
回到手工艺品的话题上,我希望未来每隔一周左右我问我的孩子们的问题能够变成这样:“我不是不要你的创意; 我只是要求你少用胶水。”
关于作者:Benjamin DeBoe
Benjamin 是 InterSystems 数据平台组的产品经理,负责可扩展性和分析领域。 作为 InterSystems 收购 iKnow 的一份子,他于 2010 年加入 InterSystems,并曾使用各种数据库技术,主要在数据仓库、自然语言处理和任何分析领域。
点击查看原文链接 乐高就是不用胶水的创造,中国传统的木结构(榫卯)也是不需要胶水的,最好/稳固的创造/搭建都是不用胶水的。。。 这个类比非常到位了
文章
姚 鑫 · 三月 26, 2021
# 第十三章 使用动态SQL(四)
# 返回完整结果集
使用`%Execute()`或`%ExecDirect()`执行语句将返回一个实现`%SQL.StatementResult`接口的对象。该对象可以是单一值,结果集或从`CALL`语句返回的上下文对象。
## %Display()方法
可以通过调用`%SQL.StatementResult`类的`%Display()`实例方法来显示整个结果集(结果对象的内容),如以下示例所示:
```
DO rset.%Display()
```
请注意,`%Display()`方法不会返回%Status值。
显示查询结果集时,`%Display()`通过显示行数来结束:“受影响的5行”。 (这是`%Display()`遍历结果集之后的`%ROWCOUNT`值。)请注意,`%Display()`不会在此行计数语句之后发出行返回。
`%Display()`有两个可选参数:
- 分隔符:在数据列和数据标题之间插入的字符串。它出现在结果集列之间,紧靠标题或数据值之前。默认为无定界符。如果省略,请在“列对齐”标志之前指定一个占位符逗号。
- 列对齐:整数标志,指定如何计算数据列和数据标题之间的空格。可用的选项有:
- 0:结果集标题/数据列将根据标准定界符(选项卡)对齐。这是默认值。
- 1:结果集标题/数据列将根据列标题和标准定界符(标签)的长度对齐。
- 2:结果集标题/数据列将根据列数据属性的精度/长度和标准定界符(选项卡)进行对齐。
## `%DisplayFormatted()`方法
可以通过调用`%SQL.StatementResult`类的`%DisplayFormatted()`实例方法,而不是调用`%Display()`,将结果集内容重新格式化并重定向到生成的文件。
可以通过指定字符串选项`%DisplayFormatted(“HTML”)`或相应的整数代码`%DisplayFormatted(1)`来指定结果集格式。可以使用以下格式:XML(整数代码0),HTML(整数代码1),PDF(整数代码2),TXT(整数代码99)或CSV(整数代码100)。 (请注意,CSV格式未实现为真正的逗号分隔值输出;相反,它使用制表符来分隔列。)TXT格式(整数代码99)以行数结尾(例如,“受影响的5行”) ”);其他格式不包括行数。 InterSystems IRIS生成指定类型的文件,并附加适当的文件扩展名。
可以指定或省略结果集文件名:
- 如果指定一个目标文件(例如,`%DisplayFormatted(99,"myresults")`),则在当前命名空间的子目录的mgr目录中生成具有该名称和相应后缀(文件扩展名)的文件。
例如,`C:\InterSystems\IRIS\mgr\user\myresults.txt`.
如果具有该后缀的指定文件已经存在,则InterSystems IRIS将用新数据覆盖它。
- 如果没有指定目标文件(例如,`%DisplayFormatted(99)`,则在Temp子目录的mgr目录中生成一个具有随机生成的名称和适当后缀(文件扩展名)的文件。
例如,`C:\InterSystems\IRIS\mgr\Temp\w4FR2gM7tX2Fjs.txt.`
每次运行一个查询时,都会生成一个新的目标文件。
这些例子显示了Windows文件名;
InterSystems IRIS支持其他操作系统上的等效位置。
如果无法打开指定的文件,则此操作将在30秒后超时并显示一条错误消息;否则,该操作将超时。当用户没有对指定目录(文件夹)的`WRITE`权限时,通常会发生这种情况。
**如果无法以指定的格式呈现数据,则将创建目标文件,但不会将结果集数据写入其中。而是将适当的消息写入目标文件。例如,流字段`OID`包含与XML和HTML特殊格式字符冲突的字符。可以通过在流字段上使用`XMLELEMENT`函数来解决此XML和HTML流字段问题。例如`SELECT Name,XMLELEMENT(“ Para”,Notes)`。**
可以选择提供`%DisplayFormatted()`在执行指定格式转换时将使用的转换表的名称。
如果一个结果集序列中有多个结果集,则每个结果集的内容都将写入其自己的文件中。
可选的第三个`%DisplayFormatted()`参数指定消息存储在单独的结果集中。成功完成后,将返回类似以下的消息:
```
Message
21 row(s) affected.
```
下面的Windows示例在`C:\InterSystems\IRIS\mgr\user\`中创建了两个PDF(整数代码2)结果集文件。
它为消息创建一个mess结果集,然后使用`%Display()`将消息显示到终端:
```java
/// d ##class(PHA.TEST.SQL).CreatePDF()
ClassMethod CreatePDF()
{
SET myquery=2
SET myquery(1)="SELECT Name,Age FROM Sample.Person"
SET myquery(2)="WHERE Age > ? AND Age < ? ORDER BY Age"
SET rset = ##class(%SQL.Statement).%ExecDirect(,.myquery,12,20)
IF rset.%SQLCODE'=0 {
WRITE !,"1st ExecDirect SQLCODE=",rset.%SQLCODE,!,rset.%Message QUIT
}
DO rset.%DisplayFormatted(2,"Teenagers",.mess)
DO mess.%Display()
WRITE !,"End of teen data",!!
SET rset2 = ##class(%SQL.Statement).%ExecDirect(,.myquery,19,30)
IF rset2.%SQLCODE'=0 {
WRITE !,"2nd ExecDirect SQLCODE=",rset2.%SQLCODE,!,rset2.%Message QUIT
}
DO rset2.%DisplayFormatted(2,"Twenties",.mess)
DO mess.%Display()
WRITE !,"End of twenties data"
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).CreatePDF()
Message
9 row(s) affected.
End of teen data
Message
20 row(s) affected.
End of twenties data
```
```java
/// d ##class(PHA.TEST.SQL).CreatePDF1()
ClassMethod CreatePDF1()
{
ZNSPACE "SAMPLES"
SET myquery=2
SET myquery(1)="SELECT Name,Age FROM Sample.Person"
SET myquery(2)="WHERE Age > ? AND Age < ? ORDER BY Age"
SET rset = ##class(%SQL.Statement).%ExecDirect(,.myquery,12,20)
DO rset.%DisplayFormatted(2,"Teenagers")
WRITE !,"End of teen data",!!
SET rset2 = ##class(%SQL.Statement).%ExecDirect(,.myquery,19,30)
DO rset2.%DisplayFormatted(2,"Twenties")
WRITE !,"End of twenties data"
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).CreatePDF1()
End of teen data
End of twenties data
```
## 对结果集进行分页
可以使用一个视图ID (`%VID`)来分页结果集。下面的例子从结果集中返回页面,每个页面包含5行:
```java
/// d ##class(PHA.TEST.SQL).Paginating()
ClassMethod Paginating()
{
SET q1="SELECT %VID AS RSRow,* FROM "
SET q2="(SELECT Name,Home_State FROM Sample.Person WHERE Home_State %STARTSWITH 'M') "
SET q3="WHERE %VID BETWEEN ? AND ?"
SET myquery = q1_q2_q3
SET tStatement = ##class(%SQL.Statement).%New()
SET qStatus=tStatement.%Prepare(myquery)
IF qStatus'=1 {
WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT
}
FOR i=1:5:25 {
WRITE !!,"Next Page",!
SET rset=tStatement.%Execute(i,i+4)
DO rset.%Display()
}
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).Paginating()
Next Page
RSRow Name Home_State
1 O'Rielly,Chris H. MS
2 Orwell,John V. MT
3 Zevon,Heloisa O. MI
4 Kratzmann,Emily Z. MO
5 King,Dmitry G. MO
5 Rows(s) Affected
Next Page
RSRow Name Home_State
6 Hanson,George C. MD
7 Martinez,Emilio G. MO
8 Cheng,Charlotte Y. MI
9 Emerson,Edgar T. MO
10 Nelson,Neil E. MT
5 Rows(s) Affected
Next Page
RSRow Name Home_State
11 Larson,Nataliya Z. MD
12 Lennon,Chelsea T. MD
13 Ingleman,Kristen U. MT
14 Zucherro,Olga H. MN
15 Ng,Lola H. MD
5 Rows(s) Affected
Next Page
RSRow Name Home_State
16 Frost,Xavier D. MO
17 Adams,Diane F. MD
18 Isaacs,Chad N. MN
19 Van De Griek,Phil S. MS
20 Schaefer,Usha G. MO
5 Rows(s) Affected
Next Page
RSRow Name Home_State
21 Wells,Sophia U. MS
22 Vivaldi,Michelle N. MD
23 Anderson,Valery N. MD
24 Frost,Heloisa K. MI
25 Gallant,Thelma Q. MA
5 Rows(s) Affected
```
文章
Frank Ma · 五月 24, 2022
同事们,大家好
在这篇文章中,我将告诉你我们如何将报告生成时间从28分钟减少到1分钟。让我告诉你我们是如何实现这一目标的
我希望,如果有必要,你将能够为自己重现同样的结果。这篇文章里有一些有用的链接,所以要读到最后。
让我们开始吧。
报告
我们使用Adaptive Analytics和InterSystems Reports Server为一家公司做报告。以前,这个报告是以DeepSee的屏幕截图形式生成的。总的来说,这并不坏,但它花费了大量的时间,而且看起来不是很可读。该报告本身由12页组成,为PDF格式。
一般来说,数据不是太大,不会使报告的生成花费很多时间
源数据
然而,在撰写本文时,有一个表包含11,330,263行。不是那么关键,但它造成了延迟。即使是计算行数的查询也需要近30秒
最初,系统的交互方案是这样的:
Atscale创建了自己的数据缓存,这导致了性能的提高。
Logi使用自己的数据缓存,这稍微加快了报告的开发速度。
但总的来说,这仍然导致了报告在28分钟内形成的事实。
鉴于报告只有12页,这个速度还是很慢的。
我们甚至故意添加了新的标签,并将报告中的小部件复制到那里,以便在开发或调试时不需要生成整个报告。也许这就是在Logi上开发时的一种日常技巧,或者说是一种正常的开发方法。总的来说,我们在工作中使用了它
在报告生成时,有数百个请求从Logi到Atscale,还有一些请求从Astcale到IRIS。一些单独的查询长达4分钟。有几次,请求一般都是在超时的情况下发出的。
然后我们意识到,这种情况不能再继续下去了。于是我们把自适应分析的主要功能连接起来,方案变成了这样:
这是一个UDAF功能,换句话说,这是个用户定义的聚合函数。实际上这是些汇总表,根据要求,定期地将需要测量的聚合值存储在其中。而最有趣的是,这些汇总表是由Atscale自动创建和更新的。
为了实现聚合,我们编译了isc-aa-udaf包,该包目前在一个私人仓库中,因为根据Atscale的使用条款,它不能被免费分发。
在打开汇总表后,创建服务表花了几分钟,汇总表被计算,总的来说,数据库被加载。但随后真正的解脱开始了。系统开始像它应该的那样工作。以前需要4分钟才能形成的请求,开始在5秒内形成。缓存变得更快。
结果,原先花了28分钟才形成的报告现在开始在1分钟内形成。
值得注意的是,这样的增长更多的是稳定的、生产系统的特征,在这些系统中,立方体是相对稳定的,聚集物被越来越多的收集。当立方体结构发生变化时,在对变化后的立方体的第一次请求中,聚合被重构并重新创建。
我们做了什么
我们所做的基本如下:
安装IRIS Adaptive Analytics UDAF
在IRIS中创建名称空间,用于存储聚合数据
连接IRIS 到 Atscale
定制功能安装模式=在数据仓库中启用定制管理功能
Adaptive Analytics已经用数据创建了一个立方体
在Logi中创建报告
测试和测量
这里的细节:
InterSystems IRIS已经为UDAF的工作安装了必要的类。我们已经将它们打包在一个名为isc-aa-udaf的ZPM包中,该包存储在zpm注册表pm.intersystems.com中。这个注册表对InterSystems的官方客户是可用的。
iris 命令:
zpm “install isc-aa-udaf”
一个旨在优化资源使用的可选项:我们为IRIS添加了一个专门的命名空间,它将存储预先计算的聚合值。这个命名空间的名称将在下一步中用到。
将IRIS连接到Atscale作为立方体(Cube)的数据源。转到设置(Setting),然后是数据仓库(Data Warehouses ),最后是创建数据仓库(CREATE DATA WAREHOUSE)。 在字段号1中指定了解析后的数据所存储的命名空间
在字段号2中,我们指定了在步骤2中创建的用于存储聚合的命名空间。这个值可以与1的值相同,在这种情况下,集合体将被存储在数据的旁边。在这种情况下,数据源不能是只读的。
我们将定制功能安装模式(CUSTOM FUNCTION INSTALLATION MODE)设置为用户管理(Customer Managed),因为我们之前在第一步安装了UDAF。如果你指定无(None)模式,那么即使安装了UDAF,这些功能也不会被使用,也不会有性能上的提高。 如果一切操作正确,那么UDAF检查显示绿色。
使用创建的数据仓库创建了一个项目和一个立方体。这是一个漫长而令人兴奋的过程。我不会在这里详细谈论这个问题,已经有好几篇关于它的文章,包括我的文章《如何轻松开始在Adaptive Analytics + InterSystems Reports中工作》。
Atscale上发布的项目为Logi报告创建了数据源连接。在之前的文章中,我也介绍了如何创建报告。链接为: 《如何轻松开始在Adaptive Analytics + InterSystems Reports中工作》。
测试和测量。这里很有趣。我最初设计的报告没有启用UDAF。正因为如此,一些请求被执行了4分钟或更长时间。由于该报告由12页组成,完成报告的时间平均为28分钟。
启用UDAF后,Atscale系统在自动模式下用一段时间加载数据源。她会自己计算将在报告中使用的实际查询,并为它准备预先计算的数值。此外,Intersystems报告是基于计算出来的参数,Intersystems报告本身对这些参数进行了部分缓存,AtScale系统给出了额外的优化,它缓存了执行相同查询的结果并即时返回,而不是重新发送到数据源。
在所述的捆绑工作包中,还有一个有趣的点:报告生成的频率越高,制作报告的时间就越短。
根据所有操作和几次测量的结果,生成12页报告的时间开始是60秒,也就是1分钟。
差别是28倍。
同时,类似的报告,在结构上完全相同,但从其他数据库中获取数据,其构建速度也有类似的提高。
基于我们所看到的,我们做出了一个明确的结论,推荐在所有未来的项目中使用这个捆绑包。它可以提高开发速度,提升调试速度,并减少向这些报告的商业消费者交付报告的时间。
我希望将来我们能够从IRIS - AtScale - Logi捆绑系统中提取更多的性能,并能够与你分享我们发现的解决方案。
如果你也有这类提升工具链性能的经验和我们分享,我将非常感激。
文章
Michael Lei · 八月 8, 2022
医疗行业的互操作性在改善病人护理、降低医疗服务提供者的成本以及为提供者提供更准确的情况方面发挥着重要作用。然而,由于有这么多不同的系统,数据的格式也有很多不同的方式。有许多标准被创造出来以试图解决这个问题,包括HL7v2、HL7v3和CDA,但每一种都有其缺点。
FHIR,即快速医疗互操作性资源,是一种新的医疗数据格式,旨在解决这些问题。它是由国际卫生级七组织(HL7)开发的,该组织还开发了HL7v2、HL7v3和CDA。
今天我们将探讨如何在VS代码中借助IntelliSense和自动完成功能,通过使用FHIR Schema 创建和验证FHIR资源。
第 1 步 :从FHIR 官方网站 https://www.hl7.org/fhir/下载 JSON schema file 文件用来做资源校验
第 2 步: 创建文件夹(在这个例子中,我使用病人文件夹和病人资源),并将提取的fhir.schema.json文件复制到同一文件夹,然后从VS Code中打开文件夹
第 3 步: 通过修改setting.json文件,设置VS代码以识别FHIR模式。按CTRL+SHIFT+P并输入工作区设置JSON文件
第 4 步: 在同一文件夹中创建一个新文件patient.fhir.json。按Ctrl+Space,你将通过IntelliSense获得FHIR资源的所有属性
添加资源类型 "病人",与病人资源有关的所有属性将出现在IntelliSense中。
VS Code 讲自动校验资源的结构和语法。
在IntelliSense和自动完成的帮助下,我们已经创建并验证了我们的病人资源。
第 5 步: 使用Postman的Rest API在InterSystems FHIR服务器上发布创建资源。
通过使用获取方法检索已创建的病人资源。
恭喜你!,我们已经创建、验证了我们的病人资源,并成功地使用postman发布和检索到InterSystems FHIR服务器。通过这种方式,我们可以轻松地创建和验证任何FHIR资源。