搜索​​​​

687 个结果
文章
Claire Zheng · 一月 21, 2021

InterSystems IRIS History Monitor仪表盘界面展示

大家好! 我想跟大家分享一个个人项目,该项目始于工作中的一个简单需求:“能否知道我们使用了多少个Caché许可证?” 在阅读社区的其他文章时,我发现了一篇David Loveluck写的非常棒的文章:APM——使用Caché History Monitor。 我根据David的这篇文章,开始使用Caché History Monitor并显示所有这些信息。 在面临“选择哪种很酷的技术”这个问题时,我决定使用简单而强大的CSP,这样我的客户可以认识到Caché不仅仅是MUMPS/终端。 在创建了页面以显示许可、数据库增长和CSP会话的历史记录后,我决定为System Dashboard和进程页面创建一个新设计。 我的Caché实例运行得良好。 但是,如果使用IRIS呢?根据Evgeny Shvarov的文章:在InterSystems IRIS开发存储库中使用Docker,我实现了docker技术,并把代码放到了GitHub上,现在大家只需几个步骤就可以进行尝试。 如何运行? 如要使用这里的repo进行编码,请执行以下操作: 1. 通过Clone/git命令将repo 更新到任意本地目录中: $ git clone https://github.com/diashenrique/iris-history-monitor.git 2. 打开这个目录下的终端,并运行: $ docker-compose build 3. 在项目中运行IRIS容器: $ docker-compose up -d 如何测试 打开浏览器,并转到链接:http://localhost:52773/csp/irismonitor/dashboard.csp 使用用户名_SYSTEM可以运行仪表盘dashboard和其他功能。 系统仪表盘 系统仪表盘(System Dashboard)可展示: ·许可 ·系统时间 ·应用程序错误 ·缓存过程 ·CSP会话 ·Lock Table ·日志空间 ·日志状态 ·ECP AppServer ·ECP DataServer ·编写守护进程 ·缓存效率 ·严重警告 折线图小工具每5秒绘制一个点: 系统菜单 系统进程 进程过滤器 通过使用不同的过滤器可以实现你所需的结果。也可以使用“Multiple Sort(多重排序)”,按Shift +单击列标题,甚至可以将数据网格导出到Excel! History Monitor(历史记录监控器) CSP会话和许可的History Monitor可显示三个部分的信息: ·每5分钟 ·每天 ·每小时 “Database Growth”部分只显示当日信息。历史记录页面共享以下功能: Date Range Picker(日期选择插件) 默认值为“过去7天” Chart / Data Table(图表/ 数据表) 在每个部分的右上角有两个按钮(Chart / Data Table [图表/ 数据表]) Data Table(数据表)显示创建图表所用的信息,同样可以以Excel格式下载。 Excel中显示CSP中定义的相同格式、内容和组。 缩放 所有图表都有Zoom(缩放)选项,以可视化方式显示更多详细信息。 平均值和最大值 对于“每小时”和“每天”部分,图表显示的是平均值和最大值。 平均值 最大值 希望这篇文章对您有用! 注:本文为译文,点击此处阅读原文,原文由Henrique Gonçalves Dias撰写。
公告
Nicky Zhu · 一月 8, 2021

InterSystems 系统警报和监视 (SAM) 预览版本已发布

现在,InterSystems **系统警报和监视**(简称 InterSystems _SAM_)第 1 版 (v1.0) 发布了预览版本。    InterSystems SAM v1.0 为基于 InterSystems IRIS 的产品提供现代化的监视解决方案。 其可对集群进行高级别查看,并且能够以单节点方式可视化深入探视指标,同时提供警报通知。 该第 1 个版本提供对一百多个 InterSystems IRIS 内核指标的可视化,并且用户可以根据自己的喜好扩展默认提供的 Grafana 模板。 V1.0 旨在成为简单直观的基准。 请进行尝试并向我们发送反馈,帮助我们使其变得更棒! 从版本 2019.4 开始,SAM 可以显示来自基于 InterSystems 的实例中的信息 SAM 仅以容器格式提供。 您将需要 SAM 管理器容器,以及一小组额外的开源_组件_(Prometheus 和 Grafana),它们由组合文件自动添加。 可从以下位置获取 SAM 组件和 SAM 管理器社区版 * [WRC 预览页面](https://wrc.intersystems.com/wrc/coDistPreview.csp):分别为“SAM 组件”和“SAM 管理器” * 如果您要在 docker-compose 运行之前下载,可通过外部源[SAM 组件 Github repo](https://github.com/intersystems-community/sam) & [Docker Hub 上的 SAM 管理器](https://hub.docker.com/_/intersystems-system-alerting-and-monitoring)(后一个链接可能在几个小时内不可用,但容器是可获取的)   如果您正在旅行,或偏爱通过语音收听有关什么是 SAM 方面的提问与回答,我们为您准备了以下播客: 可在[此处](https://docs.intersystems.com/sam/csp/docbook/Doc.View.cls?KEY=ASAM)找到 SAM 文档  
公告
Claire Zheng · 一月 7, 2021

如何在 InterSystems Global Masters倡导中心获得积分

大家好!InterSystems Global Masters 倡导中心与开发者社区紧密联系并不是秘密。 为开发者社区做出任何贡献都会带来 Global Masters 积分。 所以, 我们准备了一份关于如何在 Global Masters 以最佳方式获得积分的简短指南。 如何在 GLOBAL MASTERS 获得积分 在开发者社区上发布英文帖子 100 第一次在社区评论 回答一个问题 / 发表一个评论(英文) 300 30 第 1 个被标记为“已接受”的回答 1000 之后的每一个“已接收”回答 150 第5/10/25/50个“已接收”回答 4000/8000/20000/40000 翻译一篇文章 50 在 DC 上问第1/5/10/25/50个问题 500/2000 /5000 /15000/30000 在 DC 上发布第1/5/10/25/50个帖子 1500/7500/15000/40000/75000 在 Open Exchange 发布一个应用程序 800 对每一个ZPM应用积分奖励 400 在Open Exchange发布第1/5/10/25个应用程序 1000/10000/25000/75000 帖子浏览量达到750+/2000+/5000+/15000+ 600/2500/7000/20000 在开发者社区阅读一篇帖子 10 看一个视频 20 通过社交媒体分享一次(帖子/视频) 40 发布的第1/2/3/4/5 篇带“最佳实践”标签的文章 1000/3000/7000/10000/15000 在Open Exchange上您的应用第50/100/250/500/1000次下载 2500/5000/7500/12500/25000 对 InterSystems / InterSystems 产品作一次评述 2 000-3 000 邀请成员加入开发者社区 600 为您的OEX应用创建一个video 3000 *仅计算在 Global Masters 倡导中心注册后发布的帖子。 完成挑战,获得徽章并升级:Insider > Advocate > Specialist > Expert > VIP。 您的级别越高,可获得的奖励越有趣! 欢迎点击查看更多有关 Global Masters 的其他信息: 如何加入 InterSystems Global Masters Global Masters 徽章说明 Global Masters 级别说明 Global Masters 计划的变更 如果您尚未加入 InterSystems Global Masters 倡导中心,现在就开始行动吧! 欢迎在本帖评论中提出您的问题。
文章
Michael Lei · 二月 17

InterSystems IRIS – 适用于实时人工智能/机器学习的多功能通用平台

#### 实时人工智能/机器学习计算的挑战 我们将从我们在 InterSystems 数据科学实践中遇到的示例开始讲起: * “高负载”客户门户与在线推荐系统相集成。 计划是在整个零售网络层面重新配置促销活动(我们将假设使用“细分策略”矩阵而非“平面”促销活动母版)。 推荐机制会有哪些变化? 推荐机制内的数据馈送和数据更新会有哪些变化(输入数据量增加了 25000 倍)? 推荐规则生成设置会有哪些变化(生成规则的总量和“分类”呈千倍增加,因此需要将推荐规则筛选阈值缩小千倍)? * 设备健康监控系统使用“手动”方式馈送数据样本。 现在,它将连接到每秒可传输数千个过程参数读数的 SCADA 系统。 监控系统会有哪些变化(它能否应对以秒为单位的设备健康监控)? 当输入数据接收到包含数百列最近在 SCADA 系统中实现的数据传感器读数的新块时,会发生什么(是否有必要关闭监控系统以将新的传感器数据整合到分析当中,以及要关闭多久)? * 复杂的人工智能/机器学习机制(推荐、监控、预测)依赖于彼此的结果。 要调整这些人工智能/机器学习机制的功能以适应输入数据的变化,每月需要多少人工工时? 人工智能/机器学习机制在支持制定业务决策方面的总体“延迟”是多少(支持信息的刷新频率对比新输入数据的馈送频率)? 综合考虑包括上述在内的示例后,我们总结了以下因过渡到使用实时机器学习和人工智能而出现的挑战: * 我们对于自家公司的人工智能/机器学习机制的创建和适应速度(相对于形势变化的速度)是否满意? * 我们的人工智能/机器学习解决方案在支持制定实时业务决策方面的表现如何? * 我们的人工智能/机器学习解决方案能否自适应(即无需开发者介入即可继续工作)以应对数据漂移和由此产生的业务决策制定方法的变化? 本文综合概述了 InterSystems IRIS 平台在全面支持人工智能/机器学习机制部署、人工智能/机器学习解决方案装配(集成)和基于密集数据流的人工智能/机器学习解决方案训练(测试)方面的功能。 我们将关注市场研究、人工智能/机器学习解决方案实例以及我们在本文中称为实时人工智能/机器学习平台的概念方面的内容。 #### 调查内容:实时应用类型 由 Lightbend 在 2019 年面向约 800 名专业 IT 人士进行的[调查](https://www.lightbend.com/white-papers-and-reports/survey-streaming-data-future-tech-stack),结果不言自明: _图 1:实时数据的主要使用者_ 我们将引用该调查结果报告中对我们最重要的片段:“… 流式传输数据流水线和基于容器的基础架构有着并驾齐驱的增长趋势,二者相结合可应对在更快、更高效且更敏捷地交付有影响力的结果方面存在的竞争压力。 与传统的批处理相比,流式传输能够更快地从数据中提取有用信息。 它还可以及时地集成高级分析数据,例如基于人工智能和机器学习 (AI/ML) 模型的推荐,所有功能都旨在通过提高客户满意度来实现差异化竞争优势。 时间压力也会对 DevOps 团队构建和部署应用造成影响。 诸如 Kubernetes 等基于容器的基础架构可帮助常要通过快速、重复构建和部署应用以应对变化的团队化解其面对的许多效率低下和设计问题。 … 804 位 IT 专业人士提供了有关其组织内使用流式处理的应用的详细信息。 受访者主要来自西方国家/地区(欧洲占比 41%,北美占比 37%),任职于大中小型组织的人数占比大致相等。 … … 人工智能并非投机炒作。 在已于人工智能/机器学习生产应用中使用流式处理的受访者中,有 58% 的人表示明年将出现一些最大幅增长。 * 受访者一致认为人工智能/机器学习用例将于明年出现一些最大幅增长。 * 随着实时数据处理得到更大规模的利用,不仅会拓宽在不同用例中采用的广度,还会加大在现有用例中采用的深度。 * 除了人工智能/机器学习之外,物联网流水线采用者的热情也十分高昂 — 有 48% 已经整合物联网数据的人员表示,此用例将于近期出现一些最大幅增长。 … ” 这项非常有趣的调查表明,机器学习和人工智能场景是实时数据的主要使用者,这种看法已得到广泛认可。 另一个重要的收获是透过 DevOps 视角折射出的对于人工智能/机器学习的看法:我们现在已经可以断言,仍占主导地位的“基于完全已知数据集的一次性人工智能/机器学习”文化已发生转变。 #### 实时人工智能/机器学习平台概念 实时人工智能/机器学习最典型的使用领域之一是工业中的制造过程管理。 让我们以这一领域为例并考虑上述所有想法,为实时人工智能/机器学习平台的概念给出确切的定义。 使用人工智能和机器学习来满足制造过程管理的需求具备多项与众不同的特性: * 有关制造过程状况的数据会非常密集地生成:生成频率高、涉及参数广泛(SCADA 系统每秒可传输数以万计的参数值) * 有关检测到的缺陷的数据(且不说不断演化的缺陷,它们反而是稀少且偶发的数据)已知存在缺陷分类不足和定位不及时的问题(通常以人工记录的形式在纸上找到) * 从实际角度来看,模型训练和应用只有一个“观察窗口”,可反映以最近的过程参数读数作为结尾的合理移动间隔内的过程动态 这些特性使我们除了需要实时接收和基本处理来自制造过程的密集“宽带信号”之外,也需要以实时方式执行(并行)人工智能/机器学习模型应用、训练和准确率控制。 我们的模型在移动观察窗口中“看到”的“框架”在不断变化 – 基于之前某一“框架”训练的人工智能/机器学习模型在准确率方面也会发生变化。 如果人工智能/机器学习建模准确率下降(例如,“警报范数”分类误差的值超过了给定的容差边界),则应自动触发基于较新“框架”的重新训练 – 同时,在选择开始重新训练的时刻时,必须考虑到重新训练过程持续时间和当前模型版本的准确率下降速度(因为在获得“重新训练”版本的模型之前,在执行重新训练的过程期间会一直持续应用当前版本)。 InterSystems IRIS 拥有关键的平台内功能,可充分支持用于制造过程管理的实时人工智能/机器学习解决方案。 这些功能可以分为三大类: * 基于 InterSystems IRIS 平台实时运行的生产解决方案中新的或经修改的现有人工智能/机器学习机制的持续部署/交付 (CD) * InterSystems IRIS 平台的单一生产解决方案中的入站过程数据流、人工智能/机器学习模型应用/训练/准确率控制队列、围绕与数学建模环境实时交互的数据/代码/编排的持续集成 (CI) * 在使用传递自 InterSystems IRIS 平台的数据、代码和编排(“决策制定”)的数学建模环境中执行的人工智能/机器学习机制的持续训练 (CT) 将与机器学习和人工智能相关的平台功能归入上述类别并非随意而为。 我们引用了由 Google 发表的方法论[文章](https://cloud.google.com/solutions/machine-learning/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning),文中为这种分组提供了概念基础:“… DevOps 是开发和运行大规模软件系统的一种常见做法。 这种做法具有诸多优势,例如缩短开发周期、提高部署速度、实现可靠的发布。 如需获得这些优势,您需要在软件系统开发中引入两个概念: * 持续集成 (CI) * 持续交付 (CD) 机器学习系统是一种软件系统,因此类似的做法有助于确保您能够可靠地大规模构建和运行机器学习系统。 但是,机器学习系统在以下方面与其他软件系统不同: * 团队技能:在机器学习项目中,团队通常包括数据科学家或机器学习研究人员,他们主要负责进行探索性数据分析、模型开发和实验。 这些成员可能不是经验丰富的、能够构建生产级服务的软件工程师。 * 开发:机器学习在本质上具有实验性。 您应该尝试不同的特征、算法、建模技术和参数配置,以便尽快找到问题的最佳解决方案。 您所面临的挑战在于跟踪哪些方案有效、哪些方案无效,并在最大程度提高代码重复使用率的同时维持可重现性。 * 测试:测试机器学习系统比测试其他软件系统更复杂。 除了典型的单元测试和集成测试之外,您还需要验证数据、评估经过训练的模型质量以及验证模型。 * 部署:在机器学习系统中,部署不是将离线训练的机器学习模型部署为预测服务那样简单。 机器学习系统可能会要求您部署多步骤流水线以自动重新训练和部署模型。 此流水线会增加复杂性,并要求您自动执行部署之前由数据科学家手动执行的步骤,以训练和验证新模型。 * 生产:机器学习模型的性能可能会下降,不仅是因为编码不理想,而且也因为数据资料在不断演变。 换句话说,与传统的软件系统相比,模型可能会通过更多方式衰退,而您需要考虑这种降级现象。 因此,您需要跟踪数据的摘要统计信息并监控模型的在线性能,以便系统在值与预期不符时发送通知或回滚。 机器学习和其他软件系统在源代码控制的持续集成、单元测试、集成测试以及软件模块或软件包的持续交付方面类似。 但是,在机器学习中,有一些显著的差异: * CI 不再仅仅测试和验证代码及组件,而且还会测试和验证数据、数据架构和模型。 * CD 不再针对单个软件包或服务,而会针对应自动部署其他服务(模型预测服务)的系统(机器学习训练流水线)。 * CT 是机器学习系统特有的一个新属性,它主要涉及自动重新训练和提供模型。 … 我们可以得出结论,基于实时数据的机器学习和人工智能需要更为广泛的工具和更加丰富的功能(从代码开发到数学建模环境编排)、所有功能和主题领域之间更加紧密的集成、更好的人力及机器资源管理。 #### 实时场景:识别进料泵中出现的缺陷 继续以制造过程管理领域为例,我们将探讨一个已在开头引用过的实际案例:需要建立一种基于制造过程参数值流以及维护人员缺陷检测报告来实时识别进料泵中出现的缺陷的机制。 _图 2:识别出现缺陷的案例解析_ 许多类似的实际案例中都有一个共同的特点,即在考虑规律且及时地馈送数据 (SCADA) 时,还需要同时考虑偶发且不规则地检测(和记录)各种缺陷类型。 换句话说:SCADA 数据每秒馈送一次以供分析,但需要用纸笔记录缺陷并注明日期(例如:“1 月 12 日– 第三轴承区域漏油渗入泵盖”)。 因此,我们可以通过添加以下重要限制来对案例解析加以补充:我们只有一种具体缺陷类型的“指纹”(即具体缺陷类型由截至具体日期的 SCADA 数据表示 – 该特定缺陷类型没有其他示例)。 这一限制立即使我们脱离了假定有大量可用“指纹”的传统机器学习范式(监督学习)。 _图 3:细化缺陷识别案例解析_ 我们能否以某种方式“倍增”我们可用的“指纹”? 是的,可以。 泵的当前状况由其与已记录缺陷的相似度表征。 即使不运用定量方法,仅通过观察从 SCADA 系统接收到的参数值的动态,也可以了解很多信息: _图 4:泵状况动态与具体缺陷类型“指纹”_ 然而,视觉感知(至少目前)在我们动态发展的场景中并不是最合适的机器学习“标签”生成器。 我们将使用统计检验来评估当前泵状况与已记录缺陷的相似度。 _图 5:对传入数据与缺陷“指纹”应用统计检验_ 统计检验可评估一组包含制造过程参数值的记录(以“批次”形式取自 SCADA 系统)与具体缺陷“指纹”的记录相似的概率。 使用统计检验(统计相似度指数)评估的概率随后会被转换为 0 或 1,成为我们评估相似度的每组记录中的机器学习“标签”。 即,使用统计检验处理获取到的一批泵状况记录后,我们就能够 (a) 将该批次添加到人工智能/机器学习模型的训练数据集以及 (b) 评估人工智能/机器学习模型当前版本应用于该批次时的准确率。 _图 6:对传入数据与缺陷“指纹”应用机器学习模型_ 在之前的一期[在线讲座](https://youtu.be/-gyvCTBHh-0)中,我们展示并讲解了 InterSystems IRIS 平台如何将任何人工智能/机器学习机制实现为能够控制建模输出似然并调整模型参数的持续执行的业务流程。 我们实现泵场景依赖于在线讲座中介绍的完整 InterSystems IRIS 功能 – 这些功能在作为我们的解决方案一部分的 ANALYZER 流程中使用,通过自动管理训练数据集实现强化学习,取代了传统的监督学习。 我们会将在应用统计检验(相似度指数转换为 0 或 1)和当前版本的模型之后呈现“检测一致性”(即统计检验和模型基于这些记录均输出 1)的记录添加到训练数据集中。 重新训练模型时,在其验证阶段(将新训练的模型应用于自身的训练数据集,在此之前需要对该数据集提前进行统计检验),应用统计检验后“未能保持”输出 1 的记录(由于训练数据集中永远存在属于原始缺陷“指纹”的记录)将从训练数据集中移除,并基于缺陷“指纹”和数据流中的“成功”记录训练新版本模型。 _图 7:InterSystems IRIS 中人工智能/机器学习计算的机器人化_ 如果需要对通过 InterSystems IRIS 中的本地计算获得的检测准确率寻求“第二意见”,我们可以创建一个顾问流程,以使用云提供商(例如 Microsoft Azure、Amazon Web Services、 Google Cloud Platform 等)基于控制数据集重做模型训练/应用): _图 8:来自 Microsoft Azure 的“第二意见”,由 InterSystems IRIS 编排_ 我们场景的原型在 InterSystems IRIS 中实现为分析过程的代理系统,与设备(泵)、数学建模环境(Python、R 和 Julia)交互,并支持所有相关人工智能/机器学习机制的自我训练 – 基于实时数据流。 _图 9:InterSystems IRIS 中实时人工智能/机器学习解决方案的核心功能_ 基于我们的原型获得的一些实际结果: * 由模型检测到的缺陷“指纹”(1 月 12 日): * 模型检测到的原型已知“指纹”中未包含的新出现的缺陷(于 9 月 11 日检测到,而缺陷本身在两天后,即 9 月 13 日被维修队发现): 对包含多次发生相同缺陷的真实数据进行的模拟表明,我们使用 InterSystems IRIS 平台实现的解决方案可以在维修队发现问题的几日之前检测到缺陷。 #### InterSystems IRIS – 适用于实时人工智能/机器学习计算的多功能通用平台 [InterSystems IRIS](https://www.intersystems.com/isc-resources/wp-content/uploads/sites/24/InterSystems_IRIS_Data_Platform-Unified_Platform_for_Powering_Real-time_Data-intensive_Applications-Whitepaper.pdf) 是一款完整、统一的平台,可简化实时富数据解决方案的开发、部署和维护。 它提供了并发事务和分析处理能力,支持多个完全同步的数据模型(关系、分层、对象和文档),一个可集成不同数据孤岛和应用的完整的互操作性平台,以及支持批处理和实时用例的复杂结构化和非结构化分析功能。 该平台还提供了一个开放的分析环境,可将同类最佳的分析整合到 InterSystems IRIS 解决方案中,并提供灵活的部署功能以支持云和本地部署的任意组合。 由 InterSystems IRIS 平台提供支持的应用目前已在各行各业中得到广泛使用,帮助公司在战略和战术执行中获得切实的经济利益,促进明智的决策制定并消除事件、分析和行动之间的“差距”。 _图 10:实时人工智能/机器学习背景下的 InterSystems IRIS 架构_ 与上图相同,下图将新的“基础”(CD/CI/CT) 与平台工作元素之间的信息流结合起来。 可视化始于 CD 宏机制,并继续贯穿于 CI/CT 宏机制。 _图 11:InterSystems IRIS 平台人工智能/机器学习工作元素之间的信息流图_ InterSystems IRIS 中 CD 机制的基本要素:平台用户(人工智能/机器学习解决方案开发者)使用专门的人工智能/机器学习代码编辑器调整现有和/或创建新的人工智能/机器学习机制。上述代码编辑器为 Jupyter(全称:Jupyter Notebook;为简洁起见,在此编辑器中创建的文档也常被称为相同的名称)。 在 Jupyter 中,开发者可以在传输(“部署”)到 InterSystems IRIS 之前编写、调试和测试(也使用可视化表示)具体的人工智能/机器学习机制。 显然,以这种方式开发的新机制只能进行基本的调试(特别是因为 Jupyter 不处理实时数据流)– 但我们对此没有意见,因为原则上,在 Jupyter 中开发代码的主要目标是验证单独的人工智能/机器学习机制的功能。 类似地,已部署在平台中的人工智能/机器学习机制(请参阅其他宏机制)在调试前可能需要“回滚”到其“平台前”版本(从文件读取数据、通过 xDBC 而非本地表或 global(即 InterSystems IRIS 中的多维数据数组)访问数据等)。 在 InterSystems IRIS 中实现 CD 具有一项重要特性:平台和 Jupyter 之间存在双向集成关系,支持在平台内部署(利用进一步的平台内处理)Python、R 和 Julia 内容(三种语言均为各自主要开源数学建模环境的编程语言)。 也就是说,人工智能/机器学习内容开发者获得了在平台中“持续部署”其内容的能力,同时能够使用其常用 Jupyter 编辑器以及 Python、R、Julia 所提供的常用函数库,在平台外部提供基本的调试功能(必要情况下)。 继续聊聊 InterSystems IRIS 中的 CI 宏机制。 该图展示了“实时机器人化”的宏流程(一组数据结构、以数学环境语言编写的业务流程和代码段,以及以其编排的 InterSystems IRIS 原生开发语言 ObjectScript)。 宏流程的目标是:支持人工智能/机器学习机制运行所需的数据处理队列(基于实时传输到平台的数据流),对人工智能/机器学习机制的排序和“分类” (又名 “数学算法”、“模型”等 – 可根据实现细节和术语偏好采用多种不同名称)做出决策,对围绕人工智能/机器学习输出(多维数据集、表格、多维数据数组等 – 生成报告、仪表板等)的智能保持最新的分析结构。 在 InterSystems IRIS 中实现 CI 具有一项重要特性:平台和数学建模环境之间存在双向集成关系,支持在平台内执行使用 Python、R 或 Julia 在各自的环境中编写的内容并接收执行结果。 这种集成在“终端模式”(即人工智能/机器学习内容被制定为对数学环境执行标注的 ObjectScript 代码)和“业务流程模式”(即人工智能/机器学习内容被制定为使用可视化编辑器、Jupyter 或 IDE(IRIS Studio、Eclipse、Visual Studio Code)的业务流程)下均适用。 需要使用 CI 层内的 IRIS 和 CD 层内的 Jupyter 之间的链接指定在 Jupyter 中编辑业务流程的可用性。 本文将进一步提供与数学建模环境相集成的更为详细的概述。 我们认为此时完全有理由向您说明,平台中提供了将人工智能/机器学习机制(源自“持续部署”)“持续集成”到实时人工智能/机器学习解决方案中所需的所有工具。 最后要聊到的是至关重要的宏机制:CT。 没有它,就不会存在人工智能/机器学习平台(即便可以通过 CD/CI 实现“实时”)。 CT 的本质是平台能够在数学建模环境的会话中直接操作机器学习和人工智能的“工件”:模型、分布表、向量/矩阵、神经网络层等。 在大多数情况下,这种“互操作性”体现于在环境中创建上述工件(例如,对于模型,“创建”包括模型规范及其参数的后续评估,即所谓的模型“训练”),对工件进行应用(对于模型:借助目标变量的“建模”值进行计算 – 预测、类别指定、事件概率等),以及对已经创建的和应用的工件进行改进 (例如,通过根据模型的性能重新定义模型的输入变量以便提高预测准确率,作为一种可行选项)。 CT 角色的关键属性是它对 CD 和 CI 现实的“抽象”:CT 可以在具体环境中存在的限制下使用人工智能/机器学习解决方案的计算和数学细节来实现所有工件。 将由 CD 和 CI 负责“提供输入数据”和“交付输出”。 在 InterSystems IRIS 中实现 CT 具有一项重要特性:使用上述与数学建模环境的集成时,平台可以从其编排的数学环境内的会话中提取工件,并且(最重要的是)将它们转换为平台内数据对象。 例如,刚刚在 Python 会话中创建的分布表可以(无需暂停 Python 会话)传输到平台中作为 global(InterSystems IRIS 中的多维数据数组),并进一步重用于在不同的人工智能/机器学习机制下的计算(使用不同环境的语言实现,如 R),或者作为虚拟表。 另一个示例:与模型的“例程”功能并行(在 Python 会话中),它的输入数据集使用“自动机器学习”进行处理 – 自动搜索优化的输入变量和模型参数。 与“例程”训练一起,生产模型可以实时接收“优化建议”,以根据调整后的输入变量集、调整后的模型参数值(不再是 Python 训练的结果,而是作为其“替代”版本的训练结果,例如使用 H2O 框架),使整个人工智能/机器学习解决方案能够以自主方式处理输入数据和建模对象/流程中不可预见的漂移。 我们现在将以现有原型为例,深入了解 InterSystems IRIS 的平台内人工智能/机器学习功能。 在下图中,在图像的左侧部分,我们看到了实现 Python 和 R 脚本执行的业务流程的片段。 在中央部分,我们看到了执行这些脚本后的 Python 和 R 的相应可视化日志。 接下来是两种语言的内容示例,在各自环境中执行。 右侧为基于脚本输出的可视化。 右上角的可视化使用 IRIS Analytics 开发(数据从 Python 传输到 InterSystems IRIS 平台,并使用平台功能呈现在仪表板中),右下角所示为直接在 R 会话中获取并从中传输到图形文件的内容。 重要说明:所讨论的业务流程片段在此原型中负责基于从设备模拟器流程实时接收的数据进行模型训练(设备状况分类),该流程由监控分类模型性能的分类准确率监控流程触发。 文中会进一步讨论将人工智能/机器学习解决方案实现为一组交互式业务流程(“代理”)。 _图 12:在 InterSystems IRIS 中与 Python、R 和 Julia 的交互_ 平台内流程(又称 “业务流程”、“分析过程”、“流水线”等,具体取决于上下文)可以编辑,首先是使用平台中的可视化业务流程编辑器,所用方式可同时创建流程图及其相应的人工智能/机器学习机制(代码)。 我们所说的“创建人工智能/机器学习机制”是指从一开始就进行混合(在流程级别):使用数学建模环境的语言编写的内容与使用 SQL (包括 [IntegratedML](https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GIML) 扩展程序)、InterSystems ObjectScript 以及其他支持的语言编写的内容相邻。 此外,平台内范式以嵌入片段集的形式(如下图所示)为“绘制”流程提供了广泛的功能,有助于高效地构建有时相当复杂的内容,避免视觉组合中的“随机失活” (“非可视化”方法/类/过程等)。 即,在必要情况下(可能在大多数项目中),可以采用可视化的自文档格式实现整个人工智能/机器学习解决方案。 请您注意下图中心部分,该部分展示了“更高级的嵌入向量层”,并表明除了这样的模型训练(使用 Python 和 R 实现)之外,还有针对训练模型的所谓 ROC 曲线分析,可对其训练质量进行视觉(和计算)评估 – 该分析使用 Julia 语言实现(在其各自的 Julia 环境中执行)。 _图 13:InterSystems IRIS 中的视觉人工智能/机器学习解决方案组合环境_ 如前所述,已实现的平台内人工智能/机器学习机制的初始开发和(在其他情况中)调整将在平台外部的 Jupyter 编辑器中执行。 在下图中,我们可以找到一个编辑现有平台内流程的示例(与上图中的流程相同)– 这就是其模型训练片段在 Jupyter 中的外观。 Python 语言的内容支持在 Jupyter 中编辑、调试、查看内嵌计算图。 更改(如果需要)可以立即复制到平台内流程,包括其生产版本。 同样,新开发的内容也可以复制到平台(自动创建一个新的平台内流程)。 _图 14 在 InterSystems IRIS 中使用 Jupyter Notebook 编辑平台内人工智能/机器学习机制_ 平台内流程的编辑不仅可以使用可视化或笔记本格式执行,还可以使用“完整”的 IDE(集成开发环境)格式执行。 IDE 为 IRIS Studio(原生 IRIS 开发工作室)、Visual Studio Code(VSCode 的 InterSystems IRIS 扩展程序)和 Eclipse(Atelier 插件)。 在某些情况下,开发团队可以同时使用全部三种 IDE。 下图展示了在 IRIS Studio、Visual Studio Code 和 Eclipse 中编辑完全相同流程的示例。 内容的任何部分都完全可以编辑:Python/R/Julia/SQL、ObjectScript 和业务流程元素。 _图 15:在各种 IDE 中编辑 InterSystems IRIS 业务流程_ 在 InterSystems IRIS 中使用业务流程语言 (BPL) 组合和执行业务流程的方法值得特别提及。 BPL 允许在业务流程中使用“预先配置的集成组件”(活动)– 确切地说,这让我们有权声明 IRIS 支持“持续集成”。 预配置的业务流程组件(活动和活动之间的链接)对于装配人工智能/机器学习解决方案而言是极其强大的加速器。 不仅用于装配:由于活动及其链接,在不同的人工智能/机器学习机制之上引入了“自主管理层”,能够根据具体情况做出实时决策。 _图 16:InterSystems IRIS 平台中用于持续集成 (CI) 的预配置业务流程组件_ 代理系统(又名 “多代理系统”)的概念在机器人化领域被广泛接受,InterSystems IRIS 平台通过其“生产/流程”结构为其提供有机支持。 除了使用整体解决方案所需的功能“武装”每个流程的无限能力之外,“代理”作为平台内流程家族中的一员,能够为非常不稳定的建模现象(社会/生物系统的行为, 实施部分观察的制造过程等)创建高效的解决方案。 _图 17:在 InterSystems IRIS 中以业务流程代理系统形式运行的人工智能/机器学习解决方案_ 现在继续概述 InterSystems IRIS 平台,我们将向您展示包含适用于所有实时场景类别的解决方案的应用领域(我们在之前的一期[在线讲座](https://youtu.be/N6tN48hCnE4)中提供了对一些基于 InterSystems IRIS 的平台内人工智能/机器学习最佳做法的十分详细的发现) 。 紧接上图,我们在下面提供了一幅更具说明性的代理系统图。 在该图中,完全相同的原型显示了其四个代理流程以及它们之间的交互: GENERATOR – 模拟设备传感器的生成数据;BUFFER – 管理数据处理队列;ANALYZER – 执行机器学习;MONITOR – 监控机器学习质量以及在有必要重新训练模型时发出信号。 _图 18:在 InterSystems IRIS 中以业务流程代理系统形式构成的人工智能/机器学习解决方案_ 下图展示了不同机器人化原型(文本情感分析)在一段时间内的运行。 上半部分 – 模型训练质量指标演变(质量提高),下半部分 – 模型应用质量指标和重新训练(红条)的动态。 正如所见,该解决方案显示出有效且自主的自我训练,同时继续以所需的质量水平运行(质量指标值保持在 80% 以上)。 _图 19:基于 InterSystems IRIS 平台的持续(自)训练 (CT)_ 我们之前已经提到过“自动机器学习”,在下图中,我们将以另一个原型为例提供有关此功能的更多详细信息。 在业务流程片段图中,我们看到了在 H2O 框架中启动建模的活动,以及该建模的结果(与其他“手工”模型相比,获得的模型在 ROC 曲线方面具有明显优势,以及自动检测原始数据集中可用变量中“最具影响力的变量”)。 这里的一个重要优势是“自动机器学习”可节省时间并提供专家资源:我们的平台内流程可以在半分钟内交付专家可能需要一周到一个月时间才能完成的工作(确定和证明最佳模型)。 _图 20:在基于 InterSystems IRIS 平台的人工智能/机器学习解决方案中嵌入的“自动机器学习”_ 下图“直击高潮”,同时也很好地将有关各类实时场景的故事推向尾声:在此提醒您,尽管 InterSystems IRIS 可提供所有平台内功能,但在其编排下训练模型并非强制要求。 该平台可以接收来自在非平台编排工具中训练的模型的外部来源的所谓 PMML 规范,然后自其导入 [PMML 规范](https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=APMML)之时起继续实时应用该模型。 请务必记住,尽管大多数最广泛使用的人工智能/机器学习工件都支持,但并非每个给定的人工智能/机器学习工件都可以解析为 PMML 规范。 因此,InterSystems IRIS 是一种开放的平台,对其用户而言完全不存在“平台奴役”情况。 _图 21:InterSystems IRIS 平台中基于 PMML 规范的模型应用_ 让我们聊聊 InterSystems IRIS 平台的其他优势(为了更好地说明,请参考制造过程管理),这些优势对于人工智能和机器学习的实时自动化非常重要: * 强大的集成框架,可与任何数据源和数据使用者(SCADA、设备、MRO、ERP 等)互操作 * 内置多模型数据库管理系统,用于无限量制造过程数据的高性能混合事务和分析处理 (HTAP) * 用于将人工智能/机器学习机制持续部署到基于 Python、R、Julia 的实时解决方案的开发环境 * 用于持续集成到人工智能/机器学习机制的实时解决方案和(自)训练的自适应业务流程 * 用于制造过程数据和人工智能/机器学习解决方案输出可视化的内置商业智能功能 * API 管理,可将人工智能/机器学习输出提供给 SCADA、数据集市/仓库、通知引擎等。 在 InterSystems IRIS 平台中实现的人工智能/机器学习解决方案可轻松适应现有的 IT 基础架构。 得益于高可用性和灾难恢复配置支持,以及在虚拟环境、物理服务器、私有云和公共云、Docker 容器中的灵活部署能力,InterSystems IRIS 能够有效保障人工智能/机器学习解决方案的可靠性。 也就是说,InterSystems IRIS 确实是实时人工智能/机器学习计算的多功能通用平台。 我们平台的多功能特质在实际应用中得到了证明:对实现计算的复杂性实际上毫无限制;InterSystems IRIS 能够结合(实时)执行不同行业的场景;具有出色的适应性,能够提供满足用户具体需求的任何平台内功能和机制。 _图 22:InterSystems IRIS — 适用于实时人工智能/机器学习计算的多功能通用平台_ 为了与对本文感兴趣的读者进行更加具体的对话,我们建议您继续与我们进行“实时”交流。 我们将随时提供支持,制定与贵公司具体情况相吻合的实时人工智能/机器学习场景,运行基于 InterSystems IRIS 平台的协作原型设计,设计和执行路线图以在您的制造及管理过程中实现人工智能和机器学习。 我们人工智能/机器学习专家团队的联系电子邮件:。
文章
Michael Lei · 五月 15

InterSystems IRIS最佳实践---在TLS/SSL中使用操作系统的证书库

有一个简单的新方法可以在Windows和Mac上的InterSystems IRIS 2019.1(和2018.1.2)的SSL/TLS配置中添加证书授权(CA)证书。 你可以通过输入以下内容要求IRIS使用操作系统的证书存储。 %OSCertificateStore 在 "包含受信任证书颁发机构X.509证书的文件 "栏中输入:%OSCertificateStore。 这里有一张如何在门户中这样做的图片: 这里有一个描述这个问题的文档链接。 它在 "包含受信任的证书颁发机构证书的文件 "的选项列表中。 这就是你需要做的所有事情! 现在,这个配置将接受由操作系统证书库中列出的任何CA颁发的证书。
公告
Michael Lei · 五月 16

DBeaver 官方支持 InterSystems IRIS

我们很高兴地宣布,从7.2.4版本开始,DBeaver已经支持开箱即用InterSystems IRIS的。 你不需要再手动配置它,只要在连接列表中找到IRIS的图标即可。 所有必要的字段都已填写。但是,请不要忘记输入你的用户名和密码。 默认情况下,InterSystems的IRIS驱动程序不包括在DBeaver中。对于第一次连接,DBeaver建议从InterSystems的官方GitHub仓库下载驱动程序。这个驱动程序将被用于所有进一步的连接。 目前的版本不包含IRIS的具体功能,但所有主要的DBeaver功能都将适用于你的数据库。 如果你认为可以添加其他重要的东西,请让我们知道。
文章
Michael Lei · 六月 9

InterSystems 最佳实践系列之自定义业务服务 Business Services

业务服务Business Service/BS是能够支持我们从外部数据来源获取数据强大的组件,在在大多数情况下,内置的现成组件就已经可以完成这项工作,但有时候我们还是需要写编码来自定义业务服务。在这样做的时候,有一些最佳实践供大家参考。 精益求精--业务服务的代码应该是最小化处理。这是由于如果在业务服务中发生任何错误,将不发送任何消息,从而将不创建任何跟踪。这使得它很难进行故障排除。相反,要尽可能快地完成Ensemble消息,并将其传递给适当的目标。有些人认为,如果有一个流进来,Ensemble消息应该包括一个流属性,然后由一个业务流程来解析这个流。(见文档中的例子3)还有人说,只要包括良好的错误检查,最小的处理就可以了。在这两种情况下,请记住,数据转换是存在的,可以在业务流程中使用,以便对该数据做进一步的翻译。这些转换不应该被从业务服务中调用。(参见文档中的示例1)。 可配置的目标:--在大多数情况下,业务服务的代码应该是一个可配置的目标,而不是将其硬编码到业务服务中。要做到这一点,你可以在业务服务类中创建一个名为TargetConfigNames的属性,其类型为Ens.DataType.ConfigName,使用SETTINGS参数并将此设置放在配置页上。 虽然这个属性不需要被命名为TargetConfigNames--但使用该名称与HL7组件中使用的内置设置相一致,这样做可以保持组件内的一致性。使用上面的代码只允许你选择一个目标。如果你需要向多个组件发送消息,有一些选项可以使这个设置成为多选的。请参考文档中的添加和删除设置,以了解更多关于如何做的内容。 你可以用下面的代码对该方法进行编码以处理多个目标: For iTarget=1:1:$L(..TargetConfigNames, ",") { Set tOneTarget=$ZStrip($P(..TargetConfigNames,",",iTarget),"<>W") Continue:""=tOneTarget $$$sysTRACE("Sending input Stream ...") set tSC = ..SendRequestAsync(tOneTarget, pRequest)} 欢迎分享更多最佳实践!
文章
Lucy Ma · 六月 9

InterSystems 最佳实践系列之 - 在DeepSee中设计有效的层级

当使用DeepSee工具来设计层级的时候,一个子级必须有且仅有一个父级。当出现一个子级对应两个父级的情况时,数据结果就有可能会不可靠。另一种情况是当两个相似的级别存在,它们的主键必须要做相应的变更以确保唯一性。我们接下来将通过两个案例来解释这两种情况是如何发生的以及如何避免。 案例1 在多个州里都会有一个城市叫做Boston。在我的样本数据里,我已经记录的与Boston对应的州有MA和Boston.NY。我的维度定义如下: 城市和州在这里都是简单的字符串格式。当构建到我的Cube中时,我会需要两个州级别成员:“MA”和“NY”,以及两个城市级别成员:“Boston”和“Boston”。为什么我需要两个Boston的城市级别成员而不是一个呢?因为一个级别成员不能有两个父级。所以我们需要创建两个分别的子级成员来对应各自的父级。遗憾的是,我们现在处于“糟糕的层级”场景,因为我们只有一个键值来对应两个不同的级别成员。 为了解决这个问题,我们需要使这个键值唯一。为了替代直接使用“城市”这个属性来作为这个级别的来源属性,我们可以使用来源表达式来将这个级别成员转化成唯一的。 这样就解决了唯一性的问题,但是会产程其他我们不想要的副作用。通过添加这样的表达式,我们可以在透视表中看到下面的结果: 这样的结果有可能是或者不是我们能够接受的显示方式。到这里,我们的键值和级别成员名称都是一样的,当然我们可以多做一点来让结果展示只显示“Boston”,并且背后只对应一个唯一键值。请阅读文档来获取更多信息。 总结一下,不同的级别成员需要唯一的键值。当子级成员拥有一个特殊键值对应了不同的父级成员,同时另一个已有的子级成员已经使用了同样的键值,那么这个键值将会被新的成员重新引用。这样等同于创建了无效层级。 案例2 Date Hierarchies are common places to see invalid hierarchies. Naturally people tend to create the following hierarchy: 日期层级经常会出现无效层级的情况。通常人们会倾向于创建下面这样的层级: 年 月 周 日 ***我这里讨论的是在DeepSee中的“年,月/年,周/年,和日/月/年”的提取功能。 众所周知,一周可以存在于两个不同的月份,或者甚至不同的年份。这里所有其他的级别(年,月,和日)都可以适用在它们的父级并且不会被拆分成两部分。当需要创建一个周次的级别成员也使用同样的模式的话,你将会看到意外的结果,归因于DeepSee引擎会横切数据树(从2020年1月3日开始追溯到到2019年第52周,即2019年12月。2020年1月3日不属于2019年12月的子数据,因此引擎会将这些数据移除)。 常见的解决方法是创建一个新的层级,只有周次级别在里面。这将保持原始层级的完整性,但是也同样支持按照周次来查询数据 。 DeepSeeButtons on Open Exchange 中生成的报告中有一个部分将会检查类似的状态,会在层级无效的时候通知你。 ***在InterSystems IRIS 2020.3和更新的版本中,DeepSeeButtons将会被包含。更多的信息可以再这里找到。***
文章
Jeff Liu · 四月 8

Kettle 中使用JDBC链接 InterSystems IRIS

使用 JDBC 链接 InterSystems : ​将IRIS jdbc 驱动拷贝到 安装文件夹/lib 下 ​自定义链接URL: jdbc:IRIS://ipAddress:superserverPort/namespace ​​自定义驱动器类名称: com.intersystems.jdbc.IRISDriver 然后就可以像其他关系型数据库使用的方式来使用Kettle。
文章
Frank Ma · 五月 24

如何轻松开始在Adaptive Analytics + InterSystems Reports中工作

让我们假设我们已经将一个数据源连接到Adaptive Analytics,创建了一个项目并在那里添加了表。 现在我们来准备Adaptive Analytics的工作。首先,我们需要从表中选择数据,使其可用于未来的报告。要做到这一点,我们需要从表的列中创建维度。创建维度通常是为了将我们的数据分解成不同的类别,例如用户住在哪个城市,或者购买是在哪个月进行的。然而,没有什么可以阻止我们从数字数据中创建维度,这样我们就可以在Intersystems Reports Designer中对它们应用函数。 创建维度的工具位于界面的右侧,如下图所示。要创建一个新的维度,右击位于 "过滤器 "(Filter)行右侧的汉堡包按钮,选择 "创建维度 "(Create Dimension),如图所示。 将出现以下窗口: 在创建了一个维度后,你可以使其具有层次性。要做到这一点,在左边表格的尺寸上双击鼠标左键,进入层次结构编辑器。 通过点击层次结构旁边的三个点,我们可以在层次结构中创建一个新的维度。在菜单中,维度可以在层次结构中向上/向下移动。由于层次结构的存在,我们可以制作不同层次的数据细节。例如,我们可以指定有多少人从国家、地区、城市访问过该网站。 你可以使用维度来创建表之间的关系。要做到这一点,你需要使用鼠标左键拖动表的所需字段,并将其放到所需的高亮维度中。链接创建窗口将出现。点击保存,我们的连接就准备好了。 除了表中的实际数据外,在Adaptive Analytics中,我们可以根据应用于特定列的各种操作创建测量值(measure)。测量值是数据的数字显示--用户数量、购买金额、观看视频的平均时间,等等。 要创建一个测量值(Measure),我们采用与维度相同的原则,但使用 "测量值 "(Measures)标签。 通过点击汉堡包按钮并选择 "添加测量值"(Add measure),我们调出以下窗口: '测量值名称'(Measure name)是将要显示在Adaptive Analytics界面的名称。 “查询名称 "(Query name)是将在Intersystems报告设计器中显示的名称。它是根据列名自动生成的,但你也可以自己设置。 '描述'(Description)是指Adaptive Analytics中可见的描述。 ”来源 "(Sources)定义了从哪张表和哪一列中获取数据用于测量。"聚合处理 "(Aggregation Handling)显示了我们对数据所使用的函数。函数的列表见下文。默认选择是"汇总"(Sum)。 “数据处理和格式化 "(Data Handling and Formatting)决定了如果测量值与未定义测量值的维度一起使用,将会发生什么。你应该把它留在默认状态。 ”在已发布的数据源中的可见性 "(Visibility in Published Data Sources)指定该测量值是否在Intersystems Reports Designer (报告设计器) 中可用。 你可以按维度分割测量值。例如,我们有一个显示平均数的测量值,我们用一年内每天的数据来计算一列的数据。如果我们把这个测量值分布在一个包含月份的维度上,我们将得到每个月的平均值。 要了解连接到Adaptive Analytics的数据中的内容,你可以使用立方体数据预览(Cube Data Preview)工具。你可以通过点击工作区左上角的标签进入它。 通过在一个轴上指定一个维度,在另一个轴上指定一个测量值,我们可以得到每个维度值的测量值。在这种情况下,下面你可以看到表格中每个日期的记录数。 在创建了所有我们需要的测量值、维度和关系之后,现在我们来发布我们的项目。要做到这一点,请到项目主页面左上角的标签上,点击 "发布 "(Publish)按钮,然后在出现的所有窗口上点击 "下一步 "(Next)按钮。 现在我们可以开始注意左边的窗口,这里有两个部分。"草稿"(Draft),我们可以在这里编辑我们的项目,"发布"(Publish),显示项目的发布版本。通过点击 "发布的项目"(Published project),选择立方体(cube),并进入其 "连接 "(Connect)标签。在这里我们可以看到所有必要的数据,以便将Intersystems Reports Designer连接到我们的项目。 我们已经学会了使用Adaptive Analytics所需要的一切。现在我们可以继续在InterSystems Reports Designer中工作了。 我需要提到的是,Intersystems Reports Designer 17.1版需要JDK 16版才能工作,它不能在以后的版本上运行。 首先,你需要安装JDBC连接到Adaptive Analytics的驱动程序。 下面是所需JAR文件的链接。JDBC驱动本身必须与服务器上使用的驱动兼容。我们使用足够老的版本,这样我们就不会因为服务器上的Hive版本比我们的老而导致错误。 为了方便起见,我们将所有必要的库收集在一个档案中,你可以从链接中下载。 https://github.com/teccod/Logi-JDBC-drivers 这些文件必须放在lib文件夹中,路径是LogiReport/Designer/lib。 启动Intersystems Reports Designer并关闭 "开始 "(Start)页面。现在你可以发现自己处于Intersystems Reports Designer的工作区。默认情况下,它会打开用户正在使用的最后一个目录或与Intersystems Reports Designer一起安装的预装目录。 进入 "文件 "(File)部分,点击 "新目录"(New Catalog);填写目录的名称、数据源的名称和文件应保存的位置。 Intersystems Reports Designer为我们创建了一个空的数据源。右键单击它并选择 "新建JDBC连接"(New JDBC connection)。 在 "Driver "一行,我们写上我们的驱动程序--org.apache.hive.jdbc.HiveDriver。 我们从Adaptive Analytics的 "连接 "(Connect)标签的JDBC字段中获取URL,并填写用户名和密码。 连接已经建立,但是项目中还没有立方体被加载到其中。右键单击 "表"(Tables),然后单击 "添加表"(Add tables),选择所需的立方体;用 "添加按钮 "(Add button)添加它们,然后按 "完成 "(Done)来完成这一过程。如果当你选择的数据方案与默认打开的方案不同时,没有显示这些表,请使用 "刷新 "(Refresh)按钮。 在添加了我们所需要的一切之后,我们在项目中拥有了可用的维度和测量值,我们几乎可以开始创建一个报告了。 为了使用可用的数据,我们必须提出一个请求。在这个请求中,我们可以对数据进行必要的限制(不显示取消的订单,不显示当前月份的数据,等等),只取我们需要的那部分数据。 要在 "主页 "(Home)或 "文件 "(File)标签上创建一个查询,选择 "新建 "(New)并选择 "查询"(Query)。我们挑选数据源,填写查询名称,打开我们的源,"表 "(Tables)并使用箭头将必要的表添加到查询中。 我们进入查询编辑器窗口(Query Editor): 在那里,通过设置必要的复选框或勾选*字段旁边的方框,选择必要的或表格中的所有字段。在 "菜单 "(Menu)项中,我们看到了几个功能,其中最有趣的是数据过滤。 在这里我们可以添加条件,这些条件将用SQL语言写在 "SELECT "语句的 "WHERE "部分(或者简单地说,就是切断指定表达式的数据的条件)。在我们的案例中,我们可以写上日期小于某个值,处于某个值的范围内,等等。 在 "查询编辑器 "(Query Editor)中,我们还可以添加计算列来丰富我们的数据。创建时可以使用的函数取决于数据源提供了哪些函数。Adaptive Analytics不提供任何函数,所以我们只能使用内置的Logi函数(这是最简单的数学和逻辑运算符)。 如果查询中有多个表,那么你可以通过用鼠标左键从一个字段拖动链接到另一个字段来设置它们之间的链接。在SQL查询代码中,这些关系将显示为WHERE table_name1.field_name = table_name2.field_name。 当你完成编辑请求后,点击 "确定 "(OK)按钮。如果有必要,你可以再创建几个带有不同过滤器或字段的查询。 现在你已经准备好创建报告了。我们将在下一篇文章中讨论其创建过程。
文章
Michael Lei · 五月 20

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方法的小工具。 谢谢观赏!
文章
Nicky Zhu · 一月 8, 2021

InterSystems 最佳实践之 Ensemble 孤立消息

在本文中,我们将讨论孤立消息。 ## 什么是孤立消息 每个消息正文都与一个保存元数据的消息标头相关联。 标头保存源配置名称、目标配置名称、创建时间、处理时间、关联的消息正文引用、会话信息、消息正文类名、消息状态等信息。 当有消息正文记录没有相应的标头记录时,这些消息正文称为孤立消息正文。 我们将讨论可能导致孤立消息正文产生的原因。 ### 仅清除标头 在清除任务设置中,**BodiesToo** 设置用于指定是否将消息正文与消息标头一起清除。 如果**关闭**此设置,清除任务将只删除消息标头,而保留消息正文。 这些消息正文将成为孤立记录,因为所引用的标头已被删除。 如果清除消息标头但保留消息正文,则管理门户将无法清除孤立消息正文。 在这种情况下,必须以编程方式清除消息正文。 ![](/sites/default/files/inline/images/purgetask_1.jpg)   请参阅有关清除任务的文档 [http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG\_purge#EGMG\_purge_basic](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG_purge#EGMG_purge_basic) ### 复杂的消息正文类(对象值属性) 当 Ensemble 清除某条消息正文时,不一定删除该消息正文的对象值属性。 具体来说,只有当其他对象是序列对象或子对象(由关系定义)时,才会删除这些对象。 对于其他对象,必须通过在消息正文类中定义删除触发器或实现 **%OnDelete()** 方法来适当地处理删除。 OnDelete 实现的示例代码 Class Sample.Address Extends %Persistent{ /// The street address. Property Street As %String(MAXLEN = 80); /// The city name. Property City As %String(MAXLEN = 80); /// The 2-letter state abbreviation. Property State As %String(MAXLEN = 2); /// The 5-digit U.S. Zone Improvement Plan (ZIP) code. Property Zip As %String(MAXLEN = 5); } Class Sample.Person Extends %Persistent{ /// Person's name. Property Name As %String [ Required ]; /// Person's Social Security number. This is validated using pattern match. Property SSN As %String(PATTERN = "3N1""-""2N1""-""4N") [ Required ]; /// Person's Date of Birth. Property DOB As %Date; /// Person's home address. Property Home As Address; /// Person's office address. Property Office As Address; ///Callback for object deletion ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private ]{ // Delete the property object references. Set tSC = $$$OK, tThis = ##class(Sample.Person).%Open(oid) If $ISOBJECT(tThis.Home) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Home.%Id()) If $ISOBJECT(tThis.Office) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Office.%Id()) Quit tSC } ///Callback/Trigger for SQL delete Trigger OnDelete [ Event = DELETE ]{ // Delete the property object references. {%%ID} holds the id of the record being deleted. Set tID={%%ID} Set tThis = ##class(Sample.Person).%OpenId(tID) If $ISOBJECT(tThis.Home) Do ##class(Sample.Address).%DeleteId(tThis.Home.%Id()) If $ISOBJECT(tThis.Office) Do ##class(Sample.Address).%DeleteId(tThis.Office.%Id()) Quit } } ### 已创建但从未发送到其他主机的消息对象 当一条消息被发送/转发到其他主机时,Ensemble 会创建一个新的消息标头,并关联相应的消息正文。 如果在业务服务/流程中创建的消息正文/对象实例已保存到磁盘/数据库,但从未在生产过程中发送到其他主机,它将没有关联的标头,并保留为孤立消息正文。 最佳实践是不创建消息正文,除非它将被转发,或者不对该对象实例调用 %Save()(在将消息放入目标配置队列之前,SendRequestSync/SendRequestAsync API 将保存该对象实例)。 这样,除非将消息正文对象发送到其他主机,否则它将不会持久化。 此问题的最常见原因是开发人员: 克隆了消息正文,且从未转发克隆的消息正文 在上下文变量 (BPL) 中创建了消息正文对象,且从未转发。 ## 孤立消息的影响 孤立消息不会被清除任务清除。 这些消息将占用磁盘空间,并且随着它们数量的增长,磁盘使用量也会成比例增加。 不仅消息正文数据使用磁盘空间,每条孤立消息正文记录的任何索引/搜索表条目也都占用磁盘空间。 ## 识别孤立消息 可以通过查询消息标头和正文来确定孤立消息是否存在。 每个消息标头都引用相应的消息正文。 消息正文对象 Id 引用存储在标头的 MessageBodyId 属性中,消息正文类名存储在标头的 MessageBodyClassName 属性中。 在 HL7 消息表中查找孤立消息的示例查询: SELECT HL7.Id  FROM EnsLib_HL7.Message HL7    LEFT JOIN Ens.MessageHeader hdr    ON HL7.Id=hdr.MessageBodyId    WHERE hdr.MessageBodyId IS NULL 上面的查询将返回所有没有相应标头的 HL7 消息。 可以将该查询修改为查询任何其他消息类型,只需替换消息正文表名即可。 ## 清除孤立消息 管理门户无法提供清除孤立消息正文的方法。 在这种情况下,必须以编程方式清除消息正文。 在 **ENSDEMO** 数据库中,类 **Demo.Util.CleanupSet** 提供了一个如何执行此操作的示例。 该例程也执行深度清除,同时处理对象属性引用。 还可以参考另一个例程来清除孤立消息,但该例程不执行深度清除,只对删除消息正文有帮助。 我在下面附上可下载源码的 github 链接: 最佳做法是始终: 1. 避免编程错误(如前面所讨论)以防止出现孤立消息 2. 只有需要正文并且知道只能以编程方式清除这些消息正文时,才将清除任务设置成关闭 BodiesToo 设置。 3. 实施关系或针对持久对象属性实现 OnDelete。 我希望本文对您构建生产环境有所帮助。 如果您有任何问题或疑虑,请联系我们。 谢谢。
公告
Claire Zheng · 七月 1

InterSystems 2022 Full Stack开发者大赛

大家好!欢迎参加InterSystems第21届开发者大赛! 🏆 InterSystems 2022 Full Stack开发者大赛 🏆 时间: 2022年6月27日-7月17日(美东时间) 奖金:$10,000 主题 💡 Full Stack 应用 💡 以InterSystems IRIS, InterSystems IRIS For Health(医疗版)或 IRIS Cloud Service为后端开发一个Full Stack解决方案。所谓的Full Stack,即通过REST API、Native API、ODBC/JDBC或嵌入式Python在InterSystems IRIS中插入、更新或删除数据的前端web或移动应用程序。 还有呢? 这次我们希望邀请开发者们以自己的专长来解决一个全球面临的挑战!我们鼓励你加入这次竞赛,提交聚焦于气候变化问题的解决方案:1) 如果您提交的应用能够解决一个与全球变暖或气候变化相关的问题,将收到一份特别奖励;2) 如果您准备并将在Open Exchange提交一个与全球变暖或气候变化相关的数据集,也会得到额外奖励。 那么,我们期待您的创新方案,共同建设一个可持续的发展的世界。用您的专长,为气候问题来制定解决方案吧! 基本要求: 有效应用程序:100%全新的Open Exchange Apps或已有的应用程序(但有显著提升)。所有参赛者/团队提交的应用程序只有经过我们团队的审核之后才会被批准参赛。 该应用可以在 IRIS Community Edition or IRIS for Health Community Edition or IRIS Advanced Analytics Community Edition上运行。 该应用需开源并在GitHub上发布。 该应用的README文件应为英文,包含安装步骤,并包含视频demo或/和应用程序如何运行的描述。 奖品 1. 专家提名奖(Experts Nomination)- 获奖者由我们特别挑选的专家团选出: 🥇 第1名 - $4,000 🥈 第2名 - $2,000 🥉 第3名 - $1,000 🌟 第4-15名- $100 2. 社区提名奖(Community Nomination)- 获得总投票数最多的应用: 🥇 第1名 - $1,000 🥈 第2名 - $750 🥉 第3名 - $500 ✨ 所有获奖者都将获得Global Masters徽章! 注意:如果同时多位参赛者获得同样的票数,均被视为优胜者,将平分奖金 关键参赛节点 🛠 应用开发、提交阶段 2022年6月27日 00:00 ( 美东时间): 竞赛启动. 2022年7月10日 23:59 ( 美东时间): 提交截止 ✅ 投票阶段 2022年7月11日 00:00 ( 美东时间): 投票开始 2022年7月17日 23:59 ( 美东时间): 投票截止 注意:在整个参赛期间(开发与投票期间),开发者可持续提升其应用 谁可以参加? 任何开发者社区的成员均可参加,InterSystems内部员工除外(InterSystems contractor员工可以参加)。还没有账号?现在来建一个! 👥 开发者可以组团 创建一个协作应用程序,组团限定人数为2-5人。 请注意,要在您的README文件中标注您的团队成员——社区用户profile 资源助力: ✓ 适用于Full Stack应用的InterSystems IRIS Docker模板: IRIS Full Stack template Basic InterSystems IRIS Docker template IRIS REST API template Native API template IntegratedML template IRIS Analytics template isc-ipm-js isc-perf-ui isc-json isc-rest isc-codetidy ✓ 在线课程: Implementing RESTful Applications ✓ 视频: REST API design and Development REST API in 5 minutes Data-Driven Web Apps ✓ IRIS初学者: Build a Server-Side Application with InterSystems IRIS Learning Path for beginners ✓ ObjectScript Package Manager (ZPM) 初学者: How to Build, Test and Publish ZPM Package with REST Application for InterSystems IRIS Package First Development Approach with InterSystems IRIS and ZPM ✓ 如何将您的APP提交给大赛: 如何在InterSystems Open Exchange上发布应用程序 如何把参赛APP提交给大赛 需要帮助? 加入InterSystems的 Discord server频道,或跟帖评论提出您的问题! 期待您的精彩提交!祝好运 👍 参与此次竞赛,您同意 遵守相关条款,请认真阅读。
文章
Michael Lei · 九月 15

InterSystems IRIS 10大功能特性

InterSystems IRIS是一个伟大的数据平台,它满足了当前市场所需的功能。在这篇文章中,你可以看到我心目中的前10大功能: 排名 特性 原因 了解更多 1 互操作性, FHIR 和物联网 商业机构之间需要持续互联和交换数据。各个业务部门之间也需要加强协作来将本增效。实现协作的最佳技术是IRIS的互操作工具包,尤其是 服务总线ESB, 集成适配器,业务流程自动化引擎,数据转化工具以及例如FHIR和MQTT等。 Link 1 Link 2 Link 3 2 API 管理器 大家通过API来消费数字资产。API需要在一个中心点管理其重用、安全、消费、资产目录、开发者生态系统和其他方面。API管理器是实现这一目标的正确工具。因此,所有的公司都有或希望有一个API管理器。 Link 3 数据分片 据预测,全球创造、捕获、复制和消费的数据总量将迅速增加,在2020年达到64.2 zettabytes。在接下来的五年里,直到2025年,全球数据创建量预计将增长到180兆字节以上。在2020年,创造和复制的数据量达到了新高(来源:https://www.statista.com/ statistics/871513/worldwide-data-created/)。在这种情况下,能够以分布式的方式处理数据(进入数据分片,如hadoop或mongodb),以提高和保持性能,对企业至关重要。另一件重要的事情是IRIS比Cache快3倍,比在AWS云上比AWS数据库更快。 Link 1 Link2 4 Python 支持 Python 是实现AI的最流行的语言,AI现在是大部分企业战略的核心,帮助企业获得更多洞见、更多生产力和降低成本. Link 1 Link 2 Link 3 5 原生APIs (Java, .NET, Node.js, Python) 和自定义扩展 PEX 美国有将近100万开放的IT职位 (source: https://www.cnbc.com/2019/11/06/ how-switching-careers-to-tech-could-solve-the-us-talent-shortage.html). 也很难找到 Object Script 开发者. 因此, 能够支持各种主流语言(Python, Java, .NET, 等.)来使用IRIS特性非常重要. Link 1 Link 2 Link 3 Link 4 Link 5 Link 6 6 自适应分析 实时分析当前的业务数据,减少建模工作,提高运行速度,支持主要的分析查看器(包括Excel)是企业战略的一个关键因素。 Link 7 云, Docker 和微服务 每个人都想要微服务架构。他们希望打破传统单体应用来创建更小、更简单、解耦的、可扩展、可复用和独立的应用项目。 IRIS 支持用户部署数据、应用和分析的微服务。 IRIS 支持数据分片, docker, kubernetes, 分布式计算, DevOps 工具和更低的 CPU/内存消耗 (IRIS 甚至支持 ARM 处理器!). 使用 IRIS API管理器,可以帮助企业实现配合业务的微服务架构。 Link 1 Link 2 Link 3 Link 4 Link 5 8 嵌入式报表 报表对企业是十分重要的。运营者和决策者要用到大量的报表,有很多报表也要提交给客户。移动端和微服务APP需要支持嵌入式报表,IRIS也支持所有这些需求。 Link 1 9 VSCode 支持 VSCode 是最流行的开发工具,InterSystems IRIS 有一套非常棒的工具来支持它。 Link 1 Link 2 Link 3 10 数据科学 使用Python, R 和一体化机器学习(自动机器学习)可以支持企业及时得到AI提供的洞见。InterSystems IRIS 包括所有这些功能。 Link 1 Link 2 Link 3
公告
Claire Zheng · 九月 19

欢迎来了解一下 InterSystems Ideas ——我们的官方反馈门户

开发者社区的同学们,大家好! 我们一直以来都有一个想法——改进收集、分析和回应开发者社区成员们的产品改进请求的过程。我们知道,我们需要一个良好的用户体验,甚至更好的内部流程,来确保收集、听取和响应最好的想法。现在,这个想法终于实现了! 我们在此向您介绍 InterSystems官方反馈门户 💡 >> InterSystems Ideas << 💡 InterSystems Ideas InterSystems Ideas是一个全新的、推动改进的渠道,您可以通过它向我们提交与InterSystems服务(文档、开发社区、全球大师等)相关的产品改进请求和想法,看看其他人提交了什么,为你喜欢的想法投票,投票给你最喜欢的,并从InterSystems获得反馈。 我们开始积极开发和推广创意门户网站InterSystems Ideas和您的创意。我们希望这可以为您提供一个公开的方式来获得我们的产品经理和社区成员的反馈。 ✅ 获得投票最多的想法会得到产品管理部门的评审。 来社区分享你的想法吧!通过投票和评论为其他想法提供贡献——投票越多,影响力越大! 点击看看创意网站 InterSystems Ideas portal!