Find

Article
· Jun 23, 2024 8m read

用不到150 行代码创建 IRIS 功能齐全的现代后端应用程序

低代码挑战

想象一下那个场景。您正在 Widgets Direct 愉快地工作,这是互联网上首屈一指的小部件和小部件配件零售商。您的老板有一些毁灭性的消息,一些客户可能对他们的小部件不太满意,我们需要一个帮助台应用程序来跟踪这些投诉。为了让事情变得有趣,他希望代码占用非常小,并挑战您使用 InterSystems IRIS 以少于 150 行代码交付应用程序。这可能吗?

免责声明:本文记录了一个非常基本的应用程序的构建,为了简洁起见,省略了安全性和错误处理等细节。该应用程序仅供参考,不得用于任何生产应用。本文使用IRIS 2023.1作为数据平台,并非所描述的所有功能在早期版本中都可用

第 1 步 - 定义数据模型

我们首先定义一个新的干净的命名空间 - 带有代码和数据数据库。虽然所有内容都可以位于 1 个数据库中,但将它们拆分以便于数据刷新。

我们的帮助台系统需要 3 个基本类:一个 Ticket 对象,它可以包含用于记录员工顾问 UserAccount 和客户联系人 UserAccount 之间交互的操作。让我们用一些基本属性来定义它们:

19 行代码,我们就有了完整的数据模型!我们将 2 个类设置为 Persistent,以便将它们保存到数据库中,并且还继承自 %JSON.Adapter,这使我们能够非常轻松地以 JSON 格式导入和导出对象。作为测试,我们在终端中设置第一个用户,保存它,然后验证 JSONExport 是否正常工作

这一切看起来都不错。老板给我们留下了一个 csv 文件,其中包含员工和客户的列表。我们可以编写一些代码来解析它并加载它,但是有更简单的方法吗?

第 2 步 - 加载数据

InterSystems IRIS 在 SQL 中提供了一个简单易用的 LOAD DATA 语句,可以轻松地从 CSV 文件加载数据,包括解析标题和重命名字段的选项。让我们用它来加载我们的用户表:

我们可以使用标题标签来提取这些数据并将其加载到数据库中,如下所示:

所有 300 行均已使用单个命令导入。这 4 行代码使我们的运行代码编写数量达到 23 行。我们可以使用基本的 SQL select 查询脚本来快速验证这些记录是否正确

现在我们有了起始数据,让我们构建一些基本的 API 来和前端连接。我们将把 API 构建可以接受 JSON 的 REST 服务。

第 3 步 - 构建 REST API

InterSystems IRIS 通过继承 %CSP.REST 类提供 REST 支持,因此我们将创建一个继承  %CSP.REST 的REST.Dispatch 类。该类由 2 个部分组成:一个 XData UrlMap,它将 URL 和 Call 映射到Method,通过 Url 调用Method。

我们的最小可行产品需要 4 项操作:检索员工或客户的用户列表、检索最后一张票、通过 ID 号检索单个票,最后创建新票。我们定义Call,然后定义Method。

GetUserList 是一个基本的嵌入式 SQL 游标,它直接以 JSON 形式输出数据。然后,我们可以使用 JSON 功能解析它,将其推送到 JSON 数组中并将其作为响应正文。我们将 Staff 变量从 URL 直接传递到方法中使用。

TicketSummary 几乎相同,但改为访问票证表

TicketSummary 是最简单的服务。我们通过 ID 获取对象,并使用内置的 %JSONExport 输出JSON。如果对象加载失败,我们会写出一个错误数据包

最后,我们的 UploadTicket 方法是最复杂的。我们必须从请求对象中读取有效票证数据,将其解析为 JSON,然后使用 %JSONImport 将其导入到 Ticket 的新实例。我们还从当前时间设置 OpenDate 和 OpenTime,而不是将日期作为输入。成功保存后,我们会显示新票证对象的 JSON 表示形式,或者如果对象保存失败,我们会返回错误。

通过这些服务,我们在总数中又添加了 60 行代码。我们现在这个应用程序总共有 89 行代码

现在,我们需要在“安全”>“应用程序”下创建一个 Web 应用程序。这应该设置为 REST 类型的应用程序,并且 Dispatch Classname 应设置为我们刚刚创建的 REST.Dispatch 类(注意,您需要向该应用程序授予适当的安全角色,以便它可以访问代码和数据)。保存后,现在可以从您定义的 URL 调用 REST 服务

我们可以调用UserList来检查

我们现在准备创建一些数据。让我们使用 REST 客户端将有效数据发送到票证创建服务。我们提供关键字、描述、顾问和联系人,然后返回我们创建的票证的 JSON,包括 OpenDate 和 TicketId

我们现在有了最小可行产品。使用我们选择的前端表单生成器,我们现在可以通过 REST 服务发送和接收票证信息。

第 4 步 - 互操作性要求

您现在仅用 89 行书面代码就构建了一个基本的票务应用程序。你的老板一定印象深刻吧?是的,但他有一些坏消息。你错过了一个要求。 Widgets Direct 在法语地区有一份特殊合同,所有用法语书写的门票必须交由 Bettie Francis 女士进行初步审核。幸运的是,您有一位同事关注了 Robert Luman 关于Python Natural Language Support  的优秀文章,并创建了一个可以接受文本示例并识别语言的 REST 服务。当文本为法语时,我们可以使用 InterSystems IRIS Interoperability 来调用此服务并自动将顾问更新为 Mme Francis 吗?

我们需要首先创建一些 Message 类,以便我们有一种方法来发送和接收我们的请求。我们需要一个包含票证 ID 和示例文本的请求,以及一个返回语言代码和描述的响应。这些将继承Ens.Request 和 Ens.Response

再写 6 行代码,我们就可以得到 95 个 LOC。我们现在需要创建我们的业务操作,它将请求发送到您同事的服务并检索答案。我们定义一个出站业务操作,其中包含服务器和 URL 的属性,并通过将它们包含在 SETTINGS 参数中来将它们公开给用户配置。如果服务器路径发生变化,这将使我们能够轻松更新请求。我们创建一个辅助方法来设置 HTTPRequest,然后使用它来调用服务并填充我们的响应

又增加了 27 行代码,代码数量就超过了 100 行,现在我们已经编写了 122 行代码。我们现在需要在 Ensemble 中设置此类。转到互操作性下的Production配置,然后按操作标题下的添加。使用类名称和显示名称设置您的业务操作

然后我们可以单击它进入“设置”,输入服务器名称和 URL 并启用该业务操作。

我们现在需要第二个业务操作,该业务操作获取票证 ID 并将顾问设置为提供的用户帐户 ID。我们需要消息和业务操作类,但在这种情况下,我们不会返回响应,业务操作将在没有反馈的情况下执行任务

另外 12 行代码使我们编写了 134 行代码。我们可以按照添加服务的相同方式将此业务操作添加到Production中,但在这种情况下,我们无需设置任何配置。

接下来,我们需要一个可以调用服务、评估响应并可以选择调用 French Advisor Operations 的路由器。我们转到互操作性>构建>业务流程并访问可视化规则生成器。我们首先设置请求和响应的上下文并添加一个调用项。我们将输入和输出设置为我们创建的消息类,然后使用请求生成器映射输入。确保未选中“异步”标志,我们希望在继续之前等待响应。

然后,我们添加一个“If”项来评估返回的语言代码。如果是“fr”,那么我们要调用 FrenchAdvisor 操作

Mme Francis 的用户 ID 为 11,因此我们设置 Call 对象以向 FrenchAdvisor 服务提供 AdvisorUpdate 消息,并使用请求构建器传递 TicketID 和 Advisor 参数的固定值 11

现在,我们可以通过单击“进程”标题下的“添加”,选择该类并为其指定一个 DisplayName“FrenchRouter”,将其添加到 Production 中。  

现在我们的路由就位了。我们只需要一个服务来扫描新票并将其发送到路由器进行处理。我们基于 SQL 适配器定义一个 Service 类,如下所示(在我们的计数中添加另外 8 行代码):

然后,我们将其添加到Production中,就像我们对业务操作和业务流程对象所做的那样。我们需要对 SQL 适配器进行一些设置。我们通过 ODBC DSN 向本地数据库提供连接详细信息,以及基本 SQL 查询,服务将使用该查询来查询 CallInterval 设置中设置的计时器上的票证。此查询与键字段名称设置配对,该设置定义查询的唯一键,并防止重新发送已发送的记录

完成此业务操作后,我们现在有了完整的Production,它将扫描新票证,将文本传递到外部服务以解析语言,并可选择根据响应重置顾问程序。让我们试试这个吧!我们首先发送一个英语请求,该请求返回为 TicketId 70。我们稍等一下,然后通过 GetTicket REST 服务访问此记录,并且顾问与原始请求相比没有变化

让我们用法语文本重复一遍

当我们请求 71 票证时,我们的顾问已更改为弗朗西斯女士,正如我们所料!我们可以通过在 Visual Trace 中查找消息并验证操作是否按预期调用来在互操作性中检查这一点。

我们现在编写了 142 行代码,并且拥有一个 InterSystems IRIS 应用程序,该应用程序可以保存数据,使用 LOAD DATA 加载数据,提供用于查看和编辑数据的基本 REST API,以及基于调用提供决策支持的高级集成引擎到外部 REST 服务。当然,没有人能要求更多吗?

第 5 步 - 要求更多:分析

您的应用程序取得了巨大成功,数据源源不断地涌入。这些宝贵的数据需要专业知识才能访问,而 Widgets Direct 的管理人员希望获得一些见解。是否可以提供对数据的交互式访问?

使用 InterSystems IRIS Analytics,我们可以轻松快速地访问高级数据操作工具。我们首先需要在我们的内部 Web 应用程序上启用分析支持:

这使我们能够针对我们的命名空间使用分析部分。首先打开 Analytics>Architect。选择新建,然后填写表单以为工单类创建分析多维数据集。

接下来,我们可以使用 Visual Builder 设置维度和基本的向下钻取列表。该视图是拖放式的。还可以使用简单的可视化构建器创建列表,以自定义用户在询问数据点时看到的内容

一旦我们有了一些基本设置,我们就可以保存、编译和构建Cube。这将设置所有索引并启用多维数据集以在分析器中进行分析。打开分析器开始处理数据。在示例中,我们可以轻松地将顾问与按所服务的联系人过滤的年度和季度层次结构进行比较。单击单元格后,可以按下双筒望远镜图标来调用您创建的深入分析列表,以进行进一步分析和导出

结论

只需 142 行代码,我们就拥有了一个基本但功能齐全的现代后端应用程序,并提供支持工具以允许应用程序间通信和高级分析。这是一个过于简化的实现,只能用作在 IRIS 中构建数据库应用程序所需的基本框架的示例。正如本文开头提到的,此代码尚未准备好投入生产,在实际使用中,开发人员应参考 InterSystems IRIS 文档和最佳实践,以确保其代码稳健、安全和可扩展(这些都不适用于此代码库) )。快乐编码!

该文章 作者 @ 来源于 https://community.intersystems.com/node/553856

Discussion (0)1
Log in or sign up to continue
Article
· Jun 23, 2024 7m read

IRISでシャドウイングの代わりにミラーリングを構成する方法

これは InterSystems FAQ サイトの記事です。
 

InterSystems IRIS では、シャドウイングは非推奨機能となりました。

こちらのトピックでは、これまでにCachéでシャドウイングを使用していたお客様に対して、IRISへの移行後に、代わりに使用できるミラーリングの構成方法をご紹介します。

ミラーリングには機能的に2つの種類があります。

1.同期ミラーによるフェールオーバー(常にデータベースが同期されて複製、障害時に自動でフェールオーバー)
2.非同期ミラー(シャドウイングと同様の機能を提供)
 - DR非同期(DR構成で利用、フェールオーバーへの昇格が可能、複製DBへの書き込み不可)
 - レポーティング非同期(データマイニング/BIアプリでの利用、複製DBへの書き込み可能)


シャドウイングに代わって、IRISでは「プライマリ・フェイルオーバー」+「非同期ミラー」でミラーリングを構成する機能を利用することができます。

以下は、シャドウイングとミラーリングのサーバ役割の対比表になります。
※ミラー構成内の1つのインスタンスを  “ミラーメンバ” または単に “メンバ” と呼びます。

シャドウイング ミラーリング
DBサーバ プライマリ・フェイルオーバーメンバ
シャドウサーバ 災害復旧 (DR) 非同期メンバ
レポーティング非同期メンバ



では、ミラーの構成手順をご紹介します。手順は以下になります。

1) それぞれのサーバでISCAgent の構成・起動
2) それぞれのサーバでMIRRORDATAネームスペース(データベース)を作成
3) 正サーバでミラーを作成し、フェイルオーバー・メンバを構成・ミラーへデータベースの追加
4) 副サーバで非同期ミラー・メンバを構成・ミラーへのデータベースの追加
 (IRIS.DATのファイル自体をコピーして複製する場合は、必ずディスマウントした状態で行ってください。)

 


今回は、各設定を管理ポータルを使用して行う方法をご紹介します。
 

【今回のサンプル・ミラー構成について】

  正サーバ(ミラー・プライマリ) 副サーバ(ミラー・非同期)
ミラー名 MIRRORSET MIRRORSET
ミラーメンバ名 MACHINEA MACHINEC
IPアドレス 192.168.2.100 192.168.2.101


1) ISCAgent の構成・起動

ISCAgent は、IRISインストール時にインストールされます。
 こちらは、IRIS起動時に開始するよう設定する必要があります。
開始/停止方法は、OSごとに異なりますのでドキュメントをご覧ください。
ISCAgent は、各ミラーメンバ上の専用ポート (既定値は 2188) を使用します。


2) MIRRORDATAネームスペース(データベース)の作成      

それぞれのサーバで、MIRRORDATAという名前の新しいネームスペースを作成し、参照するデータベースとしてMIRRORDATAデータベースをデフォルト設定の状態で作成します。 

  


3) 正サーバでミラーを作成し、フェイルオーバー・メンバを構成


1.ミラーサービスを有効にします
 管理ポータル:
 [システム管理] > [構成] > [ミラー設定] > [ミラーサービス有効]
 サービス有効 にチェックをして保存します。

 

 
2.ミラーを作成します
 管理ポータル:
 [システム管理] > [構成] > [ミラー設定] > [ミラーサービス作成] 
 [ミラー情報] セクションに以下の情報を入力して保存します。

※プライマリ-非同期ミラー構成の場合は、アービターを使用する必要はありません。

※ミラーメンバ名は、既定で $sysytem 変数の内容が設定されています。
 (<デバイス名>/<インスタンス名> 例:JP001ISJ/IRIS)
 こちらをそのまま使用するのでも構いません。


3.TESTMIRRORへMIRRORDATAデータベースを追加します。ミラーデータベース名には、MIRRORDATAを使用します

 管理ポータル:
 [システム管理] > [構成] > [システム構成] > [ローカルデータベース]
 MIRRORDATAの編集 → ミラー○○に追加

 メモ:もし、画面中に「ミラーに追加」のリンクが表示されない場合、ディスマウントを実行し、マウントし直してください。

 

※ミラーが有効なライセンスを使用していない場合、以下のようなエラーになりますのでご注意ください。
 エラー #2076: 'TESTMIRROR' のミラーメンバ情報取得中にエラーが発生しました。
 エラー情報: Failed to create InterSystems IRIS context, error = -1



4) 副サーバで非同期ミラー・メンバを構成


1.ミラーサービスを有効にします
 管理ポータル:[システム管理] > [構成] > [ミラー設定] > [ミラーサービス有効]
 サービス有効 にチェックをして保存します。
 

2.ミラーに非同期として参加します
 管理ポータル:[システム管理] > [構成] > [ミラー設定] > [非同期として参加] 
 [ミラー情報] セクションに、2) で設定した正サーバの情報を入力し、「次へ」をクリックします。

 


3.非同期メンバとして登録したいマシンの情報を指定して保存します
 今回は、非同期メンバシステムタイプ=災害復旧(DR)の構成とします。
 ※ミラーメンバ名は、既定で $sysytem 変数の内容が設定されています。こちらをそのまま使用するのでも構いません。 

 



4.非同期ミラーへデータベースの追加・キャッチアップを行います

 非同期データベースにMACHINEA(正サーバ)のバックアップファイルをリストアします。
 【補足】
 データベースファイル(IRIS.DAT)のコピーによるバックアップの場合は(=Backup.GeneralクラスのExternalFreeze()/ExternalThaw() を利用してバックアップを取っている場合)、非同期データベースをディスマウントした状態でデータベースファイル(IRIS.DAT)を置換します。

※外部/オンラインバックアップ・リストアについては、以下の記事で詳細手順を説明していますので、参考になさってください。
外部バックアップについて
オンラインバックアップについて

※バックアップからのリストアの場合、
 Limit restore to mirrored databases? →Yes でリストアします(リストア後、ミラーが有効化&キャッチアップされます)
 

5.リストア(置換)後、ミラーモニタ画面にて非同期データベースに対するミラーの「有効化」を行います

 管理ポータル:
 [システムシステムオペレーション] > [ミラーモニタ] 

 


6.有効化した後、キャッチアップします

 


7.キャッチアップしたことを確認します(こちらで構成は終了です)

 


 


※非同期メンバのシステム・タイプを変更したい場合(DR非同期 --> レポーティング非同期)

管理ポータルで変更できます。

管理ポータル:
[システム管理] > [構成] > [ミラー設定] > [非同期を編集]

1.非同期メンバシステムタイプを「読み書き可能なレポーティング」に変更します。

2.非同期レポーティング(読み書き可能)は、フェールオーバーメンバに昇格する条件を満たしません。
  読み書き可能に変更するためには、フェールオーバーデータベースフラグをクリア します。
  ※ [FailoverDB] フラグをクリアすると、データベースは読み書き可能に変更されます。
   そのため、ミラーのプライマリコピーとしては使用できなくなります。
   非同期レポーティング(読み取り専用)の場合、この設定は推奨されません

3.保存します。

※詳細は、ドキュメント をご覧ください。


【注意】
[読み書き可能] または [読み取り専用のレポート] から [災害復旧 (DR)] に変更することはできません。
※一部の条件を満たした場合を除きます。詳細は ドキュメント をご覧ください。
 


enlightened【ご参考】
Cache Mirroring 101:簡単なガイドとよくある質問  
ミラーリングの機能について
ミラージャーナルファイルの削除のタイミングと要件
IRISでシャドウイングの代わりにミラーリングを構成する方法-プログラム編
 

Discussion (0)0
Log in or sign up to continue
Question
· Jun 23, 2024

Long JSON Error {}.%FromJSONFile(file)

I am working on JSON and want to be prepared to handle large Objects. I try this code:

ClassMethod MaxLen() As %Status

{

    set longStr=""

    for i=1:1:$SYSTEM.SYS.MaxLocalLength() { set longStr = longStr_"x" }

    write "Maximum string length = "_$LENGTH(longStr)

    ;

    set longObject = {"a":(longStr),"b":(longStr)}

    set file=##class(%File).%New("/tmp/longObjectFile.txt")

    do file.Open("WSN")

    do longObject.%ToJSON(file)

    do file.Close()

    ;

    do file.Open("RS")

    set newObject = {}.%FromJSONFile(file)

    write !,"Property newObject.a is "_$LENGTH(newObject.a)_" characters long."

    quit 1

}

I get error

Maximum string length = 3641144
<THROW>%FromJSONFile+18^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 0 

5 Comments
Discussion (5)3
Log in or sign up to continue
Question
· Jun 23, 2024

How to convert an embeddings vector to be saved as %Vector

I try to get a vector from calling GetEmbedding, but i failed to convert it into a vector 

Here is a simplyfied sample class: 

Class User.myclass Extends %Persistent
{ Property myVECTOR As %Vector(CAPTION = "Vector");

Property myProperty As %String(MAXLEN = 40) [ Required ];

}

here the GetEmbedding part from User.mymethods:

...
ClassMethod GetEmbedding(sentences As %String) As %String [ Language = python ]
{
  import sentence_transformers   model sentence_transformers.SentenceTransformer('C:/InterSystems/IRIS/lib/python/Lib/site-packages/sentence_transformers/models/all-MiniLM-L6-v2')
  embeddings model.encode(sentences)   embeddings_list [str(embedding.tolist()) for embedding in embeddings]
  return embeddings_list
}.....

I try to save the VECTOR into myVECTOR, but that will fail because the vector is not in the right format: 


set VECTOR=##class(User.mymethods).GetEmbedding("this is my text")


/// here I need to convert the VECTOR, but I do not know the right command
 

set data=##class(User.myclass).%New()
set data.myProperty ="anything"
set data.myVECTOR=VECTOR
set ok=data.%Save()

Question: is there a method to convert the vector into the right format to be saved as %Vector

4 Comments
Discussion (4)1
Log in or sign up to continue
Discussion (3)1
Log in or sign up to continue