搜索​​​​

清除过滤器
文章
Louis Lu · 四月 15, 2021

2020 InterSystems IRIS 路线图 —— 蓝图分析

我喜欢事务型分析DBMS和高级分析细分概念 VSCode的IRIS 1.0版插件很炫酷。社区和InterSystems IRIS之间的合作对此有着非常积极的作用。但在不久的将来,减少代码开发量对于IRIS来说将是一个非常合适的选项。 动态网关/原生API将IRIS定位为面向市场上主要开放语言的最先进的数据平台,但有必要使用这些语言的公共包管理器,尤其是Maven公共仓库。 API管理器是一个不错的方案,但社区版IRIS不能用,且仅能用于由IRIS创建的API。这个关键问题亟待解决。 用于物联网的OPC-UA适配器和用于实时事件的Kakfa适配器都很棒,我很喜欢。未来,也可以考虑用于Salesforce、SAP、Office365和其他最常用平台的新适配器。 云支持目前很完美,采用ICM和IKO进行部署和管理,SAM进行监控。 FHIR加速器对于FHIR项目是一个很棒的方案,真的很有用。 IRIS的速度真的越来越快了,它能够让已经非常快的东西变得更快,非常出色。 自适应分析重磅推出后广受欢迎,它能够加速和简化分析数据立方体的创建(以完全可视化和直观的方式),并以极好的方式向Excel和其他数据查看器展示数据。未来,我很想看到InterSystems发布自己的查看器,因为IRIS本身的报告功能比较有限,且无法提供社区版,因而使它不可能在社区中推广。 IntegratedML是我最喜欢的IRIS的新功能。它非常易用,适合所有的DBA。AutoML也是超棒的技术,将会被广泛使用。现在,InterSystems需要向最终用户提供一个预测和分类查看器,比如它可以使用与SAM的Grafana相同的技术。
公告
Michael Lei · 一月 23, 2023

InterSystems 开发者竞赛:Tool(工具)

嘿开发者, 我们想邀请您参加我们的下一场比赛,该比赛致力于创造有用的工具,让您的开发伙伴们的生活更轻松: 🏆 InterSystems 开发者竞赛:Tool(工具)🏆 提交有助于加快开发速度、贡献更多定性代码并有助于使用 InterSystems IRIS 测试、部署、支持或监控您的解决方案的应用程序。 时间: 2023 年 1 月 23 日至 2 月 12 日(美国东部时间) 奖金池: 13,500 美元 话题 💡 InterSystems IRIS 开发者竞赛:Tool(工具)💡 在本次竞赛中,我们期待应用程序能够改善开发人员使用 IRIS 的体验,帮助更快地开发,贡献更多定性代码,帮助测试、部署、支持或监控您使用 InterSystems IRIS 的解决方案。 一般要求: 已接受的应用程序:Open Exchange 应用程序或现有应用程序的新应用程序,但有显着改进。我们的团队将审核所有申请,然后再批准他们参加比赛。 该应用程序应该可以在InterSystems IRIS Community Edition上运行。 匹配的应用程序类型:UI 框架、IDE、数据库管理、监控、部署工具等。 该应用程序应该是开源应用程序并发布在 GitHub 上。 应用程序的自述文件应为英文,包含安装步骤,并包含视频演示或/和应用程序工作原理的描述。 一位开发者最多可以携带 3 个应用程序参加比赛。 奖品 1. 专家提名奖(Experts Nomination)- 获奖者由我们特别挑选的专家团选出:: 🥇第一名 - 5,000 美元 🥈第二名 - 3,000 美元 🥉第三名 - 1,500 美元 🏅第四名 - $750 🏅第五名 - $500 🌟第 6-10 名 - $100 2. 社区提名奖(Community Nomination)- 获得总投票数最多的应用: 🥇第一名 - $750 🥈第二名 - $500 🥉第三名 - $250 如果几个参与者获得相同数量的选票,他们都被认为是赢家,奖金由赢家分享。 重要截止日期: 🛠 应用开发和注册阶段: 2023 年 1 月 23 日(美国东部时间 00:00):比赛开始。 2023 年 2 月 5 日(美国东部时间 23:59):提交截止日期。 ✅ 投票时间: 2023 年 2 月 6 日(美国东部时间 00:00):投票开始。 2023 年 2 月 12 日(美国东部时间 23:59):投票结束。 注意:开发者可以在整个注册和投票期间改进他们的应用程序。 谁可以参加? 任何开发人员社区成员,InterSystems 员工除外。 创建一个帐户! 👥开发人员可以组队创建协作应用程序。一个团队允许 2 到 5 名开发人员。 不要忘记在应用程序的自述文件中突出显示您的团队成员——DC 用户配置文件。 有用的资源 ✓ 示例应用程序: iris-rad-studio - 用于 UI 的 RAD cmPurgeBackup - 备份工具 errors-global-analytics - 错误可视化 objectscript-openapi-definition - 开放 API 生成器 测试覆盖率工具- 测试覆盖率助手 还有更多。 ✓ 我们建议从以下模板开始: IRIS开发模板 rest-api-竞赛模板 本机 API 竞赛模板 IRIS FHIR模板 IRIS全栈模板 IRIS互操作性模板 IRIS分析模板 ✓ 对于 IRIS 初学者: 使用 InterSystems IRIS 构建服务器端应用程序 新手学习路径 ✓ 对于ObjectScript 包管理器 (ZPM)的初学者: 如何使用 InterSystems IRIS 的 REST 应用程序构建、测试和发布 ZPM 包 使用 InterSystems IRIS 和 ZPM 的封装优先开发方法 ✓ 如何提交您的应用程序参加比赛: 如何在 Open Exchange 上发布应用程序 如何提交比赛申请 需要帮忙? 加入 InterSystems 的Discord 服务器上的竞赛频道或在本文的评论中与我们交谈。 我们迫不及待地想看到您的项目!祝你好运👍 参加本次比赛,即表示您同意此处列出的比赛条款。请在继续之前仔细阅读它们。
文章
Michael Lei · 一月 17, 2023

HTAP 数据平台插入和查询速度测试

每秒插入大量记录,同时同步进行实时查询的能力称为**混合事务分析处理 (HTAP)**。 它也被称为 Transactional analytics 或 Transanalytics 或 Translytics,当存在来自工业物联网传感器的持续实时数据流或股票市场的波动数据时,它是非常有用的技术,并且允许实时或接近实时地查询这些数据集。 在本文中我将分享我在不同平台上运行带有测试流数据的演示,同时进行持续插入和持续查询,看看每个平台上有何不同反应,如在每个平台上输入和输出数据的速度以及它们的性能。 我在本演示中试验的平台包括:InterSystems IRIS、MariaDB 和 MySQL。 试验结果 20秒的测试时间里: | | 插入数据条数 | 查询次数 | 插入数据大小 | 查询数据大小 | | --- | ------ | ---- | ------ | ------ | | IRIS | 708,000 | 59,000 | 184M | 15.217M | | MariaDB | 98,000 | 23,679 | 25M | 6.69M | | MySQL | 38,000 | 11,947 | 9.869M | 2.45M | 本演示的视频: 需要环境 Docker 和 Docker Compose 本地运行 我们在三个不同的平台(MySQL、MariaDB 和 InterSystems IRIS 社区版)上运行记录的摄取和查询速度测试。 为此,需要按如下所示为每个平台下载容器的 YAML 文件: 1. 使用 MySQL 运行速度测试 1. 下载 YAML 文件: 2. 在上述 YAML 文件所在的文件夹中打开命令提示符并运行命令,为 MySQL 构建 docker 镜像:**docker-compose -f ./docker-compose-mysql.yml up** 3. 在浏览器选项卡中输入 以查看演示 UI。 2. 使用 MariaDB 运行速度测试 1. 下载 YAML 文件: 2. 在上述 YAML 文件所在的文件夹中打开命令提示符并运行命令,为 MariaDB 构建 docker 镜像:**docker-compose -f ./docker-compose-mariadb.yml up** 3. 在浏览器选项卡中输入 以查看演示 UI。 3. 使用 InterSystems IRIS 运行速度测试 1. 下载 YAML 文件: 2. 在上述 YAML 文件所在的文件夹中打开命令提示符并运行命令,为 InterSystems IRIS 构建 docker 镜像:**docker-compose up** 3. 在浏览器选项卡中输入 以查看演示 UI。 从 localhost 运行测试后,可以看到以每秒钟摄取和查询的记录数形式显示的结果。 与 MySQL 和 MariaDB 相比,InterSystems IRIS 的数值更令人印象深刻。 异常 在尝试为每个平台运行 docker 容器时,可能会出现以下错误: “Missing Linux capabilities”(缺少 Linux 功能) ![](/sites/default/files/inline/images/error_4.png)   可以在 YAML 文件的 htapirisdb 部分添加以下行,以跳过 Linux 功能检查: **command: --check-caps false** _(@Robert.Kuszewski, 2022)_ __如下所示:![](/sites/default/files/inline/images/ss_0.png)   每个平台上的实时测试运行: 每个平台的速度测试结果 InterSystems IRIS: ![](/sites/default/files/inline/images/iris.png)   MariaDB: ![](/sites/default/files/inline/images/mariadb.png)   MySQL: ![](/sites/default/files/inline/images/mysql.png)  参考文献 1. [intersystems.com](http://intersystems.com). (Amir, S.). _InterSystems Open Exchange_. [在线] 网址: [访问日期:2022 年 9 月 20 日]。 2. Kuszewski, B. (2022). _[在 Docker 20.10.14+使用 InterSystems IRIS 容器_.](https://cn.community.intersystems.com/post/在-docker-201014-使用-intersystems-iris-容器) [在线] InterSystems 开发者社区。 英文原文: [访问日期:2022 年 10 月 20 日]。 ‌
公告
Claire Zheng · 六月 23, 2022

【参赛时间延长】InterSystems技术写作大赛:Python

嗨,开发者们!欢迎加入第二届InterSystems技术写作大赛! 🐍 InterSystems技术写作大赛:Python 🐍 6月20日至七月20日 延长至7月31日,在社区撰写一篇利用InterSystems技术使用Python的文章,主题自定。 🎁 撰文即得奖 我们为每一位参与此次写作大赛的作者准备了一份特殊礼品! 🏆 优秀文章大奖 AirPods Max; Apple Watch SE; Apple HomePod mini / Apple Pencil 奖品 1. 每个人都是InterSystems技术文章竞赛的赢家! 任何在比赛期间写文章的用户都会得到特别的奖励: 🎁 InterSystems Branded Apple AirTag 🎁 InterSystems Branded Rubik's 9-Panel Cube 2. 专家选择奖 – 文章将由InterSystems的专家进行评判: 🥇 一等奖: Apple AirPods Max 🥈 二等奖: Apple Watch SE 🥉 三等奖: Apple HomePod mini / Apple Pencil 或者另选:获奖者可以从低一级的奖品中进行选择(比如,一等奖获得者可以选择二等奖和三等奖的礼品) 3. 开发者社区奖 – 点赞最多的文章。 获胜者将有机会从以下奖品中选择一个。 🎁 Apple Pencil 🎁 Apple HomePod mini 请注意: 每位作者只可以获得某一类别奖项一次(即:获奖者最多可以获得两个奖项:一个来自专家评选,一个来自和社区点赞) 当出现票数相当的平手情况时,将以专家评判投票数作为最终票数高低的判断标准。 谁可以参加? 任何开发者社区成员(InterSystems的员工除外)。 创建一个账户! 比赛时间 📝 6月20日 - 7月20日(美东时间): 文章发布与投票时间 在这段时间内发表一篇文章。 DC成员可以用 "赞 "为发表的文章投票--在社区奖中投票。 注意:越早发表文章,就越有时间收集专家和社区投票。 有什么要求? ❗️ 任何在比赛期间写的文章,只要满足以下要求,就能自动参加比赛: 文章必须与通过InterSystems技术使用Python(内嵌Python或Python API)相关。 文章必须为英文撰写。 文章必须是100%的新文章(可以是现有文章的延续)。 不允许翻译其他社区的现有文章。 文章发布时必须带着tag: Python/ Embedded Python (具体看您的主题)。 文章篇幅不低于 750单词 (链接和代码不计入字数限制)。 同一作者可以发布多篇文章。 不同作者可以发布同一主题的文章。 🎯 最新:额外奖励 这次我们决定增加额外的奖金,将帮助您赢得奖金! 欢迎了解详情: 要求 奖励票数 详情 主题奖励 5 如果您的文章符合以下列出的建议主题,可以获得五张来自专家的投票 (vs 专家选出的第一名为3 票). 视频奖励 3 文章内容的呈现形式:在发布文章的同时制作说明视频。 讨论奖励 1 文章中有最有用的讨论,由InterSystems专家决定。 只有1篇文章可以得到这个奖励。 翻译奖励 1 文章发布后,在其他社区发布翻译版。 注意:每篇文章可获得一票。 新成员奖励 3 首次参加此次比赛的新成员,将获得三张专家票。 建议主题 以下是可以为您的文章增加额外奖励的主题列表: # 主题 详情要求 1 对InterSystems数据平台有用的Python库 描述您使用哪些库在InterSystems平台上生成应用程序。 2 从互操作性角度谈嵌入式Python 来自互操作性的嵌入式Python探索如何从互操作性产品中利用嵌入式Python。 3 嵌入式Python:通过语言结构进行翻译 虽然我们的目标是实现无缝的嵌入式Python集成,但有一些技巧和技巧可以让事情顺利进行。 下划线方法、字典、列表等。 从ObjectScript调用Python特性的最佳方式是什么? 4 PEX for Python Examples 描述一个以python为中心的方法来利用InterSystems IRIS的能力。Native Python架构中的数据模型。 5 Native API for Python Examples 描述您使用哪些库在InterSystems平台上生成应用程序。 请注意:允许不同作者就同一主题进行创作。 ➡️ 加入 InterSystems Discord 聊聊竞赛规则、奖励和您的想法吧! 期待您的大作! ✨ Important note: Prizes cannot be delivered to residents of Crimea, Russia, Belarus, Iran, North Korea, Syria, or other US embargoed countries.
公告
Claire Zheng · 九月 15, 2021

Online Meetup:与InterSystems开发者竞赛(InterSystems IRIS Analytics)竞赛优胜者交流

亲爱的社区开发者们,大家好! 我们诚挚地邀请您参加与InterSystems开发者竞赛(InterSystems IRIS Analytics)竞赛优胜者交流 online meetup! 日期 & 时间: 美国东部时间2021年9月17日(周五)12:00;北京时间2021年9月18日(周六)0:00-1:00 在此次线上交流会上,您将了解到: 优胜者简介 优胜者提交项目的简短demo 关于项目中使用到的技术的开放探讨、问答,以及下一场开发者竞赛的安排。 届时上线嘉宾: @Dmitry.Maslennikov, Co-founder, CTO and Developer Advocate, CaretDev Corp @Henry.HamonPereira, Systems Analyst at BPlus Technology @Evgeniy.Potapov, CEO at TECCOD @John Pan, @Carmen.Logue, InterSystems Product Manager - Analytics and AI @Evgeny.Shvarov, InterSystems Developer Ecosystem Manager 您还有机会在这个特别的线上研讨会中与我们的开发者交流。 期待您的参加! ➡️ 注册参会!
公告
Michael Lei · 十月 26, 2021

InterSystems IRIS和InterSystems IRIS for Health的完整套装版本供开发人员使用!

InterSystems很高兴地宣布一个全新的 开发者下载网站 提供InterSystems IRIS社区版和InterSystems IRIS for Health社区版的完整配套版本。 这些都是免费提供给应用开发者使用的。 你可以选择直接从 InterSystems开发者社区 直接 下载 InterSystems IRIS. 这些实例包括一个免费的内置13个月的许可证。 它们限制在10GB的用户数据,将在8个核心的机器上运行,支持5个并发连接,并支持应用开发。可用的平台。RedHat, Ubuntu, SUSE, Windows和macOS InterSystems IRIS 和 InterSystems IRIS for Health医疗版也可以从Docker Hub获得容器版. 请在这里查看如何开始,访问我们网站上的InterSystems IRIS 数据平台或InterSystems IRIS for Health 医疗版,了解更多关于我们的产品,并访问 开发者资源页面深入了解开发。 如果您之前注册了InterSystems登录账户(如开发者社区或WRC),您可以使用这些账户来访问开发者下载网站 。
文章
Louis Lu · 三月 12, 2021

第 1 天:使用 InterSystems Object 和 SQL 进行开发

原文在这里。 原作者YURI MARX GOME 我正在参加 Joel Solon 讲授的“使用 InterSystems Objects 和 SQL 进行开发”课程。 课程非常好,我将在这里分享一些从培训中总结的提示。 第 1 天的提示: 1. InterSystems IRIS 统一了:InterSystems IRIS Database (Caché)、IRIS Interoperability (Ensemble)、IRIS Business Intelligence (DeepSee) 和 IRIS Text Analytics (iKnow)。 2. IRIS 为多模型:对象、关系、文档和多维。 3. 互操作性:从 Java、.NET 和其他语言(如 ObjectScript)进行原生访问;ODBC 和 JDBC 数据访问,SOAP/REST 服务访问;数据路由、转换和工作流驱动消息;支持 ESB 的 SOA 架构。 4. IRIS 是事务和分析的结合。 5. IRIS 使用 ECP(用户量的分布式缓存)和Sharding进行水平数据量扩展。 6. 使用 Cloud Manager 在公共或私有容器中部署。 7. 3 种待开发 IDE 选项:VSCode(最受欢迎)、Studio(仅限 Windows)、Atelier(已弃用)。 8. 适用于 CLI 命令的终端工具。 9. 基于浏览器的管理门户。 10. IRIS 支持多平台(UNIX,Linux,Windows),并为 Linux 提供了 Docker 选项。 11. 提供年度版本 20##.1(EM - 扩展维护)和季度版本(CD - 连续交付)。 12. IRIS 区分大小写,推荐采用驼峰表示法。 13. 类是方法和属性的容器。 14. 方法执行特定任务,不允许方法重载(类中具有两个同名方法)。 15. 有 2 种类型的方法:ClassMethod(与对象实例不关联的操作)和 Method(与对象实例相关联的操作)。 16. 使用 ##class() 运行类方法并创建实例(利用 %New 或 %OpenId)以执行 Methods。 17. 方法参数的默认类型为 %String。 18. 符号 ... 表示变量参数。 示例:Method Sample(a As %String, b... as %String) as %Status。 19. 将参数作为方法调用方传递时: 如果使用 . 则作为引用传递; 参数是可选的,您可以使用 $data() 借助调用方传递的参数进行测试。 20. string 是变量的默认类型。 21. ObjectScript 支持动态类型。 22. 在 ObjectScript 中,0 为 false,其他值为 true。 23. 软件包允许您将类整理到文件夹中。 24. 如果在类或方法中使用导入,则不需要将限定名称引用到类。 25. 持久类(存储在磁盘中)扩展 %Persistent。 26. 持久类具有保持类特性/值的属性。 27. 每个持久类都有一个唯一的不可变 ID 编号。 PS 1:我用 40,000 积分兑换了这个为期 5 天的课程(价值 2800 美元) (https://globalmasters.intersystems.com/rewards/34/reward_redemptions/new) PS 2:Joel Solon 是一位出色的讲师(提供了优秀的 IRIS 认证提示) PS 3:课程材料非常好,课程资源、工具和支持都很棒。 明天我会发布第 2 天的总结。
公告
Michael Lei · 一月 9, 2022

2021 年英文社区Top 问题

a {color:#2a2e78;} 嘿,社区。 这里是2021年度开发社区问题摘要。 让我们来看看InterSystems开发人员提出的最受欢迎的问题。 统计 ✓ 2021年提出了980 个问题✓ 社区总共提出了5,699 问题 最多浏览问题 WINDOWS ODBC CACHE 驱动 by Fernando Zañartu 2,113 SOAP 错误 CONTENT-TYPE 返回 text/html 而不是 text/xml by Kurro Lopez 741 如何用xmlns 和 xsi:type 属性解析xml by water huang 733 ODBC 驱动 by Brian Bechard 667 VS Code中的意外Token错误 by David Hockenbroch 646 Log4j 脆弱性 by JOSE PALAU 597 如何在SQL查询中获得行编号? by Anderson Negreli 541 httpRequest POST 文件上传by Emanuel Lazar 527 Log4Shell Apache 影响 / Intersystems产品by Andy Stobirski 486 Intersystems Cache Studio 下载 by Joseph Lovato 461 如何在httpResponse对象中设置HTTP Response 状态编码 by Mike Yackanich 441 JSON解析空值null values in by Lucas Macori 398 如何快速简单从老的Dot Scoping转化为新的Parentleses Scoping? by Dominic Chui 397 从Caché 数据库到 IRIS数据库的转化. by Сергей Марушко 383 JSON Web Token令牌 授权与不记名令牌Tokensby Neil Thaiss 371 在另一个命名空间中调用类的方法 by Nigel Salm 371 超出License 限制? by yeung elijah 364 锁 /解锁 by Matjaz Murko 352 JWT/OAuth2.0 by M C 344 转化 ISO-8859-1 输入文件 by Michoel Reach 332 显示所有英文社区问题 » 显示所有中文社区问题 » 讨论最多的 Debugging功能不见了 by Anna Golitsyna 24 在 %SYS 命名空间外获得用户属性 by Evgenii Ermolaev 22 从 VS studio终端运行Python脚本 by Akshay Pandey 20 VS Code中的意外Token错误 by David Hockenbroch 20 JSON对象上的SQL 搜索索引. by Güvenal 20 锁 /解锁 by Matjaz Murko 19 IRIS - 原生 API 和 .NET Provider - 回归到 Cache .net Provider ?by Emanuel Lazar 18 &sql(.....) 不工作且返回SQLCODE -400 by prashanth ponugoti 18 修改 %Stream 内容 by Marlin Mixon 17 收到错误 #9406 by Rick Prichett 16 在VSCode转化 ObjectScript格式 by Julian Matthews 16 从Caché 数据库到 IRIS数据库的转化. by Сергей Марушко 15 Ensemble用SQL批量插入 by Jimmy Christian 14 #5003 没有实施by Gary Koester 14 动态 SQL 参数化 UPDATE vs INSERT的问题 by Jonathan Anglin 14 如何区分命名空间 Globals 和 Routines 数据库 ? by Muhammad Waseem 14 如何测试从虚拟文档到FLR的转化 by Werner Beukes 14 第一个REST 操作 - 定制Header by Scott Roth 14 vscode 新 routines 没有显示 by Paul Price 14 显示 %GlobalCharacterStream by Rochdi Badis 13 显示所有英文社区问题 » 显示所有中文社区问题 »
文章
Qiao Peng · 四月 25, 2022

InterSystems互操作进阶 - 第一篇:InterSystems流程自动化与工作流引擎

InterSystems流程自动化与工作流引擎 InterSystems工作流程引擎的主要功能 2 使用InterSystems工作流程引擎 3 场景描述 3 环境配置与测试 5 任务管理 15 任务API和自定义任务用户界面 16 展望 17 15 集成平台除了集成业务系统,打通数据与业务流程外,另一个核心的功能就是流程自动化(BPA)。 流程自动化涉及几个重要的特性: 流程建模 流程协同 决策自动化 低代码工作流程自动化 任务协同与任务管理 其中第4和5点都是和工作流程相关的。 什么是工作流程(Workflow)?它和业务流程(Business Process)有何区别?为何集成平台要涉及对工作流程的管理? 工作流程是对人工工作任务的流程及其各操作步骤之间业务规则的抽象、概括描述。所以它针对的是人工工作任务,而非业务系统的接口。业务流程与工作流不同,业务流程描述的是特定的业务在各个IT系统间和人工任务间的流程过程和业务抽象。也就是说业务流程范围比工作流程大,是包括工作流程的。 为何要在集成平台里提供工作流程建模和管理的能力?其实医院的所有业务系统都是执行人工任务的,例如医生在HIS中给患者录入诊断、下达医嘱。但并非所有的人工任务和流程在现有的业务系统中都有,例如越来越多的辅助决策系统会提供给医护人员决策建议,这些建议需要医护人员确认才能被采纳。这些辅助决策系统需要被集成平台持续集成:拿到辅助决策的上下文数据,并实时反馈决策建议给业务系统。但它的决策建议缺很难集成进业务系统的工作流程中,这涉及对业务系统的改造 – 改造现有业务系统的流程和用户界面,时间和费用成本高昂。随着辅助决策使用的范围与深度的扩大,通过改造业务系统以纳入对不断涌现的辅助决策支持内容变得越发难以为继。 工作流程引擎可以帮助解决这样的需求,快速满足业务流程优化和再造的需要,创造持续集成的价值。 InterSystems工作流程引擎的主要功能 InterSystems IRIS数据平台、Health Connect医疗集成平台和Ensemble集成平台都内建有工作流引擎。工作流程引擎具有以下功能: 任务角色和用户管理 – 对工作任务的角色定义和角色用户的管理 任务抽象与建模 – 对工作任务的上下文数据模型和任务动作的建模 任务列表 – 对任务进行管理的 任务分配 – 对工作任务进行分配与管理,例如按什么顺序分配任务?任务退回后如何重分配? 任务流程建模和自动化 – 通常工作流程是业务流程的一部分,按业务流程图建立工作流程模型,并自动化执行 任务门户 – 提供给用户的任务界面,用以查看、接受、执行或退回任务 任务API – 提供给第三方系统用以集成的任务查询、接受、执行、退回的API InterSystems数据平台提供了一个针对工作任务的标准业务操作类 -EnsLib.Workflow.Operation,将这个业务操作加入到业务流程即可。它有对应的任务请求消息 –EnsLib.Workflow.TaskRequest 任务响应消息 - EnsLib.Workflow.TaskResponse。这些类都无需修改,直接使用。 使用InterSystems工作流程引擎 场景描述 我们以一个简化的示例为例,说明如何使用工作流。这个示例不需要写代码,完全通过图形化工具和配置工具完成。场景如下: 医生通过医生站下达药嘱后,药嘱发送给药房系统。现在医院上了一套基于机器学习的药品知识库,通过患者的年龄信息、诊断和药嘱,判断药嘱是否有风险。但药房系统尚无法与药品知识库做流程集成,因此我们用InterSystems工作流来做对药剂师的药嘱风险进行提示。整体业务流程图如下: 医生站会发出HL7 V2的药嘱消息OMG_O19,药房系统也接受HL7 V2的药嘱消息OMG_O19。而药品知识库提供服务,需要的请求消息,包含患者诊断、药嘱,并返回警告级别和警告内容。 我们的用例中,医生为控制患者血压开了美托洛尔,但患者有糖尿病,美托洛尔是β受体阻滞剂药物,会影响血糖和血脂的代谢。因此药品知识库会给出药品风险提示。 环境配置 演示环境安装和配置 初始的演示环境在这里下载。 将它导入您的IRIS或HealthConnect平台,如果还没有IRIS,可以下载免费的社区版。 导入后,会看到有Demo.BP.Workflow这个非常简单的业务流程: Production中只有一个业务服务,用来通过文件接收HL7 V2消息,默认的接收文件目录是 C:\Temp\hl7v2\,处理过的HL7文件会保存在C:\Temp\hl7v2\Archive。请配置这2个目录到你本地的可用且有权限的目录。 下载包中提供了样例HL7 V2消息文件,测试时,将其拷贝到接收文件目录即可。 现在我们增加“药剂师复核”的工作任务 向Production中增加操作,弹出页面中: 类名称 选择 EnsLib.Workflow.Operation 操作名称 可以填写“药剂师” 自动创建角色 选择 是 。这样系统会自动检查任务角色名称,如果没有“药剂师”任务角色,会自动帮我们创建 修改业务流程,增加对药剂师角色的任务流程调度 将“待实现药剂师任务”的<empty>流程节点删除,并在原节点上增加“调用(<call>)”流程节点。选择目标为“药剂师”业务操作;取消选中“异步”;给它的名称设置为“提示药剂师药品风险”。 配置药剂师任务 4.1配置任务请求消息 – 应选择EnsLib.Workflow.TaskRequest。这个消息中有这些属性: %Actions:字符串类型,用来让用户执行的操作,如果有多个操作,用逗号分隔。这里我们给药剂师二个操作选项:"取消药嘱,忽略提示"。 %Subject: 字符串类型,任务的主题。今后可用于任务的分析、分配。这里我们设置为"药嘱风险处理"。 %Message:字符串类型,任务的描述。这里我们不赋值。 %Priority: 整数型,任务优先级,1为最高,默认值为3。我们将任务优先级设置为药品风险级别: context.DrugAlertLevel。 %UserName:字符串类型,用于指定任务分配到的具体用户。这里我们计划分配给角色,而不是具体的用户(药剂师),因此不用赋值。 %Title:字符串类型,任务的名称。它和主题不同,是任务的具体名称。这里我们不赋值。 %TaskHandler:字符串类型,任务句柄,设置为响应消息的类名。不用设置。 %Command: 字符串类型,用于向任务句柄传递参数。不用设置。 %FormTemplate: 字符串类型,用于设置用户自定义任务界面的CSP网页名。不用设置。 %FormFields: 字符串类型,用于设置任务用户界面的显示项目名称,多个显示项目名称间用逗号分隔。我们需要显示患者姓名、药品名称、患者诊断、药品风险级别和药品风险信息,设置为"患者姓名,药品名称,患者诊断,药品风险级别,药品风险"。 %FormValues:字符串数组类型,对应%FormFields每个显示项目的值。%FormValues的下标(Key)就是对应的%FormFields的每个显示项目的名称。 其中Key为"患者姓名"的数据从请求HL7消息的PID段的PatientName字节获取,因此值设置为request.{PIDgrp.PID:PatientName}; Key为"药品名称"的数据从上下文变量context的Msg4DrugDB属性的Drug属性中获取,因此值拖拽为context.Msg4DrugDB.Drug; Key为"患者诊断"的数据从上下文变量context的Msg4DrugDB属性的Diagnoses属性中获取,因此值拖拽为context.Msg4DrugDB.Diagnoses; Key为"药品风险级别"的数据从上下文变量context的DrugAlertLevel属性中获取,因此值拖拽为context.DrugAlertLevel; Key为"药品风险"的数据从上下文变量context的DrugAlert属性中获取,因此值拖拽为context.DrugAlert。 4.2配置任务响应消息 – 应配置为EnsLib.Workflow.TaskResponse。这个消息中有这些属性: %Action: 记录了药剂师完成任务时选择了哪个操作。我们需要将它保存到上下文中。直接拖拽callresponse的%Action到context的PharmacistDecision: %Priority:任务优先级,是从任务请求消息拷贝来的。我们无需处理它。 %UserName: 记录哪个用户执行了该任务。我们需要将它保存到上下文中。 %UserTitle:记录执行该任务的用户头衔。我们无需处理它。 %UserRanking: 记录执行该任务的用户在该角色组中的排序。我们无需处理它。 %RoleName:记录执行该任务的角色名称。我们无需处理它。 %Subject:任务的主题,是从任务请求消息拷贝来的。我们无需处理它。 %Message:任务的描述,是从任务请求消息拷贝来的。我们无需处理它。 %Actions:用来让用户执行的操作,是从任务请求消息拷贝来的。我们无需处理它。 %FormTemplate: 用户自定义任务界面的CSP网页名,是从任务请求消息拷贝来的。我们无需处理它。 %FormFields: 任务用户界面的显示项目名称,是从任务请求消息拷贝来的。我们无需处理它。 %FormValues:任务用户界面的项目值。我们无需处理它。 %Status:任务状态,用于查询任务状态。我们无需处理它。 %TaskStatus: 任务状态,用于工作流引擎分配和管理任务。我们无需处理它。 添加业务流程分支,以响应药剂师不同的任务执行结果 在“提示药剂师药品风险”流程节点后面增加对任务执行结果判断,这里需要用“分支<branch>”,而不是“if” - “分支<branch>”可以返回到任何的“标签<label>”节点。 对“分支<branch>”节点,需要设置其条件和标签,在满足条件时转到标签继续执行。因此条件设置为药剂师没有选择“取消医嘱”: context.PharmacistDecision'="取消医嘱";标签选择“药房”。 编译并启动Production 祝贺大家看到这里了,主要工作已经完成,我们没有写任何一行代码、完全通过配置,已经有了如下完整的业务流程图,保存并编译它。 启动Production。 配置工作流角色与工作流用户 启动Production后,系统会自动帮助我们创建“药剂师”工作流角色。可以到管理门户>Interoperability>管理>工作流>工作流角色 确认。 现在要增加一个工作流用户。可以使用你正在使用的IRIS账户作为药剂师用户账户。在管理门户>Interoperability>管理>工作流>工作流用户 页面中选择你的IRIS账户,我这里选择的是SuperUser;并给他一个全名,然后保存。 然后将这个工作流用户加入“药剂师”工作流角色:在工作流角色管理界面点击添加,在用户名中选中刚才创建的工作流用户,其它不用选中,点击确定。现在我们有了可用于测试的工作流用户。 测试 现在我们开始测试: 8.1 检查一下Production是否处于启动状态;然后将示例HL7 V2文件拷贝到接收HL7目录,应该看到这个文件很快就消(处)失(理)了。 8.2登录到任务门户:以药剂师用户帐号登录到管理门户>Analytics>用户门户>工作流收件箱。 可以看到有一个新的“药嘱风险处理”任务,“已分配给”字段时空的,也就是说这个给药剂师角色的人物还没有分配给任何用户。 8.3 这时,我们是看不到任务详情的,但有一个“接受”按钮。点击它就会接受该任务。当任务被接受,其他用户就看不到该任务了。 现在,就可以看到任务详情了:我们设置的任务上下文信息,例如患者姓名、药品名称、药品风险提示都可以看到了。同时,页面上面有4个按钮,其中2个“取消药嘱”、“忽略提示”是我们设置给药剂师的操作。 另外2个按钮是什么? 用户接受了、或被分配了任务,但可以点击“放弃”以退回任务,这样任务又称为“未分配”状态,其他用户就可以看到它并点击“接受”以接受任务。 “保存”是用于未完成任务,但中途需要保存信息时使用。例如任务需要用户书写记录,记录书写到一半离开去忙别的事情,可以点击“保存”以保存已经书写的内容。注意,这时任务并没有完成。 8.4 现在我们让药剂师忽略药嘱风险提示,点击“忽略提示”继续发药流程。 8.5 现在让我们回顾一下完整的业务流程: 在可视化追踪中查看刚才的业务,我们可以看到业务流程按照设计,在药品知识库有提示的情况下,启动了药剂师药嘱风险决策支持任务,并在药剂师忽略提示后,将药嘱发送给药房系统。 大家可以更改一下药剂师的决策,看看流程有什么变化。 任务管理 平台管理员可以查看、分配、重分配、修改优先级和取消任务。 以管理员身份登录到管理门户>Interoperability>管理>工作流>工作流任务,可以查看包括完成的任务在内的所有任务,并可按不同的条件排序。 如果要分配任务,在“用户名”中选择要分配给的用户; 如果要调整任务优先级,选择“优先级”; 如果要取消任务,选中“是否取消”选择框,即可取消。 另外,任务管理员可以将已取消或已完成的任务重新激活。 任务API和自定义任务用户界面 前面介绍了工作流建模、使用工作流门户管理工作任务。如何使用自己的应用或界面管理工作流任务? 有几种方法: 管理门户是网页,它可以被嵌入到其它应用中。即其它应用可以直接通过单点登录,登录到管理门户进行操作。 使用InterSystems平台的任务管理API,然后自己开发任务用户界面或直接在自己的应用中调用。 我个人推荐方法2: 社区里有一篇非常棒的文章,介绍任务管理API和如何使用这些API和Angular进行自定义的任务用户界面开发。 其中任务管理API可以在此下载 自定义任务管理界面可以在此下载 展望 现在的IT应用都是“复合应用”:当今所有应用系统建设即不是原来的纯单体应用开发项目、也不是仅与其它系统整合的集成项目,而是一个复合应用项目 – 每个新业务都需要快速开发并和别的应用集成。 InterSystems工作流引擎为人工工作流程建模提供了低代码/免代码开发的支持。同时,它也赋能复合应用开发: 使用InterSystems工作流和业务流程建模、自动化机器学习引擎或第三方机器学习引擎,可以将基于机器学习的辅助决策支持整合到业务流程中,形成决策过程闭环和机器学习优化闭环。 基于InterSystems工作流,可以将传统编码开发实现的人工工作流程开发通过低代码的业务流程建模方式实现,赋能业务团队高度参与到业务流程梳理、建模与优化中;它将业务流程逻辑与用户界面分离,从而提高业务团队参与度、降低开发成本、快速满足业务进化需求、提高架构灵活性。
文章
Claire Zheng · 四月 21, 2021

InterSystems Caché系统运维培训:InterSystems Caché系统监控和性能数据采集

近日,InterSystems极客俱乐部举办了线上直播“InterSystems Caché系统运维培训”,这是系列视频之一。InterSystems中国资深售前顾问马浩讲解了“InterSystems Caché系统监控和性能数据采集”。
文章
Michael Lei · 五月 8, 2021

InterSystems IRIS 上的 COVID-19 分析

大家好! 约翰·霍普金斯大学每天都会发布有关 COVID-19 疫情的新数据。 我在部署于 GCP Kubernetes 上的 docker 中使用 InterSystems IRIS Community Edition 构建了一个[简单的 InterSystems IRIS Analytics 仪表板](http://34.77.54.254:52773/dsw/index.html#/IRISAPP/Covid19),可显示疾病爆发的关键指标。 [![](/sites/default/files/inline/images/images/screenshot_2020-03-28_12_58_33.png)](http://34.77.54.254:52773/dsw/index.html#/IRISAPP/Covid19) 这个仪表板的示例说明了如何使用 IRIS Analytics 分析 CSV 中的信息并以 InterSystems IRIS Community Edition 的形式将其部署到 GCP Kubernetes。 添加了[美国的互动式地图](http://34.77.54.254:52773/dsw/index.html#/IRISAPP/Covid19/USA.dashboard): [![](https://community.intersystems.com/sites/default/files/inline/images/images/covid_usa.gif)](http://34.77.54.254:52773/dsw/index.html#/IRISAPP/Covid19/USA.dashboard) [下一个仪表板显示时间线](http://34.77.54.254:52773/dsw/index.html#/IRISAPP/Covid19/Daily.dashboard): [![](/sites/default/files/inline/images/images/screenshot_2020-03-28_20_48_27.png)](http://34.77.54.254:52773/dsw/index.html#/IRISAPP/Covid19/Daily.dashboard) 并且可以按国家/地区筛选。 例如, 这是[在美国](http://34.77.54.254:52773/dsw/index.html#!/d/Covid19/Daily.dashboard?ns=IRISAPP&FILTERS=TARGET:*;FILTER:%5BDay%5D.%5BH1%5D.%5BMonth%5D.%26%5BNOW%5D~%5BCountryRegion%5D.%5BH1%5D.%5BCountryRegion%5D.%26%5BUS%5D): [![](/sites/default/files/inline/images/images/screenshot_2020-03-28_21_05_49.png)](http://34.77.54.254:52773/dsw/index.html#!/d/Covid19/Daily.dashboard?ns=IRISAPP&FILTERS=TARGET:*;FILTER:%5BDay%5D.%5BH1%5D.%5BMonth%5D.%26%5BNOW%5D~%5BCountryRegion%5D.%5BH1%5D.%5BCountryRegion%5D.%26%5BUS%5D) 应用程序的源代码在 [Open Exchange](https://openexchange.intersystems.com/package/covid-19-analytics) 上提供。 工作原理 演示使用 InterSystems IRIS Community Edition docker 容器运行,并通过 MDX2JSON REST API 使用 DeepSee Web 表示层公开 InterSystems IRIS BI 仪表板。 它部署在 GCP 上,使用 Google Kubernetes Engine (GKE) 运行。 **开发方式**  数据以 CSV 格式提取自[约翰·霍普金斯仓库](https://github.com/CSSEGISandData/COVID-19)。 类、多维数据集和初始数据透视通过 [Analyzethis](https://openexchange.intersystems.com/package/AnalyzeThis) 模块生成,感谢 @Peter.Steiwer! 随后使用 CSVTOCLASS 方法引入导入方法,感谢 @Eduard.Lebedyuk! 使用 DeepSee Web (DSW) 模块渲染仪表板。 IRIS BI [项目(枢轴、仪表板)](https://github.com/evshvarov/covid-19/tree/master/src/dfi)由 [ISC.DEV](https://openexchange.intersystems.com/package/ISC-DEV) 模块导出: IRISAPP> d ##class(dev.code).workdir("/irisdev/app/src") IRISAPP> d ##class(dev.code).export("*.dfi") 代码采用 [VSCode ObjectScript](https://openexchange.intersystems.com/package/VSCode-ObjectScript) 开发,感谢 @Dmitry.Maslennikov。 **为开发和部署构建 docker 镜像** 所有部署均位于 [Dockerfile](https://github.com/evshvarov/covid-19/blob/master/Dockerfile)。 我们通过 Dockerfile 构建了一个包含数据、Web 应用和模块且正确设置的镜像,然后将映像部署到 GCP Kubernetes。 这个 Dockerfile 是 [Dockerfile 模板](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Dockerfile)的修改版,[本文](https://community.intersystems.com/post/dockerfile-and-friends-or-how-run-and-collaborate-objectscript-projects-intersystems-iris)对其进行了很好的描述。 所以,我只会在新的部分停留。  17 COPY data files 在这里,我们将 CSV 文件从数据文件夹复制到容器 set pfile = "/opt/irisapp/files/covid-"_$tr($zd($h-1),"/","-")_".csv", rc=0 \ do ##class(AnalyzeThis.Generated.covid03162020).Import(,pfile,",", ,1,.rc) \ write "imported records: "_rc \ do ##class(%DeepSee.Utils).%BuildCube("covid03162020") \ 这段代码会导入最新数据并构建多维数据集。 zpm "install dsw" \ 安装 DeepSee Web。 do EnableDeepSee^%SYS.cspServer("/csp/irisapp/") \ 这会为 /csp/irisapp web 应用启用 IRIS Analytics (DeepSee)。 zn "%SYS" \ write "Modify MDX2JSON application security...",! \ set webName = "/mdx2json" \ set webProperties("AutheEnabled") = 64 \ set webProperties("MatchRoles")=":%DB_IRISAPP" \ set sc = ##class(Security.Applications).Modify(webName, .webProperties) \ if sc<1 write $SYSTEM.OBJ.DisplayError(sc) 需要这段代码来使分析 Web 应用无需凭据即可使用。 COPY irisapp.json /usr/irissys/csp/dsw/configs/ 这条命令可以帮助设置 DSW 配置。 **部署到 Kubernetes** 部署过程由 GitHub Actions 处理 - 此[工作流](https://github.com/evshvarov/covid-19/blob/master/.github/workflows/workflow.yaml)会在每次提交到仓库时处理。 GitHub 工作流使用我们在上一步构建的 Dockerfile 以及 [Terraform](https://github.com/evshvarov/covid-19/tree/master/terraform) 和 [Kubernetes](https://github.com/evshvarov/covid-19/tree/master/k8s) 设置。  该过程与 @Mikhail.Khomenko 在[这篇文章](https://community.intersystems.com/post/deploying-intersystems-iris-solution-gke-using-github-actions)中描述的过程相同。 **如何在本地运行和开发** 欢迎您运行和开发此项目或与此项目展开协作。 要在本地运行,请使用 docker: 将仓库克隆/git pull 到任意本地目录 $ git clone https://github.com/intersystems-community/objectscript-docker-template.git 在此目录中打开终端,然后运行: $ docker-compose build 运行 IRIS 容器: $ docker-compose up -d 构建并运行容器后,在以下位置打开应用程序: localhost:yourport/dsw/index.html#!/d/Covid19/Countries.dashboard?ns=IRISAPP **如何开发** 此仓库可以通过 ObjectScript 插件在 VSCode 中编码。 安装VSCode、Docker 和 ObjectScript 插件并在 VSCode 中打开文件夹。 **如何贡献** 创建[仓库](https://github.com/evshvarov/covid-19)分支,进行更改并发送拉取请求。 [观看视频了解更多信息](https://www.youtube.com/watch?v=1x0hC_MlRfg&t=4s)。 期待您的贡献! 
文章
Michael Lei · 六月 1, 2021

使用 InterSystems IRIS 实现 Data Fabric 架构

什么是 Data Fabric? “这是一套用于在公司中实施、管控、管理和执行数据操作的硬件基础架构、软件、工具和资源,功能包括跨所有数据存储平台的数据采集、转换、存储、分发、整合、复制、可用性、安全性、保护、灾难恢复、演示、分析、保存、保留、备份、恢复、归档、召回、删除、监视和容量规划,并可使应用程序的使用满足公司的数据需求”。 (Alan McSweeney) Data Fabric 是一种可利用包括多模型数据库、Analytics、AI、ESB/SOA、微服务和 API 管理在内的所有可用资源和技术创新来获取商业价值的新型数据操作方法。 Data Fabric 原则 Alan McSweeney 列出了以下 Data Fabric 使用原则: 管控、管理和控制 - 无论数据位于何处,均可掌控数据并能够有效管理和管控数据           稳定性、可靠性和一致性 - 使用通用工具和实用工具在所有数据层之间提供稳定可靠的 Data Fabric 安全性 - 符合 Data Fabric、治理自动化、合规性和风险管理方面的各项安全标准   开放、灵活和自由选择 - 能够选择和更改数据存储、访问权限和位置 自动化 - 自动化管理和维护活动、DevOps 和 DevSecOps   性能、恢复、访问和使用 - 应用程序和用户可以在需要时、根据需求以及以适用格式访问数据 一体化 - 所有组件在所有数据层上均可互操作       Data Fabric 架构 McSweeney 设计了一幅在组织内部采用 Data Fabric 的详细概念图,如下所示: 您可以看到,需要采用某些技术才能将数据输入、处理和输出操作融合到一个流程中,进而“编织”数据并为数据使用者提供业务价值。 这些元素可以概括为下图: 数据操作位于数据接收网关 (Data Intake Gateway) 中,使用 ESB 和 API 网关技术捕获、编排、转换、丰富数据,并将数据资产整合到企业数据资产中。 借助 Analytics 和 AI 处理数据操作结果,从而为数据使用者提供数据分析。 由于数据量庞大且种类繁多,以及人们对于“黄金数据”这一“获得真理的唯一渠道”的需求,因此多模型存储库同样是一个重要角色。 InterSystems IRIS 与 Data Fabric InterSystems IRIS 是一款支持在组织内部采用 Data Fabric 架构的 Data Fabric 平台,如下文所示: Data Fabric 组件        InterSystems IRIS 组件 多功能存储库   IRIS 数据库   Java、Python、.NET 和对象脚本中受支持的 SQL Relational 对象 NoSQL 到 JSON – DocDB 可以使用 MDX 多维数据集进行分析 分片支持以支持大数据(与 MongoDB 相同) 企业缓存 – ECP 通过集成总线实现的 MDM RBAC、密码学和标签 Transanalytic 和数据湖 使用 ORM 进行对象脚本的 JDBC、ODBC 或本机 SQL 访问 通过集成总线/服务总线和 API 网关实现数据接收/网关   IRIS 互操作性    REST API 和 API 管理 数据总线 - SOA、EAI、ESB 集成和 EDI 适配器 流程自动化 - BPL 和 DTL、规则 原生集成 Java、.NET 和 C Python 和 JavaScript MFT - 托管文件传输 消息、事件和 JMS 采用 MQTT/API 的物联网 数据抽取/引入、转换和加载     分析和报告实用工具   IRIS Analytics   BI/分析和 ETL (BPL/DTL) 分级面板、分析和数据透视 SQL、MDX 和 Power BI 连接器访问 报告和嵌入式报告 UIMA - 非结构化内容分析 语义和情感分析 实时或计划分析 AutoML – IntegratedML 采用 R 或 Pyhton 的 AI/机器学习 NLP - 自然语言处理 R 、Python 和对象脚本中的统计信息 数据总线和认知流 文本分析 PMML 自适应运营分析 (AtScale) 用户门户 AI 实用工具     ## 结语 InterSystems IRIS 并非简单的数据库或互操作平台,而是帮助您实现 Data Fabric 的核心角色。 如果您使用其他公司的其他解决方案,则需要购买 4 至 7 套解决方案,但使用 InterSystems,您只需要由多模型数据库、ESB/APIM、Analytics 和 AI 组成的一套解决方案即可创建 Data Fabric。 它为您提供了价格低廉、易于使用的优势。 了解详情:
公告
jieliang liu · 七月 12, 2021

InterSystems技术文章写作大赛启动!

嗨,开发者们, 你准备好迎接新的挑战了吗? 我们很高兴地宣布第一届InterSystems技术文章写作比赛: 🏆 InterSystems技术文章写作大赛 🏆 从2021年7月15日至8月15日,写一篇与InterSystems技术有关的任何主题的文章! 每个人都有奖品: 在此期间,每个在DC上发表文章的人都将获得一个特别的奖品包! 大奖: Apple iPad 参加我们的新比赛,你的内容将被超过55K的月度读者看到! 详情如下。 奖品: 1. 每个人都是InterSystems技术文章竞赛的赢家! 任何在比赛期间写文章的用户都会得到特别的奖励: 🎁 独特的开发者社区连帽衫 🎁 InterSystems 贴纸 2. 专家选择奖 – 文章将由InterSystems的专家进行评判: 🥇 一等奖: Apple iPad 128GB 🥈 二等奖: Amazon Kindle 8G Paperwhite 🥉 三等奖: Nike Utility Speed Backpack 或者另选: Raspberry Pi 4 8GB + InterSystems IRIS社区版安装包镜像 3. 开发社区奖 – 点赞最多的文章。 获胜者将有机会从以下奖品中选择一个。 🎁 Nike Utility Speed Backpack 🎁 Amazon Kindle 8G Paperwhite 谁可以参加? 任何开发者社区成员,除了InterSystems的员工。 创建一个账户! 比赛时间 📝 七月 15日 - 八月 15日: 发表关于社区和投票时间的文章。. 在这段时间内发表一篇文章。 DC成员可以用 "赞 "为发表的文章投票--在社区奖中投票。 注意:你越早发表文章,你就越有时间收集赞。 🎉 八月 16日: 获奖者名单公布。 有什么要求? ❗️ 任何在比赛期间写的文章,只要满足以下要求,就能自动参加比赛: 文章必须与InterSystems技术有关 文章必须是英文的 文章必须是100%的新文章(可以是现有文章的延续)。 文章不应抄袭或翻译。 文章大小。>超过1,000个字符 团队规模:个人(允许同一作者的多个作品)。 要写什么? ❗️ 你可以选择任何与InterSystems技术相关的技术主题。 这里有一些选择文章主题的可能领域。这些只是例子,你可以自由选择任何你想要的东西。 # 主题 细节 1 嵌入式Python简介 嵌入式Python是InterSystems IRIS的一个令人兴奋的新功能,允许开发人员用Python编写方法、SQL存储过程等。 2 来自互操作性的嵌入式Python 探索如何从互操作性中利用嵌入式Python。 3 嵌入式Python。通过语言结构进行翻译 虽然我们的目标是实现嵌入式Python的无缝集成,但还是有一些技巧和窍门可以让事情变得顺利。下划线方法、字典、列表和其他。从ObjectScript中调用Python功能的最佳方式是什么? 4 InterSystems报告设计器介绍 续写 这篇文章. 续篇应该包括: 创建目录 创建基本的报告类型,即 图表(柱状图、饼状图、线状图、仪表图、热图...)。 表(摘要和详细)。 串联表 发布报表到报表服务器 创建一个时间表 教程参考: Getting Started with InterSystems Reports 5 从互操作性/IRIS调用报告 一篇描述如何从IRIS上执行(和获得)InterSystems Reports Report的文章,该报告来自Interoperability Production。 6 使用InterSystems的地图报告 一篇描述如何用地理空间数据建立InterSystems报告的文章。HoleFoods数据集包含了交易的地点,你可以使用。 7 如何用InterSystems IRIS做CI/CD – 8 使用Kafka连接的变更数据采集 一个例子显示了如何设置Kafka Connect并通过Kafal Connect JDBC连接器导出&导入SQL数据。 9 将分析/ML应用于SQL语句索引 – 10 我最喜欢的维护任务,自动化 – 11 利用审计数据库 – 12 设置GitHub动作的三个步骤,让你的应用程序立于不败之地 – 13 IRIS实例中的OAuth2授权 – 14 在K8s上设置镜像 – 15 在IRIS分析中使用%MDX和%KPI而不是主题区域 – 16 尝试外部语言网关/与以前的编程语言网关相比 Example 17 从IAM向Kafka流式传输事件 – 18 IntegratedML演练 – 19 使用Python将请求导出到Excel – 20 将云服务与production结合起来 例如,MS Azure Cognitive Services或Amazon Rekognition。 21 Working with IKO – 22 IKO IRIS on AWS Kubernetes with Hugepages – 23 纳入IKO的备份 – 24 IKO - 创建一个有计算节点、SAM、无分片的集群 包括CPF文件来设置我们的最佳实践。 25 与ECP建立的数据科学共享工作组 有一个数据服务器,每个数据科学家的桌面上都有一个计算节点。显示数据在断开连接时可以使用,重新连接时可以同步。 26 讨论云部署的存储选项的文章(本地存储、块存储等的性能差异)和权衡(如果使用块存储,你可能不需要镜像,等等)。 – 注意:允许不同作者的同一主题的文章。 欢迎在本帖的评论中提交你的主题想法。 所以。 我们等待着你的精彩文章! 祝你们好运,让普利策的力量与你们同在! ✨
文章
Michael Lei · 五月 20, 2022

InterSystems IRIS REST API应用程序模式

本文向你推荐一些使用IRIS创建REST API应用程序的模式。 注:所有源代码在https://github.com/yurimarx/movie 类模式到REST应用 首先,请看我对创建IRIS API应用程序所需类的建议: IRISRESTApplication: CSP.REST 类会作为中央控制者来控制业务服务处理的所有REST请求和响应. BusinessService: 具有业务主题的类实现。它可以使用一个或多个持久化域类来持久化和查询业务主题要求的数据。 Persistent Domain: 管理SQL表的持久化类. 环境准备 VSCode; Docker Desktop; InterSystems ObjectScript Extension Pack. 示例应用的类图 我将创建一个电影目录应用程序来演示文章中建议的模式: Note: 感谢IRIS API 模版应用 https://openexchange.intersystems.com/package/iris-rest-api-template . 这是本教程的基础. 搭建样本应用 1. 在你的文件系统中创建一个movie文件夹。在一个新的VSCode窗口中打开这个文件夹。 2. 在movie 文件夹中创建 Dockerfile 文件来在Docker container实例中运行IRIS社区版. 内容: Docker file content ARG IMAGE=intersystemsdc/iris-community:2020.3.0.221.0-zpm ARG IMAGE=intersystemsdc/iris-community:2020.4.0.524.0-zpm ARG IMAGE=intersystemsdc/iris-community FROM $IMAGE USER root WORKDIR /opt/irisapp RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp USER ${ISC_PACKAGE_MGRUSER} COPY src src COPY module.xml module.xml COPY iris.script /tmp/iris.script RUN iris start IRIS \ && iris session IRIS < /tmp/iris.script \ && iris stop IRIS quietly 3. 在movie 文件夹中创建 docker-compose.yml 文件来让你同时运行你的docker 和其他实例 (不在本例子中, 但是从docker-compose而不是 dockerfile运行是很好的习惯。内容: Docker composer content version: '3.6' services: iris: build: context: . dockerfile: Dockerfile restart: always ports: - 51773 - 1972:1972 - 52773:52773 - 53773 volumes: - ./:/irisdev/app 4. 在movie文件夹中创建iris.script文件,在运行IRIS之前做一些操作。这个文件对于做应用程序所需的自定义终端操作非常重要,比如禁用密码过期。内容: iris.script content ;do $System.OBJ.LoadDir("/opt/irisapp/src","ck",,1) zn "%SYS" Do ##class(Security.Users).UnExpireUserPasswords("*") zn "USER" zpm "load /opt/irisapp/ -v":1:1 halt 5. 在movie文件夹中创建module.xml文件,使用ZPM安装和运行你的应用程序。这个文件对于应用程序的端点配置和安装swagger-ui(用于使用swagger文件运行和测试你的API的web应用程序)非常重要。内容: Module.xml content <?xml version="1.0" encoding="UTF-8"?> <Export generator="Cache" version="25"> <Document name="movie.ZPM"> <Module> <Name>movie</Name> <Version>1.0.0</Version> <Packaging>module</Packaging> <SourcesRoot>src</SourcesRoot> <Resource Name="dc.movie.PKG"/> <Dependencies> <ModuleReference> <Name>swagger-ui</Name> <Version>1.*.*</Version> </ModuleReference> </Dependencies> <CSPApplication Url="/movie-api" DispatchClass="dc.movie.MovieRESTApp" MatchRoles=":{$dbrole}" PasswordAuthEnabled="1" UnauthenticatedEnabled="0" Recurse="1" UseCookies="2" CookiePath="/movie-api" /> </Module> </Document> </Export> You can see CSPApplication tag, used to run the application API in the /movie-api URI and enable or disable password to consume the API. 6. 在movie文件夹中创建LICENSE文件,设置你的应用程序的许可证。内容: LICENSE content MIT License Copyright (c) 2019 InterSystems Developer Community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 7. 在movie文件夹中创建README.md文件,用markdown语言向用户记录你的应用程序。: ## movie-rest-application This is a sample of a REST API application built with ObjectScript in InterSystems IRIS. 8. 在movie文件夹内创建.vscode文件夹。在.vscode文件夹中创建settings.json文件,以配置VSCode和你的IRIS实例之间的服务器连接。内容: Settings content { "files.associations": { "Dockerfile*": "dockerfile", "iris.script": "objectscript" }, "objectscript.conn" :{ "ns": "USER", "username": "_SYSTEM", "password": "SYS", "docker-compose": { "service": "iris", "internalPort": 52773 }, "active": true }, "sqltools.connections": [ { "namespace": "USER", "connectionMethod": "Server and Port", "showSystem": false, "previewLimit": 50, "server": "localhost", "port": 32770, "askForPassword": false, "driver": "InterSystems IRIS", "name": "objectscript-docker", "username": "_SYSTEM", "password": "SYS" } ] } 9. 在movie文件夹内创建src文件夹,放置你的源代码文件夹和文件。 10. 在src文件夹内创建dc文件夹。当你建立项目到InterSystems开发者社区时,这是个传统,否则就没有必要。 11. 在dc文件夹内创建movie文件夹。这个文件夹将是你的objectscript类的文件夹。 12. 在 src\dc\movie 文件夹中创建我们的第一个类,MovieRESTApp.cls 文件。这个文件将是IRISRESTApplication类。内容: MovieRESTApp content Class dc.movie.MovieRESTApp Extends %CSP.REST { Parameter CHARSET = "utf-8"; Parameter CONVERTINPUTSTREAM = 1; Parameter CONTENTTYPE = "application/json"; Parameter Version = "1.0.0"; Parameter HandleCorsRequest = 1; XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ] { <Routes> <!-- Server Info --> <Route Url="/" Method="GET" Call="GetInfo" Cors="true"/> <!-- Swagger specs --> <Route Url="/_spec" Method="GET" Call="SwaggerSpec" /> </Routes> } ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ] { #dim %response As %CSP.Response SET tSC = $$$OK IF $$$ISERR(pStatus) { SET %response.Status = 500 SET tSC = ..StatusToJSON(pStatus, .tJSON) IF $isobject(tJSON) { SET pResult = tJSON } ELSE { SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] } } } ELSEIF pStatus=1 { IF '$isobject(pResult){ SET pResult = { } } } ELSE { SET %response.Status = pStatus SET error = $PIECE(pStatus, " ", 2, *) SET pResult = { "error": (error) } } IF pResult.%Extends("%Library.DynamicAbstractObject") { WRITE pResult.%ToJSON() } ELSEIF pResult.%Extends("%JSON.Adaptor") { DO pResult.%JSONExport() } ELSEIF pResult.%Extends("%Stream.Object") { DO pResult.OutputToDevice() } QUIT tSC } ClassMethod SwaggerSpec() As %Status { Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger) Do swagger.info.%Remove("x-ISC_Namespace") Set swagger.basePath = "/movie-api" Set swagger.info.title = "Movie API" Set swagger.info.version = "1.0" Set swagger.host = "localhost:52773" Return ..%ProcessResult($$$OK, swagger) } } 注1:该类扩展了CSP.REST,以作为REST Endpoint使用。 注2:参数chaset是用来对请求和响应进行UTF-8编码的。 注3:CONVERTINPUTSTREAM用于强制要求的内容为UTF-8,如果没有这个参数,你可能会遇到特殊拉丁字母的问题。 注4:CONTENTTYPE用于使用JSON而不是XML声明内容。 注5:HandleCorsRequest = 1是必要的,它允许你从不同于IRIS服务器的其他服务器上消费API。 注意 6: Routes用于声明每个类方法的API URI。 注7:CSP.REST类的SwaggerSpec允许你生成API swagger(API网络文档)内容。 现在你有以下的文件夹和文件: 13. 打开VSCode终端 (menu Terminal > New Terminal) 并键入: docker-compose up -d --build 这样就建立一个docker示例并运行。 14. 用Swagger-UI测试API。打开浏览器键入: http://localhost:52773/swagger-ui/index.html. 注意地址栏。 在VSCode和 IRIS 之间建立联系 1. 点击ObjectScript 栏 ( VSCode footer) 2. 在顶部选择Toogle 链接: 3. 在ObjectScript Explorer里检查链接状态 (你能看到文件夹和创建的类): Movie 目录应用的持久化类 在这个部分我们会创立持久化域的类来存储和查询业务数据.查看DBeaver图: 1. 在src\dc\movie 目录内创建文件folder模型. 2. 在model目录内创建Actor.cls 文件. 写以下内容: Class dc.movie.model.Actor Extends (%Persistent, %JSON.Adaptor) { Parameter %JSONREFERENCE = "ID"; Property actorId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; Property name As %VarString(MAXLEN = 120); Property dob As %Date; Property genre As %Integer(VALUELIST = ",1,2"); } 3. 在model 目录内创建 Movie.cls 文件,写内容: Class dc.movie.model.Movie Extends (%Persistent, %JSON.Adaptor) { Parameter %JSONREFERENCE = "ID"; Property movieId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; Property name As %VarString(MAXLEN = 120); Property releaseDate As %Date; Property duration As %Integer; Property imdb As %String(MAXLEN = 300); Property movieCategory As dc.movie.model.MovieCategory; ForeignKey MovieCategoryFK(movieCategory) References dc.movie.model.MovieCategory(); } 4. 在model 目录内创建MovieCategory.cls 文件. 写下如下内容: Class dc.movie.model.MovieCategory Extends (%Persistent, %JSON.Adaptor) { Parameter %JSONREFERENCE = "ID"; Property movieCategoryId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; Property name As %VarString(MAXLEN = 120); } 5. 在model 目录内创建Casting.cls 文件. 写下如下内容: Class dc.movie.model.Casting Extends (%Persistent, %JSON.Adaptor) { Parameter %JSONREFERENCE = "ID"; Property castingId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; Property movie As dc.movie.model.Movie; ForeignKey MovieFK(movie) References dc.movie.model.Movie(); Property actor As dc.movie.model.Actor; ForeignKey ActorFK(actor) References dc.movie.model.Actor(); Property characterName As %String(MAXLEN = 100); Index CastingIndex On (movie, actor) [ Unique ]; } 查看创建的文件: 注1: 参数 %JSONREFERENCE = "ID" 允许在JSON回复内返回ID 值. 注2: 属性actorId 作为 %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ] 和一些其他的类似的属性被用来返回class+id 到 JSON响应中去. 注3: (VALUELIST = "1,2") 设置可能的值到1或者 2。 注4: 外健 MovieFK(movie) 参考 dc.movie.model.Movie() 和类似的用来创建SQL 外键参照. 注5: 在 (movie, actor) [ Unique ]上建立索引CastingIndex和类似的用来不允许在合并On (movie 和 actor)时重复值 注6: 我使用 Camel Case 做属性名称因为这是JSON属性命名的最佳实践. 业务服务类到Classes to the Movie Catalog Application 在本节中,我们将创建具有业务逻辑的类(做持久性、查询和计算的方法)。 1. 在src/dc/movie中创建服务文件夹。 2. 在服务文件夹中创建CrudUtilService.cls文件。写下内容: CrudUtilService content Class dc.movie.service.CrudUtilService Extends %CSP.REST { Parameter CHARSET = "utf-8"; Parameter CONVERTINPUTSTREAM = 1; Parameter CONTENTTYPE = "application/json"; Parameter Version = "1.0.0"; Parameter HandleCorsRequest = 1; /// Return all the records ClassMethod GetAll(DomainClass As %Persistent) As %Status { #dim tSC As %Status = $$$OK Set rset = DomainClass.ExtentFunc() Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Write "[" if rset.%Next() { Set actor = DomainClass.%OpenId(rset.ID) Do actor.%JSONExport() } While rset.%Next() { Write "," Set actor = DomainClass.%OpenId(rset.ID) Do actor.%JSONExport() } Write "]" Quit tSC } /// Return one record ClassMethod GetOne(DomainClass As %Persistent, id As %Integer) As %Status { #dim tSC As %Status = $$$OK #dim e As %Exception.AbstractException #; Set the response header to plain text Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Set domain = DomainClass.%OpenId(id) If '$IsObject(domain) Quit ..Http404() Do domain.%JSONExport() Quit tSC } /// Creates a new record ClassMethod Create(DomainClass As %Persistent) As %Status { #dim tSC As %Status = $$$OK #dim e As %Exception.AbstractException Set domain = DomainClass.%New() Set data = {}.%FromJSON(%request.Content) $$$TOE(tSC, domain.%JSONImport(data)) $$$TOE(tSC, domain.%Save()) Write domain.%JSONExport() Set %response.Status = 204 Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Quit tSC } /// Update a record with id ClassMethod Update(DomainClass As %Persistent, id As %Integer) As %Status { #dim tSC As %Status = $$$OK #dim e As %Exception.AbstractException Set domain = DomainClass.%OpenId(id) If '$IsObject(domain) Return ..Http404() Set data = {}.%FromJSON(%request.Content) $$$TOE(tSC, domain.%JSONImport(data)) $$$TOE(tSC, domain.%Save()) Write domain.%JSONExport() Set %response.Status = 200 Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Quit tSC } /// Delete a record with id ClassMethod Delete(DomainClass As %Persistent, id As %Integer) As %Status { #dim tSC As %Status = $$$OK #dim e As %Exception.AbstractException Set domain = DomainClass.%OpenId(id) If '$IsObject(domain) Return ..Http404() $$$TOE(tSC, domain.%DeleteId(id)) Set %response.Status = 200 Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Quit tSC } } 3. 在服务文件夹中创建MovieService.cls文件。编写内容: MovieService content Class dc.movie.service.MovieService Extends %CSP.REST { ClassMethod GetAll() As %Status { Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Movie).%New()) } ClassMethod GetOne(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Movie).%New(), id) } ClassMethod Create() As %Status { Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Movie).%New()) } ClassMethod Update(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Movie).%New(), id) } ClassMethod Delete(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Movie).%New(), id) } /// Return casting from the movie ClassMethod GetMovieCasting(id As %Integer) As %Status { #dim tSC As %Status = $$$OK Set qry = "SELECT actor->name AS actorName, characterName, movie->name AS movieName FROM dc_movie_model.Casting WHERE movie = ?" Set tStatement = ##class(%SQL.Statement).%New() Set qStatus = tStatement.%Prepare(qry) If tSC'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT} Set rset = tStatement.%Execute(id) Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Set result = [] While rset.%Next() { Set item = {} Set item.actorName = rset.actorName Set item.movieName = rset.movieName Set item.characterName = rset.characterName Do result.%Push(item) } Write result.%ToJSON() Quit tSC } } 4. 在服务文件夹中创建MovieCategoryService.cls文件。编写内容: MovieCategoryService content Class dc.movie.service.MovieCategoryService { ClassMethod GetAll() As %Status { Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.MovieCategory).%New()) } ClassMethod GetOne(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.MovieCategory).%New(), id) } ClassMethod Create() As %Status { Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.MovieCategory).%New()) } ClassMethod Update(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.MovieCategory).%New(), id) } ClassMethod Delete(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.MovieCategory).%New(), id) } } 5. 在服务文件夹中创建ActorService.cls文件。编写内容: ActorService content Class dc.movie.service.ActorService { ClassMethod GetAll() As %Status { Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Actor).%New()) } ClassMethod GetOne(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Actor).%New(), id) } ClassMethod Create() As %Status { Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Actor).%New()) } ClassMethod Update(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Actor).%New(), id) } ClassMethod Delete(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Actor).%New(), id) } } 6. 在服务文件夹中创建CastingService.cls文件。编写内容: CastingService content Class dc.movie.service.CastingService { ClassMethod GetAll() As %Status { Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Casting).%New()) } ClassMethod GetOne(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Casting).%New(), id) } ClassMethod Create() As %Status { Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Casting).%New()) } ClassMethod Update(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Casting).%New(), id) } ClassMethod Delete(id As %Integer) As %Status { Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Casting).%New(), id) } } 7. 更新MovieRESTApp.cls文件,创建所有新服务类方法的路径。编写内容: MovieRESTApp updated content Class dc.movie.MovieRESTApp Extends %CSP.REST { Parameter CHARSET = "utf-8"; Parameter CONVERTINPUTSTREAM = 1; Parameter CONTENTTYPE = "application/json"; Parameter Version = "1.0.0"; Parameter HandleCorsRequest = 1; XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ] { <Routes> <!-- Server Info --> <Route Url="/" Method="GET" Call="GetInfo" Cors="true"/> <!-- Swagger specs --> <Route Url="/_spec" Method="GET" Call="SwaggerSpec" /> <!-- List all movies --> <Route Url="/movies" Method="GET" Call="GetAllMovies" /> <!-- Get a movie --> <Route Url="/movies/:id" Method="GET" Call="GetMovie" /> <!-- Get the movie casting --> <Route Url="/movies/casting/:id" Method="GET" Call="GetMovieCasting" /> <!-- Create new movie --> <Route Url="/movies" Method="POST" Call="CreateMovie" /> <!-- Update a movie --> <Route Url="/movies/:id" Method="PUT" Call="UpdateMovie" /> <!-- Delete a movie --> <Route Url="/movies/:id" Method="DELETE" Call="DeleteMovie" /> <!-- List all movie categories --> <Route Url="/categories" Method="GET" Call="GetAllMovieCategories" /> <!-- Get a movie category --> <Route Url="/categories/:id" Method="GET" Call="GetMovieCategory" /> <!-- Create new movie category --> <Route Url="/categories" Method="POST" Call="CreateMovieCategory" /> <!-- Update a movie category --> <Route Url="/categories/:id" Method="PUT" Call="UpdateMovieCategory" /> <!-- Delete a movie category --> <Route Url="/categories/:id" Method="DELETE" Call="DeleteMovieCategory" /> <!-- List all actors --> <Route Url="/actors" Method="GET" Call="GetAllActors" /> <!-- Get a actor --> <Route Url="/actors/:id" Method="GET" Call="GetActor" /> <!-- Create new actor --> <Route Url="/actors" Method="POST" Call="CreateActor" /> <!-- Update a actor --> <Route Url="/actors/:id" Method="PUT" Call="UpdateActor" /> <!-- Delete a actor --> <Route Url="/actors/:id" Method="DELETE" Call="DeleteActor" /> <!-- List all castings --> <Route Url="/castings" Method="GET" Call="GetAllCastings" /> <!-- Get a actor --> <Route Url="/castings/:id" Method="GET" Call="GetCasting" /> <!-- Create new actor --> <Route Url="/castings" Method="POST" Call="CreateCasting" /> <!-- Update a actor --> <Route Url="/castings/:id" Method="PUT" Call="UpdateCasting" /> <!-- Delete a actor --> <Route Url="/castings/:id" Method="DELETE" Call="DeleteCasting" /> </Routes> } /// List movies ClassMethod GetAllMovies() As %Status { Return ##class(dc.movie.service.MovieService).GetAll() } /// Get movie casting ClassMethod GetMovieCasting(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieService).GetMovieCasting(id) } /// Get a movie ClassMethod GetMovie(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieService).GetOne(id) } // Create a new movie ClassMethod CreateMovie() As %Status { Return ##class(dc.movie.service.MovieService).Create() } // Update a movie ClassMethod UpdateMovie(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieService).Update(id) } // Delete a movie ClassMethod DeleteMovie(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieService).Delete(id) } /// List movies categories ClassMethod GetAllMovieCategories() As %Status { Return ##class(dc.movie.service.MovieCategoryService).GetAll() } /// Get a movie category ClassMethod GetMovieCategory(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieCategoryService).GetOne(id) } // Create a new movie category ClassMethod CreateMovieCategory() As %Status { Return ##class(dc.movie.service.MovieCategoryService).Create() } // Update a movie category ClassMethod UpdateMovieCategory(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieCategoryService).Update(id) } // Delete a movie category ClassMethod DeleteMovieCategory(id As %Integer) As %Status { Return ##class(dc.movie.service.MovieCategoryService).Delete(id) } /// List actors ClassMethod GetAllActors() As %Status { Return ##class(dc.movie.service.TestActorService).GetAll() } /// Get an actor ClassMethod GetActor(id As %Integer) As %Status { Return ##class(dc.movie.service.ActorService).GetOne(id) } // Create a new actor ClassMethod CreateActor() As %Status { Return ##class(dc.movie.service.ActorService).Create() } // Update an actor ClassMethod UpdateActor(id As %Integer) As %Status { Return ##class(dc.movie.service.ActorService).Update(id) } // Delete an actor ClassMethod DeleteActor(id As %Integer) As %Status { Return ##class(dc.movie.service.ActorService).Delete(id) } /// List castings ClassMethod GetAllCastings() As %Status { Return ##class(dc.movie.service.CastingService).GetAll() } /// Get a casting ClassMethod GetCasting(id As %Integer) As %Status { Return ##class(dc.movie.service.CastingService).GetOne(id) } // Create a new casting item ClassMethod CreateCasting() As %Status { Return ##class(dc.movie.service.CastingService).Create() } // Update a casting ClassMethod UpdateCasting(id As %Integer) As %Status { Return ##class(dc.movie.service.CastingService).Update(id) } // Delete a casting ClassMethod DeleteCasting(id As %Integer) As %Status { Return ##class(dc.movie.service.CastingService).Delete(id) } /// General information ClassMethod GetInfo() As %Status { SET version = ..#Version SET fmt=##class(%SYS.NLS.Format).%New("ptbw") SET info = { "Service": "Movie API", "version": (version), "Developer": "Yuri Gomes", "Status": "Ok", "Date": ($ZDATETIME($HOROLOG)) } Set %response.ContentType = ..#CONTENTTYPEJSON Set %response.Headers("Access-Control-Allow-Origin")="*" Write info.%ToJSON() Quit $$$OK } ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ] { #dim %response As %CSP.Response SET tSC = $$$OK IF $$$ISERR(pStatus) { SET %response.Status = 500 SET tSC = ..StatusToJSON(pStatus, .tJSON) IF $isobject(tJSON) { SET pResult = tJSON } ELSE { SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] } } } ELSEIF pStatus=1 { IF '$isobject(pResult){ SET pResult = { } } } ELSE { SET %response.Status = pStatus SET error = $PIECE(pStatus, " ", 2, *) SET pResult = { "error": (error) } } IF pResult.%Extends("%Library.DynamicAbstractObject") { WRITE pResult.%ToJSON() } ELSEIF pResult.%Extends("%JSON.Adaptor") { DO pResult.%JSONExport() } ELSEIF pResult.%Extends("%Stream.Object") { DO pResult.OutputToDevice() } QUIT tSC } ClassMethod SwaggerSpec() As %Status { Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger) Do swagger.info.%Remove("x-ISC_Namespace") Set swagger.basePath = "/movie-api" Set swagger.info.title = "Movie API" Set swagger.info.version = "1.0" Set swagger.host = "localhost:52773" Return ..%ProcessResult($$$OK, swagger) } } 8. 最终项目的文件和文件夹是: 9. 访问 http://localhost:52773/swagger-ui/index.html测试你的新方法 注 1: REST路径是以/id为复数的业务主题,当我们需要将id传递给Camel 和Case的情况下,将路径传递到. 注 2: 我们使用动词GET进行查询,POST用于新记录,PUT用于更新记录,DELETE用于删除记录。 注 3: 在<Route Url="/movies/casting/:id" Method="GET" Call="GetMovieCasting" /> 我使用/casting表示第二个目的(获得Movie和Casting)。这个方法运行ToJSON(),因为它是一个动态数组([])和动态项目({})。 注 4: 我创建了 CrudUtilService ,遵循 "避免重复 "的原则,做通用CRUD方法的小工具。 谢谢观赏!