#InterSystems IRIS

0 フォロワー · 1.3K 投稿

InterSystems IRISは総合データプラットフォームです

    InterSystems IRISは、企業にとって最も価値のある資産(データ)の取得、共有、理解、そしてデータに基づく行動のために必要なすべてのものを提供します。

    完全なプラットフォームである InterSystems IRIS は、複数の開発技術を統合する必要がありません。より少ないコードで開発が可能で、そのアプリケーションは、システムリソース、メンテナンスなども少なくて済みます。

記事 Mihoko Iijima · 4月 24, 2023 6m read

開発者の皆さん、こんにちは!

過去に開催した開発者向けウェビナー アーカイブビデオのまとめページを作成しました。

今後もウェビナーを開催していきますのでこのページをブックマークしていただけると嬉しいですlaugh

プレイリストはこちら👉https://www.youtube.com/playlist?list=PLzSN_5VbNaxB39_H2QMMEG_EsNEFc0ASz

2025年開催分:

✅ウェビナー

Connpassから申込が行えます:🤖はじめてのAI開発 ~ゼロからのIRIS環境構築とOpenAI連携チャットボット作り~🤖
残席7席ですので、ぜひお早めにお申し込みください!💨

24
3 749
記事 Toshihiko Minamoto · 11月 5, 2025 8m read

新しい InterSystems IRIS® Cloud SQL と InterSystems IRIS® Cloud IntegratedML® クラウド製品のユーザーであり、デプロイメントのメトリクスにアクセスして独自の可観測性プラットフォームに送信しようと考えている方のために、メトリクスを Google Cloud Platform Monitoring(旧称 StackDriver)に送信して手っ取り早く行う方法をご紹介します。

クラウドポータルには、概要メトリクス表示用のトップレベルのメトリクスが含まれており、ユーザーに公開されているメトリクスエンドポイントを使用しますが、ある程度探索しなければ、そこにあることには気づきません。

🚩 このアプローチは、「今後名前が付けられる予定の機能」を利用している可能性があるため、それを踏まえると将来性があるものではなく、確実に InterSystemsでサポートされているアプローチではありません。


では、より包括的なセットをエクスポートしたい場合はどうでしょうか?この技術的な記事/例では、メトリクスを取得して可観測性に転送する方法を紹介します。Open Telemetry Collector を使用して、任意のメトリクスターゲットを取得し、任意の可観測性プラットフォーム送信できるように、ニーズに合わせて変更することができます。

上記の結果に導く仕組みは多数の方法で得られますが、ここでは Kubernetes pod を使用して、1 つのコンテナーで Python スクリプトを実行し、もう 1 つのコンテナーで Otel を実行して、メトリクスのプルとプッシュを行います... 自分のやり方を選択することはできますが、この例と記事では、k8s を主人公に Python を使って行います。

手順:

  • 前提条件
  • Python
  • コンテナー
  • Kubernetes
  • Google Cloud Monitoring

前提要件:

  • IRIS®  Cloud SQL の有効なサブスクリプション
  • 実行中の 1 つのデプロイメント(オプションで Integrated ML を使用)
  • 環境に提供するシークレット

環境変数

 
 シークレットの取得
この内容は少し複雑で本題から少し外れているためティーザーに入れましたが、これがシークレットの生成に必要なる値です。
ENV IRIS_CLOUDSQL_USER 'user'
ENV IRIS_CLOUDSQL_PASS 'pass'

☝ これは https://portal.live.isccloud.io の認証情報です。

ENV IRIS_CLOUDSQL_USERPOOLID 'userpoolid'
ENV IRIS_CLOUDSQL_CLIENTID 'clientid'
ENV IRIS_CLOUDSQL_API 'api'

☝ これはブラウザの開発ツールから取得する必要があります。

  • `aud` = clientid
  • `userpoolid`= iss
  • `api` = request utl

ENV IRIS_CLOUDSQL_DEPLOYMENTID 'deploymentid'

☝これはクラウドサービスポータルから取得できます

 

Python:

以下に、クラウドポータルからメトリクスを取得し、それを Otel Collectorが取得するメトリクスとしてローカルにエクスポートする Python ハッキングを示します。

 
iris_cloudsql_exporter.py
import time
import os
import requests
import json

from warrant import Cognito from prometheus_client.core import GaugeMetricFamily, REGISTRY, CounterMetricFamily from prometheus_client import start_http_server from prometheus_client.parser import text_string_to_metric_families

classIRISCloudSQLExporter(object):definit(self): self.access_token = self.get_access_token() self.portal_api = os.environ['IRIS_CLOUDSQL_API'] self.portal_deploymentid = os.environ['IRIS_CLOUDSQL_DEPLOYMENTID']

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">collect</span><span class="hljs-params">(self)</span>:</span>
    <span class="hljs-comment"># Requests fodder</span>
    url = self.portal_api
    deploymentid = self.portal_deploymentid
    print(url)
    print(deploymentid)

    headers = {
        <span class="hljs-string">'Authorization'</span>: self.access_token, <span class="hljs-comment"># needs to be refresh_token, eventually</span>
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
    }

    metrics_response = requests.request(<span class="hljs-string">"GET"</span>, url + <span class="hljs-string">'/metrics/'</span> + deploymentid, headers=headers)
    metrics = metrics_response.content.decode(<span class="hljs-string">"utf-8"</span>)

    <span class="hljs-keyword">for</span> iris_metrics <span class="hljs-keyword">in</span> text_string_to_metric_families(metrics):
        <span class="hljs-keyword">for</span> sample <span class="hljs-keyword">in</span> iris_metrics.samples:

            labels_string = <span class="hljs-string">"{1}"</span>.format(*sample).replace(<span class="hljs-string">'\''</span>,<span class="hljs-string">"\""</span>)
            labels_dict = json.loads(labels_string)
            labels = []

            <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> labels_dict:
                labels.extend(labels_dict)
            <span class="hljs-keyword">if</span> len(labels) &gt; <span class="hljs-number">0</span>:
                g = GaugeMetricFamily(<span class="hljs-string">"{0}"</span>.format(*sample), <span class="hljs-string">'Help text'</span>, labels=labels)
                g.add_metric(list(labels_dict.values()), <span class="hljs-string">"{2}"</span>.format(*sample))
            <span class="hljs-keyword">else</span>:
                g = GaugeMetricFamily(<span class="hljs-string">"{0}"</span>.format(*sample), <span class="hljs-string">'Help text'</span>, labels=labels)
                g.add_metric([<span class="hljs-string">""</span>], <span class="hljs-string">"{2}"</span>.format(*sample))
            <span class="hljs-keyword">yield</span> g

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_access_token</span><span class="hljs-params">(self)</span>:</span>
    <span class="hljs-keyword">try</span>:
        user_pool_id = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_USERPOOLID'</span>] <span class="hljs-comment"># isc iss </span>
        username = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_USER'</span>]
        password = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_PASS'</span>]
        clientid = os.environ[<span class="hljs-string">'IRIS_CLOUDSQL_CLIENTID'</span>] <span class="hljs-comment"># isc aud </span>
        print(user_pool_id)
        print(username)
        print(password)
        print(clientid)
        
        <span class="hljs-keyword">try</span>:
            u = Cognito(
                user_pool_id=user_pool_id,
                client_id=clientid,
                user_pool_region=<span class="hljs-string">"us-east-2"</span>, <span class="hljs-comment"># needed by warrant, should be derived from poolid doh</span>
                username=username
            )
            u.authenticate(password=password)
        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> p:
            print(p)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(e)

    <span class="hljs-keyword">return</span> u.id_token

ifname == 'main':

start_http_server(<span class="hljs-number">8000</span>)
REGISTRY.register(IRISCloudSQLExporter())
<span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>:
    REGISTRY.collect()
    print(<span class="hljs-string">"Polling IRIS CloudSQL API for metrics data...."</span>)
    <span class="hljs-comment">#looped e loop</span>
    time.sleep(<span class="hljs-number">120</span>)</code></pre>

 

Docker:

 
Dockerfile
FROM python:3.8ADD src /src
RUN pip install prometheus_client
RUN pip install requests
WORKDIR /src
ENV PYTHONPATH '/src/'ENV PYTHONUNBUFFERED=1ENV IRIS_CLOUDSQL_USERPOOLID 'userpoolid'ENV IRIS_CLOUDSQL_CLIENTID 'clientid'ENV IRIS_CLOUDSQL_USER 'user'ENV IRIS_CLOUDSQL_PASS 'pass'ENV IRIS_CLOUDSQL_API 'api'ENV IRIS_CLOUDSQL_DEPLOYMENTID 'deploymentid'RUN pip install -r requirements.txt
CMD ["python" , "/src/iris_cloudsql_exporter.py"]
docker build -t iris-cloudsql-exporter .
docker image tag iris-cloudsql-exporter sween/iris-cloudsql-exporter:latest
docker push sween/iris-cloudsql-exporter:latest


デプロイメント:

k8s、ネームスペースを作成します:

kubectl create ns iris

k8s、シークレットを追加します:

kubectl create secret generic iris-cloudsql -n iris \
    --from-literal=user=$IRIS_CLOUDSQL_USER \
    --from-literal=pass=$IRIS_CLOUDSQL_PASS \
    --from-literal=clientid=$IRIS_CLOUDSQL_CLIENTID \
    --from-literal=api=$IRIS_CLOUDSQL_API \
    --from-literal=deploymentid=$IRIS_CLOUDSQL_DEPLOYMENTID \
    --from-literal=userpoolid=$IRIS_CLOUDSQL_USERPOOLID

otel、構成を作成します:

apiVersion: v1
data:
  config.yaml: |
    receivers:
      prometheus:
        config:
          scrape_configs:
          - job_name: 'IRIS CloudSQL'
              # Override the global default and scrape targets from this job every 5 seconds.
            scrape_interval: 30s
            scrape_timeout: 30s
            static_configs:
                    - targets: ['192.168.1.96:5000']
            metrics_path: /
exporters:
  googlemanagedprometheus:
    project: "pidtoo-fhir"
service:
  pipelines:
    metrics:
      receivers: [prometheus]
      exporters: [googlemanagedprometheus]

kind: ConfigMap metadata: name: otel-config namespace: iris

k8s、otel 構成を configmap としてロードします:

kubectl -n iris create configmap otel-config --from-file config.yaml

k8s、ロードバランサー(確実にオプション)、MetalLB をデプロイします。これはクラスタ外部からグスクレイピングして検査するために行っています。

cat <<EOF | kubectl apply -f -n iris -
apiVersion: v1
kind: Service
metadata:
  name: iris-cloudsql-exporter-service
spec:
  selector:
    app: iris-cloudsql-exporter
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 8000
EOF

gcp、Google Cloud へのキーが必要です。サービスアカウントにスコープを設定する必要があります

  • roles/monitoring.metricWriter
kubectl -n iris create secret generic gmp-test-sa --from-file=key.json=key.json

k8s; deployment/pod そのもの。2 つのコンテナー:

 
deployment.yaml
kubectl -n iris apply -f deployment.yaml

実行

特に問題がなければ、ネームスペースを詳しく調べて、状況を確認してみましょう。

✔ GCP と Otel 用の 2 つの configmap

 

✔ 1 つのロードバランサー

 

✔ 1 つの pod、2 つのコンテナーが正しくスクレイピングされます

  

Google Cloud Monitoring

可観測性を調べてメトリクスが正しく受信されていることを確認し、可観測性を高めましょう!

 

0
0 20
記事 Toshihiko Minamoto · 10月 30, 2025 7m read

img

この記事では、IRIS環境におけるPythonプログラミングの基礎について紹介します。

本題に入る前に、重要なトピックである「Pythonの仕組み」について説明します。これは、IRIS環境でPythonを使用して作業する際に起こりうる問題や制限を理解するのに役立ちます。

すべての記事と例は、以下のgitリポジトリで確認できます: iris-python-article

Pythonの仕組み

インタープリター型言語

Pythonはインタープリター型言語であり、コードはランタイム時に1行ずつ実行されます。スクリプトをインポートする場合でも同様です。

これはどういうことでしょうか? 以下のコードを見てみましょう。

# introduction.py

def my_function():
    print("Hello, World!")

my_function()

このスクリプトを実行すると、Pythonインタープリターはコードを1行ずつ読み取ります。 まず最初に関数 my_function を定義してから、その関数を呼び出すと、コンソールに「Hello, World!」と出力されます。

スクリプトを直接実行している例:

python3 /irisdev/app/src/python/article/introduction.py 

出力は以下のようになります。

Hello, World!

IRIS環境でこのスクリプトをインポートするとどうなるのでしょうか?

Class Article.Introduction Extends %RegisteredObject
{
    ClassMethod Run()
    {
        Set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")

        do ##class(%SYS.Python).Import("introduction")
    }
}

実行しましょう。

iris session iris -U IRISAPP '##class(Article.Introduction).Run()'

出力が表示されます。

Hello, World!

これは、Pythonインタープリターがコードを解釈しながらインポートするためで、最初に関数を定義し、その後に関数を呼び出します。これはスクリプトを直接実行した場合と同じ動作ですが、実行しているのではなくインポートしています

⚠️ 重要な注意事項:関数を呼び出さずにスクリプトをインポートしても、何も起こりません。 関数は定義されますが、明示的に呼び出さない限り実行されません。

分かりましたか? Pythonインタープリターはファイル内のコードを実行しますが、関数を呼び出さなければ、その関数は実行されません。

呼び出さずにインポートする例:

# introduction1.py
def my_function():
    print("Hello, World!")

Pythonインタープリターで実行しましょう。

python3 /irisdev/app/src/python/article/introduction1.py 

出力:

# 関数は定義されていますが、呼び出されていないため、出力はありません

IRIS環境にこのスクリプトをインポートすると:

Class Article.Introduction1 Extends %RegisteredObject
{
    ClassMethod Run()
    {
        Set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")
        do ##class(%SYS.Python).Import("introduction1")
    }
}

実行しましょう。

iris session iris -U IRISAPP '##class(Article.Introduction1).Run()'

関数は定義されていますが、呼び出されていないため、出力はありません。

🤯この微妙な違いが重要な理由

  • Pythonスクリプトをインポートすると、そのスクリプトのコードが実行されます。
    • コードを実行したくない場合があります
  • インポートするとスクリプトが実行されているように見えるかもしれませんが、実際には直接実行されているわけではないため、混乱を招く可能性があります。

インポートのキャッシュ

Pythonスクリプトをインポートすると、Pythonインタープリターがインポートされたスクリプトをキャッシュします。 つまり、同じスクリプトをもう一度インポートすると、そのスクリプトのコードは再実行されず、キャッシュされたバージョンが使用されます。

具体例による説明:

introduction.py スクリプトを再利用しましょう。

# introduction.py
def my_function():
    print("Hello, World!")

my_function()

次に、同じように Article.Introduction クラスを再利用しましょう。

Class Article.Introduction Extends %RegisteredObject
{
    ClassMethod Run()
    {
        Set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")
        do ##class(%SYS.Python).Import("introduction")
    }
}

今度は、同じIRISセッション内で2回続けて実行します。

iris session iris -U IRISAPP 

IRISAPP>do ##class(Article.Introduction).Run()
Hello, World!

IRISAPP>do ##class(Article.Introduction).Run()

IRISAPP>

🤯一体どういうことでしょうか?

はい、「Hello, World!」は一度だけ出力されます!

⚠️ インポートされたスクリプトはキャッシュされています。 つまり、インポートした後にスクリプトを変更しても、IRSセッションが変更されるまで変更は反映されません。

IRISで language tag を使用する場合でも同じです。

Class Article.Introduction2 Extends %RegisteredObject
{

ClassMethod Run() [ Language = python ]
{
    import os

    if not hasattr(os, 'foo'):
        os.foo = "bar"
    else:
        print("os.foo already exists:", os.foo)
}

}

実行しましょう。

iris session iris -U IRISAPP

IRISAPP>do ##class(Article.Introduction2).Run()

IRISAPP>do ##class(Article.Introduction2).Run()
os.foo already exists: bar

なんと、os モジュールはキャッシュされ、foo 属性は存在しないことに再定義されていません。

まとめ

この入門編が、IRISでPythonを使用する際に、特にスクリプトのインポートやキャッシュ処理に関して、予期しない動作が発生する理由を理解する助けになれば幸いです。

IRISでPythonを使う際のポイント:

  • Pythonスクリプトで変更を確認するには、IRISセッションを毎回変更する。
    • これはバグではなく、Pythonの仕様です。
  • スクリプトをインポートするとそのコードが実行されることに気を付ける。

ボーナス

待って! スクリプトをインポートするとキャッシュされる?つじつまが合いません。 language tag = python で作業していて、スクリプトを変更したのにIRISセッションを変更しなくてもうまく動作するのは何故でしょうか?

いい質問です。これは language tag の仕組みが関係しています。language tag は実行するたびにスクリプトをもう一度読み込み、ネイティブのPythonインタープリターで新しい行を入力するかのように、行ごとに実行します。language tag はスクリプトをインポートするわけではなく、Pythonインタープリターを再起動せずに直接スクリプトを実行しているのと同じ動作をします。

例:

Class Article.Introduction2 Extends %RegisteredObject
{
ClassMethod Run() [ Language = python ]
{
    import os

    if not hasattr(os, 'foo'):
        os.foo = "bar"
    else:
        print("os.foo already exists:", os.foo)
}
}

実行しましょう。

iris session iris -U IRISAPP
IRISAPP>do ##class(Article.Introduction2).Run()

IRISAPP>do ##class(Article.Introduction2).Run()
os.foo already exists: bar  

Pythonインタープリターだと、こんな感じになります。

import os

if not hasattr(os, 'foo'):
    os.foo = "bar"
else:
    print("os.foo already exists:", os.foo)

import os
if not hasattr(os, 'foo'):
    os.foo = "bar"
else:
    print("os.foo already exists:", os.foo)

出力:

os.foo already exists: bar # only printed once

いかがでしょうか。

今後の内容 :

  • Pep8
  • モジュール
  • ダンダーメソッド
  • IRISでPythonを動かす
  • ...
0
0 16
記事 Toshihiko Minamoto · 10月 28, 2025 3m read

img

この記事では、マジックメソッドとしても知られるPythonダンダーメソッドについて簡単に解説します。

ダンダーメソッドとは?

ダンダーメソッドは、始めと終わりに2つのアンダースコア(__)が付いているPythonの特殊メソッドです。 このメソッドを使用することで、加算や減算、文字列表現など、組み込みの操作に対するオブジェクトの動作を定義することができます。

よくあるダンダーメソッドには、次が含まれます。

  • __init__(self, ...):オブジェクトの作成時に呼び出されます。
    • ObjectScriptの %OnNew メソッドに似ています
  • __str__(self):オブジェクトを文字列として表現するために、str() 組み込み関数と print によって呼び出されます。
  • __repr__(self):デバッグ用のオブジェクトを表現するために、repr() 組み込み関数によって呼び出されます。
  • __add__(self, other)+ 演算子が使用される際に呼び出されます。
  • __len__(self):オブジェクトの長さを返すために、len() 組み込み関数によって呼び出されます。
  • __getitem__(self, key):インデックス構文を使用してコレクションからアイテムを取得するために呼び出されます。
  • __setitem__(self, key, value):インデックス構文を使用してコレクション内にアイテムを設定するために呼び出されます。
  • ... 他にもたくさんあります。

IRIS環境において、ダンダーメソッドが重要であり関連性があるのはなぜか?

Objectscriptでは、Pythonのようなシンタックスシュガーはありませんが、ダンダーメソッドを使用して同じような動作を実現できます。

例えば、インポートしたPythonモジュールにPythonのリストを返す関数があり、Objectscriptでそれを使用したいとします。 リスト内のアイテムにアクセスするには、__getitem__ ダンダーメソッドを使用する必要があります。

# src/python/article/dunder_example.py
def get_list():
    return [1, 2, 3, 4, 5]
Class Article.DunderExample Extends %RegisteredObject
{

ClassMethod Run()
{
    Set sys = ##class(%SYS.Python).Import("sys")
    do sys.path.append("/irisdev/app/src/python/article")
    set dunderExample = ##class(%SYS.Python).Import("dunder_example")
    set myList = dunderExample."get_list"()
    for i=0:1:myList."__len__"()-1 {
        write myList."__getitem__"(i), !
    }
}

}

実行しましょう。

iris session iris -U IRISAPP '##class(Article.DunderExample).Run()'

出力は以下のようになります。

1
2
3
4
5

これは、IRIS環境でPythonオブジェクトとやり取りするためにダンダーメソッドを使う方法を具体的に示しており、ObjectScript環境内で作業しながらPythonの機能を活用することができます。

ボーナス

ダンダーの優れた使い方の1つは、スクリプトがモジュールとしてインポートされた際にコードが実行されないようにするために、if __name__ == "__main__": ブロックをPythonスクリプトの最後に配置することです。

最初の記事で、スクリプトをインポートするとコードが実行されることを説明しました。 このブロックにより、スクリプトがインポートされたときではなく、直接実行されたときにのみ実行されるコードを定義できます。

例:

# src/python/article/dunder_example.py
def get_list():
    return [1, 2, 3, 4, 5]

if __name__ == "__main__":
    print(get_list())

まとめ

ダンダーメソッドを使えば、PythonのシンタックスシュガーでできることはObjectScriptでも可能です。

0
0 14
記事 Kosaku Ikeda · 10月 26, 2025 14m read

コミュニティの皆さんこんにちは。
 

ベクトル検索関連の処理が完全にノーマークだった私が、一先ず「やってみよう!」との事で、2つの動画のサンプルを実行してみました。
Pythonは初心者なので、アレな箇所があっても目をつぶっていただけると幸いです。

また、間違っている箇所があったら、ご指摘いただけると幸いです。


■参考にした動画

■参考にしたコミュニティ記事

【目的】

本記事では、動画で紹介された内容を実際にIRIS環境上で実行できるよう、具体的な環境構築とコーディングを記載致します。
コミュニティの皆さんが簡単に試せるようになれば幸いです。

またGithubにサンプルソースを配置しているので、必要な方は参考にして下さい。

【準備】

■作業環境

※環境作成方法に問題のない方は、読み飛ばしていただいて構いません。

項目 バージョン情報・他
OS WIndowsServer2019
IRIS IRIS Community 2025.2.0.227.0
Python 3.12.10
開発環境 VS Code 1.105.1
0
0 41
InterSystems公式 Seisuke Nakahashi · 10月 23, 2025

インターシステムズは、InterSystems IRIS® data platformInterSystems IRIS® for HealthTMHealthShare® Health Connect のメンテナンスバージョン 2025.1.2 および 2024.1.5 をリリースしました。今回のリリースでは、最近お知らせした以下の警告や勧告の修正が含まれています。

製品の品質改善のために、開発者コミュニティを通じてぜひご意見をお聞かせください。

ドキュメント

詳細な変更リストとアップグレードチェックリストはこちらのドキュメントをご参照ください(すべて英語, 2025.1):

早期アクセスプログラム (Early Access Programs; EAPs)

0
0 25
記事 Hiroshi Sato · 10月 21, 2025 1m read

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

ルーチンやメソッドを実行した際に以下のような<FRAMESTACK>エラーが発生する場合、DOコマンドの発行の入れ子数が多すぎて、それ以上スタック情報を保持できなくなったことを示しています。

<FRAMESTACK> error is reported when the routine has too many nested calls to DO command. You can check the current stack with $STACK value.

可能性として高いのはプログラミング上のミスで再起的なメソッド/ルーチン呼び出しがループしている場合などです。

以下のようなプログラミングを行い、$STACK変数の値を確認することで、スタックのレベルがどのように変化しているのかを確認できます。

0
0 18
記事 Hiroshi Sato · 10月 21, 2025 1m read

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

%String型のプロパティをOrder Byの条件にしてクエリーを発行した際のデータは以下のような順番で並べられます。

SELECT * FROM Shop.Order orderby StatusFlag
null
-1
-2
-99
0

これは%String型(文字列型)のプロパティの照合順として正しい振る舞いです。

文字列照合の並び順

文字列プロパティに対し、+ をつけることで、数値照合と同じ照合順を得ることができます。

SELECT * FROM Shop.Order orderby +StatusFlag
null
-99
-1
-2
0
0
0 15
記事 Hiroshi Sato · 10月 21, 2025 1m read

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

SQLアクセス( ADO含む)を行う場合は、SQLトランザクションを使用して、トランザクションを制御します。

一方オブジェクトアクセス(ObjectScript)ではtstart / tcommit / trollbackコマンド 
(Native SDK for .NETでは IRIS の TStart(), TCommit(), TRollback() メソッド)
によってトランザクションを制御します。

この2種類のトランザクションモードを混在させて使用することはサポートされていません。

詳細は、以下のドキュメントをご参照ください。

トランザクション管理

また関連するメソッドの以下ドキュメントの注意事項にも

「このメソッドは Native SDK トランザクション・モデルを使用し、ADO.NET/SQL トランザクション・メソッドとは互換性がありません。

この 2 つのトランザクション・モデルを混在させないでください。」

と記載をしております。

Native SDK for .NET のクイック・リファレンス

0
0 13
記事 Hiroshi Sato · 6月 22, 2025 1m read

.pyファイルの中でIRISのEmbedded Pythonを動作させる際にirispythonコマンドで実行する方法はドキュメント上で紹介されていましたので、以前より使用していました。

しかし、普通のpythonコマンドを使用するとうまく実行できなかったのですが、最近その謎(原因)が解けたので紹介します。

これは、Mac特有の問題である可能性が高くWindowsやLinuxでは何の問題もなく実行できるのかもしれません。

エラーは以下のようなエラーです。

  File "/opt/iris/lib/python/iris.py", line 34, in <module>
    from pythonint import *
ImportError: IrisSecureStart failed: IRIS_ATTACH (-21)

 

このエラーの原因は、シェルの実行ユーザーとirisのオーナーが異なることが原因とのことです。

Macで普通にIRISをインストールするとそのオーナーはrootです。

従ってpython3コマンドを実行する時にsudoコマンドでrootになる必要があるということです。

そして以下のような環境変数の設定も必要です。

3
0 78
お知らせ Mihoko Iijima · 10月 2, 2025

開発者の皆さん、こんにちは!今年も開発者コミュニティミートアップを東京にて開催します!📣

【ミートアップ概要】

AI アプリの開発に興味があるけれど、何から始めれば良いか分からない方へ。

RAG、生成 AI などの用語は聞いたことがあるけど、そこまで詳しくない。
興味はあり、自分たちのシステムにも導入してみたい、でも、なかなか時間が取れなくて、学ぶチャンスがない。
そう悩んでいる方いませんか?

そんなあなたに!12月3日(水)AIアプリの開発をテーマとしたミートアップを開催します! 

ミートアップでは、最初に、数々の AI 駆動開発をご経験されている方から、「AI駆動開発の最新情報」についてお話いただきます。
次に、AI アプリ作成のワークショップを通じて、具体的な開発の流れを短時間でご体験いただきます。
最後に、コミュニティメンバーとのネットワーキングの時間を楽しんでいただきます。この時間には、クイズ大会も行う予定です(軽食もご用意いたします)。

AI を「使う」から「創る」側へ。未来を拓く一歩を踏み出しませんか?
ぜひ、AI アプリ作成を体験できるミートアップにご参加ください。

《こんな方におすすめ》

  • RAG、生成AIに興味があり、開発をしてみたい方
  • 具体的に動くコードを見るとワクワクする方  
1
0 96
記事 Mihoko Iijima · 10月 16, 2025 1m read

開発者の皆さん、こんにちは!

この記事では、Developer Hub にまたまた新チュートリアル:InterSystems IRIS for Health:デジタルヘルスの相互運用性 が追加されましたので、体験内容についてご紹介します。(準備不要でブラウザがあれば試せるチュートリアルです!)

チュートリアルでは、InterSystems IRIS for Health を使用しているのですが、IRIS for Health の持つ機能により以下のような相互運用性シナリオを作成できます。

  • HL7、CDA、FHIR、DICOM のデータルーティングを管理
  • HL7 から FHIR への変換、CDA から HL7 への変換、FHIR から CDA への変換
  • 異なるシステムと API との間のデータフローを確立

チュートリアルの中では、あるシステムから入力される HL7 メッセージを他のシステムに送信する流れをご体験いただけます。

また、データ変換が必要な場合の対応方法や HL7 メッセージの一部をテーブルに保存する流れなどもご体験いただけます。

例)HL7 メッセージの一部をテーブルに格納

アカウント作成やログインも不要で  ボタンをクリックするだけで始められます👍

ぜひ、お試しください!​​​​​​

0
0 20
お知らせ Rie Tokue · 10月 16, 2025

 

いつもお世話になっております。

11月の開発者向けウェビナー以下の内容で開催いたします。

タイトル:「組み込みPythonの仕組みと、その効果的な使い方について」

日時:11月20日(木)13時30分~14時

参加費無料・事前登録制

ご登録はこちらから

【概要】

【概要】

組み込みPythonが正式にリリースされてから3年が経過しました。それ以降、多くのエンジニアにより、様々なアイデアが実現されるとともに、その使い方についても良し悪し、向き不向き、といった議論が行われています。今回のウェビナは、組み込みPythonの仕組みを少し深堀りするとともに、この仕組みにより実現する、その「双方向性」を理解した上で、Pythonのエコシステムを最大限に生かしながら開発することのメリットをお伝えする、という内容です。

【こんな方にお勧め】

組み込みPythonに興味をお持ちの方

ご多用中とは存じますが、皆様のご参加をお待ち申し上げております。

インターシステムズジャパン

0
0 30
記事 Toshihiko Minamoto · 10月 16, 2025 2m read

私が先週リリースしたInterSystems Testing Managerの新しいバージョンでは、@Timothy Leavittの優れた
テストカバレッジツールが追加され、私は2025年度Developer Toolsコンテストに出品しました。

こちらは、IPMプロジェクトのユニットテストが、IPMリポジトリでソート順を上書きできると思われる機能をまだカバーしていないことを示すティザー的なスクリーンショットです。

88行目が開発者への警告として赤くハイライトされていることに注目してください。

VS Codeのエクスプローラービューには「バッテリーインジケーター」風のアイコンが表示されており、このクラスのメソッド内の実行可能な行のうち、テストでカバーされているのが76%のみであるため、黄色になっています。 インジケーターにカーソルを合わせると、さらに詳しい情報が表示され、メソッドのカバレッジ(9個中8個)が、エディター内のオプションのテストカバレッジツールバーに第2のインジケーターとして表示されます。

VS Codeでは、しきい値を設定できるほか、赤・黄・緑が区別しにくい場合には、色自体も構成できます。

いかがでしょうか? すでにInterSystemsの%UnitTestフレームワークをご利用中であれば、ぜひご自身でもお試しください。 ご意見・ご感想は大歓迎です。コンテストの投票への投票もぜひお願いします。投票は米国東部時間で8月3日(日)深夜まで受け付けています。

0
0 20
お知らせ Toshihiko Minamoto · 10月 14, 2025

%UnitTestフレームワークのユーザーは、InterSystems Testing Manager拡張機能の最新リリース(v2.0.0)を@Timothy Leavittの素晴らしいテストカバレッジツールと組み合わせることで、VS Code内でテストカバレッジ情報を取得できるようになりました。

上部にテストカバレッジのペインが表示されています。左側のテストエクスプローラーと併せて確認しやすいように、右側のセカンダリサイドバーに移動させました。

直近のテスト実行(テストカバレッジツール自体のユニットテストすべて)の結果、TestCoverage.Procedures内のBitValueメソッドはカバーされていましたが、BitCountメソッド(および他の6つのメソッド)はカバーされていないことに注目してください。 TestCoverageパッケージの全体で43.08%の実行可能行のみが、ユニットテストによってカバーされていました。

InterSystems Testing Managerに対するこの大幅なアップグレードを、現在開催中のDeveloper Toolsコンテスト に出品します。 もし良いと思っていただけたら、来週の投票でぜひ応援してください!

0
0 29
記事 Mihoko Iijima · 10月 9, 2025 1m read

開発者の皆さん、こんにちは!

この記事では、Developer Hub にあるチュートリアルに新しいチュートリアル:InterSystems IRIS ベクトル検索を使用した RAG が追加されましたので内容をご紹介します。(準備不要でブラウザがあれば試せるチュートリアルです!)

このチュートリアルでは、生成 AI アプリケーションの精度向上に向けて、ベクトル検索と検索拡張生成(Retrieval Augmented Generation)の活用を体験できます。

具体的には、InterSystems IRIS のベクトル検索機能を活用し、生成 AI チャットボット向けのナレッジベースをサンプルコードを利用して作成します。

また、Streamlit を使用して作成したチャットボットを動かしながら、ナレッジベースの情報を追加することで生成 AI からの回答が変化していくことを確認していきます。

アカウント作成やログインも不要で  ボタンをクリックするだけで始められます👍

チュートリアルへのリンクは「開発者コミュニティのリソース」からも辿れます!

ぜひ、お試しください!​​​​​​

0
0 33
記事 Toshihiko Minamoto · 10月 9, 2025 8m read

少し遅れましたが、モバイルアプリケーションから接続する例を示して Workflow Engine に関する連載記事をようやく締めくくることにします。

前回の記事では、これから説明する例として、患者と担当医師の両方にとって高血圧症などの慢性病状の詳細な管理を可能にするアプリケーションを示しました。 この例では、患者は携帯電話からウェブアプリケーション(基本的に、デバイスに応答するように設計されたウェブページ)にアクセスし、ポータブル血圧計が IRIS インスタンスに送信する測定に基づく通知を受信します。

したがって、IRIS インスタンスへのアクセスは 2 つです。

  • モバイルアプリケーションからのユーザーアクセス。
  • 血圧の測定値を送信するデバイスアクセス。

この記事では、患者が測定値を生成するタスクを管理できる、最初のアクセスを確認します。

モバイルアプリケーションと IRIS の接続

この接続では、IRIS 内でウェブアプリケーションを構成するのが最も単純です。これを行うには、管理ポータルのシステム管理 -> セキュリティ -> アプリケーション -> ウェブアプリケーションからアクセスします。

次に、表示されるリストでアプリケーションの新規作成をクリックすると、以下のような画面が開きます。

この画面で、以下のフィールドを構成しましょう。

  • 名前: IRIS にデプロイされる機能にアクセスできるように公開する URL を定義します。
  • ネームスペース: ウェブアプリケーションを関連付けるネームスペースです。これによって、後で相互運用性プロダクションの機能を利用できるようになります。
  • REST: 公開するものが HTTP 接続を可能にする REST API であるため、このオプションを選択します。
  • ディスパッチクラス: HTTP 呼び出しを受け取り、その処理を決定する ObjectScript クラス。
  • JWT 認証を使用する: このオプションをオンにすると、アプリケーションに定義した URL の /login および /logout エンドポイントが有効になるため、IRIS への呼び出しを認証するための JSON ウェブトークンを取得できるようになります。
  • セキュリティ設定 -> 許可される認証方法: 呼び出しを安全にするためにパスワードを設定します。

Workflow.WS.Service クラスを確認しましょう。

Class Workflow.WS.Service Extends%CSP.REST
{

Parameter HandleCorsRequest = 0;Parameter CHARSET = "utf-8"; XData UrlMap [ XMLNamespace = "https://www.intersystems.com/urlmap" ] { <Routes> <Route Url="/getTasks" Method="GET" Call="GetTasks" /> <Route Url="/saveTask" Method="POST" Call="SaveTask" /> </Routes> }

ClassMethod OnHandleCorsRequest(url As%String) As%Status { set url = %request.GetCgiEnv("HTTP_REFERER") set origin = $p(url,"/",1,3) // origin = "http(s)://origin.com:port"// here you can check specific origins// otherway, it will allow all origins (useful while developing only)do%response.SetHeader("Access-Control-Allow-Credentials","true") do%response.SetHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS") do%response.SetHeader("Access-Control-Allow-Origin",origin) do%response.SetHeader("Access-Control-Allow-Headers","Access-Control-Allow-Origin, Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control") quit$$$OK }

ClassMethod GetTasks() As%Status { Try { Do##class(%REST.Impl).%SetContentType("application/json") If '##class(%REST.Impl).%CheckAccepts("application/json") Do##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) QuitDo##class(%REST.Impl).%SetStatusCode("200") set sql = "SELECT %Actions, %Message, %Priority, %Subject, TaskStatus_TimeCreated, ID FROM EnsLib_Workflow.TaskResponse WHERE TaskStatus_AssignedTo = ? AND TaskStatus_IsComplete = 0"set statement = ##class(%SQL.Statement).%New(), statement.%ObjectSelectMode = 1set status = statement.%Prepare(sql) if ($$$ISOK(status)) { set resultSet = statement.%Execute($USERNAME) if (resultSet.%SQLCODE = 0) { set tasks = [] while (resultSet.%Next() '= 0) { set task = {"actions": "", "message": "", "priority": "", "subject": "", "creation": "", "id": ""} set task.actions = resultSet.%GetData(1) set task.message = resultSet.%GetData(2) set task.priority = resultSet.%GetData(3) set task.subject = resultSet.%GetData(4) set task.creation = resultSet.%GetData(5) set task.id = resultSet.%GetData(6) do tasks.%Push(task) }
} } set result = {"username": ""} set result.username = $USERNAMEDo##class(%REST.Impl).%WriteResponse(tasks)

} <span class="hljs-keyword">Catch</span> (ex) {
    <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"400"</span>)
    <span class="hljs-keyword">return</span> ex.DisplayString()
}

<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

ClassMethod SaveTask() As%Status { Try { Do##class(%REST.Impl).%SetContentType("application/json") If '##class(%REST.Impl).%CheckAccepts("application/json") Do##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) Quit// Reading the body of the http call with the person dataset dynamicBody = {}.%FromJSON(%request.Content)

    <span class="hljs-keyword">set</span> task = <span class="hljs-keyword">##class</span>(EnsLib.Workflow.TaskResponse).<span class="hljs-built_in">%OpenId</span>(dynamicBody.<span class="hljs-built_in">%Get</span>(<span class="hljs-string">"id"</span>))
    <span class="hljs-keyword">set</span> sc = task.CompleteTask(dynamicBody.action)

    <span class="hljs-keyword">if</span> <span class="hljs-built_in">$$$ISOK</span>(sc) {	        
        <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"200"</span>)
        <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%WriteResponse</span>({<span class="hljs-string">"result"</span>: <span class="hljs-string">"success"</span>})         
	}	
    
} <span class="hljs-keyword">Catch</span> (ex) {
    <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"400"</span>)
    <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%WriteResponse</span>({<span class="hljs-string">"result"</span>: <span class="hljs-string">"error"</span>})
}

<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

}

ご覧のとおり、WS から必要なすべてのロジックを解決していますが、この方法は推奨されません。ネームスペースに構成されたプロダクションに受信したリクエストを送信することで可能なトレーサビリティを失ってしまうためです。

URLMap セクションを確認すると、2 つのエンドポイントが WS で構成されていることが分かります。

  • getTasks: ユーザーのすべての保留中のタスクを復旧します(使用されている SQL を見ると、ログインしたときに生成される変数から直接ユーザー名を渡しています)。
  • saveTask: ユーザーのタスクへのレスポンスを受信し、EnsLib.Workflow.TaskResponse クラスの CompleteTaks メソッドを実行することで、タスクの終了に進みます。

IRIS の部分では、外部アプリケーションが接続できるようにすべてが構成済みです。

Workflow Engine で外部アプリケーションをテストする

まず、ファイル /shared/hl7/message_1_1.hl7 をパス /shared/in にコピーすることで、HL7 からプロダクションへのメッセージの送信をシミュレーションします。送信するメッセージを確認しましょう。

MSH|^~\&|HIS|HULP|EMPI||20240402111716||ADT^A08|346831|P|2.5.1
EVN|A08|20240402111716
PID|||07751332X^^^MI^NI~900263^^^HULP^PI||LÓPEZ CABEZUELA^ÁLVARO^^^||19560121|F|||PASEO MARIO FERNÁNDEZ 2581 DERECHA^^MADRID^MADRID^28627^SPAIN||555819817^PRN^^ALVARO.LOPEZ@VODAFONE.COM|||||||||||||||||N|
PV1||N
OBX|1|NM|162986007^Pulso^SNM||72|^bpm|||||F|||20240402111716
OBX|2|NM|105723007^Temperatura^SNM||37|^Celsius|||||F|||20240402111716
OBX|3|NM|163030003^Presión sanguínea sistólica^SNM||142|^mmHg|||||F|||20240402111716
OBX|4|NM|163031004^Presión sanguínea diastólica^SNM||83|^mmHg|||||F|||20240402111716

前回の記事を覚えていらっしゃらない方のために説明すると、BPL は収縮期血圧が 140 を超えるか拡張期血圧が 90 を超えるとアラートが生成されるように定義していたため、このメッセージにより、DNI(スペインの身分証明書)が 07751332X である患者に対する警告タスクと、IRIS が新しい通知を受信するまで開いたままになる別の自動タスクが生成されます。

モバイルアプリケーションを確認しましょう。

2 つのタスクが生成されています。1 つは手動タスクとして定義されており、ユーザーによって終了方法が異なります。もう 1 つは自動タスクとして宣言されており、それを終了するには、ユーザーが血圧計で新しい測定を行う必要があります。 HTTP 呼び出しを見てみると、これにどのように JWT を含めているのかが分かります。

ユーザーが保留中のタスクの Accept ボタンをクリックすると、このフローは血圧計の測定値の受信を待機したままとなり、次のステップに進みません。 手動タスクが受け入れられ、血圧計からの新しい測定値を受信し、それがもう一度制限を超えている場合は、システムは患者向けのタスクと、関連する医師向けに危険な状態の可能性を警告するタスクの 2 つの新しい警告タスクを生成します。 :

完璧です! 患者通知システムは素早く簡単にセットアップ済みです。

まとめ

この連載記事でご覧になったとおり、Workflow Engine の機能と InterSystems IRIS の相互運用性機能を合わせることで、他のビジネスソリューションではほとんど実現できないビジネス プロセスの実装において、驚異的な可能性を切り開くことができます。 最大限に活用するためには、技術的な知識が必要となる可能性がありますが、実際に必要な取り組みを投じる価値はあります。

0
0 23
お知らせ Mihoko Iijima · 9月 30, 2025

開発者の皆さん、こんにちは!本日(10月1日)よりコンテストへご応募いただけます💨

✅コンテスト詳細👉「第3回 InterSystems Japan 技術文書ライティングコンテスト 開催!

✅応募方法👉「記事の投稿方法:第 1 回技術文書ライティングコンテスト

✅応募記事一覧👉「技術文書ライティングコンテスト一覧

0
0 27
質問 m.fuku · 9月 24, 2025

IRIS Communityの再インストールを行ったところ

tomcat上で動作するJavaのWEBアプリケーションから

JDBC経由でのDB接続ができなくなりました。

他のSQLクライアントツールからは問題なく接続できていますので

接続情報やDBの起動状態には問題ないと考えています。

解決策をご指導頂ければ幸いです。

■環境

IRISバージョン:IRIS_Community-2025.2.0.227.0-win_x64

JDKバージョン:11.0.28

JDBCドライバ:intersystems-jdbc-3.2.0.jar

■事前作業

ライセンス有効期限が切れてサービス起動できなくなったため、以下投稿と同様、再インストールを行っています。

https://jp.community.intersystems.com/post/iris%E3%82%A4%E3%83%B3%E3%82…

ちなみに前回利用したバージョン(IRIS_Community-2024.2.0.247.0-win_x64)では

以下エラー(messages.log)となりサービス起動できなかったため

7
0 42
お知らせ Mihoko Iijima · 9月 25, 2025

開発者の皆さんこんにちは!

技術文書ライティングコンテストの開始(10月1日)まであと少しとなりました!💨

このお知らせでは、今年の賞品を発表いたします!

👀

🎁賞品情報🎁

審査員投票とコミュニティメンバーからの「いいね」の数の合計で順位を決定します。

1位~3位を受賞された方は、各順位に記載された賞品の中からお好きな1点をお選びいただけます。(1位の方は1~3位の賞品を、2位の方は2~3位の賞品をお選びいただけます)

🥇 1位

  • リカバリーウェア TENTIAL BAKUNEシリーズ
  • スマートリング Re・De Ring
  • アウトドアの体験ギフト EXCITING Gift Premium -エキサイティング プレミアム

🥈 2位

  • MYTREX DR. HEAT NECK
  • ソーダーストリーム TERRA スターターキット
  • アウトドアの体験ギフト EXCITING Gift -エキサイティング

🥉 3位

  • Bluetoothスピーカー
  • モレスキン クラシックダイアリー Large
  • スタバギフトカード(5000円)

🎁参加賞:投稿いただいた方全員に「モバイルバッテリー」をプレゼント!

1回目、2回目とは異なる賞品を!ということで賞品決めチームでいろいろ探してみました👀

高得点を狙う場合は、早めの投稿がおすすめです!(コミュニティメンバーからの「いいね」ポイントをより多くゲットできます!)

0
0 52
記事 Toshihiko Minamoto · 9月 25, 2025 8m read

REST レスポンスから IRIS データーベースに情報を保存する新しいプロジェクトがあります。 少なくとも 20 以上の個別の REST エンドポイントの情報を同期する必要があるため、それらのエンドポイントの結果を保存するために、ほぼ同じ数の ObjectScript クラスを作成しなければなりません。

ChatGPT を使って、それらのクラスを作成することはできますか? 答えは「できます」です。生成 AI を使って便利なものを作るのは初めてなので、素晴らしい機会だと思います。 スープを飲むキリンの写真を生成するのには飽きてきました…。

以下のようにして実現しました。

  • エンドポイントをクエリするために、「curl」を使ってサンプルの JSON REST の呼び出し出力を取得する。
  • ChatGPT にアクセスする(InterSystems は社員に会社全体で使用できるライセンスを提供しています)。
  • ChatGPT と以下のように会話する。

以下のリクエストを「Message ChatGPT」プロンプトに入力しました。

私: 次の JSON のデータを格納する ObjectScript クラスを生成してください。

JSON を入力する前に Return キーを押すと、ChatGPT から次のように指示されました。

ChatGPT: ObjectScript クラスの生成が必要な JSON 構造を提供してください。 サンプルの JSON オブジェクトがある場合は、それを貼り付けてください。それに対応する InterSystems ObjectScript クラスを作成します。

プロンプトに以下の内容を入力しました。

{
  "id": 335818632,
  "appId": 113,
  "appName": "Batch",
  "contentId": 182455380233,
  "subject": "Test Subject",
  "name": "Test email campaign name",
  "counters": {
    "processed": 3910,
    "deferred": 86,
    "unsubscribed": 17,
    "statuschange": 17,
    "bounce": 153,
    "mta_dropped": 8,
    "dropped": 299,
    "delivered": 3749,
    "sent": 3903,
    "click": 16,
    "open": 323
  },
  "lastProcessingFinishedAt": 1733232499000,
  "lastProcessingStartedAt": 1733232303000,
  "lastProcessingStateChangeAt": 1733232499000,
  "numIncluded": 4201,
  "processingState": "DONE",
  "scheduledAt": 1733232300000,
  "type": "BATCH_EMAIL"
}

ChatGPT の返答:

提供された JSON 構造にマッピングする InterSystems ObjectScript クラスです。

Class MyNamespace.MyJSONData Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyNamespace.Counters;Property lastProcessingFinishedAt As%BigInt;Property lastProcessingStartedAt As%BigInt;Property lastProcessingStateChangeAt As%BigInt;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%BigInt;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyNamespace.MyJSONData) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyNamespace.Counters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statuschange As%Integer;Property bounce As%Integer;Property mta_dropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

説明も提示されました。

このコードは基礎として最適ですが、自分の「MyPkg」というパッケージに対応するようにし、クラスに「EmaiCampaign」という名前を付けたいと思います。 また、NI を少々使用すると、「%BigInt」プロパティを生成した値が実は Linux 時間であり、プロパティは「%Library.PosixTime」である必要があることが分かります。

以下のようにリクエストしました(「~ください」と機会になぜ言ってしまうのかわかりませんが、親にそう育てられたからでしょう)

私: パッケージ名を「MyPkg」、クラスを「EmailCampaign」に変えて、もう一度クラスを作成し直してください。 また、プロパティの型を %BigInt から %Library.PosixTime に変更してください。

ChatGPT の返答:

指定されたパッケージ名とクラス名で ObjectScript クラスを更新しました。また、タイムスタンププロパティを %Library.PosixTime に更新しました。

Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyPkg.Counters;Property lastProcessingFinishedAt As%Library.PosixTime;Property lastProcessingStartedAt As%Library.PosixTime;Property lastProcessingStateChangeAt As%Library.PosixTime;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%Library.PosixTime;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyPkg.EmailCampaign) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyPkg.Counters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statuschange As%Integer;Property bounce As%Integer;Property mta_dropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

説明も提示されました。

コードをそのまま VSCode にコピーすると、波括弧に関する構文の問題がハイライトされました。 ObjectScript クラスでは内部クラス定義を使用できません。

ChatGPT に、MyPkg.Counters 内部クラスを別のクラスにして「波括弧」の問題を修正するように頼んでも「no-op」になるため、人の手でそのクラスを別のファイルに移動する必要があります。 ChatGPT は次のリクエストの後にそのクラスの名前を変更しました。

私: 記述されたとおりのクラスはコンパイルしません。 MyPkg.Counters 内部クラスをメインクラスから独自のクラスに移動して、MyPkg.CampaignCounters に名前を変更できますか?

ChatGPT の返答:

MyPkg.CampaignCounters クラスを独自のクラスに移動して、ObjectScript コードを更新しました。

Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyPkg.CampaignCounters;Property lastProcessingFinishedAt As%Library.PosixTime;Property lastProcessingStartedAt As%Library.PosixTime;Property lastProcessingStateChangeAt As%Library.PosixTime;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%Library.PosixTime;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyPkg.EmailCampaign) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyPkg.CampaignCounters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statuschange As%Integer;Property bounce As%Integer;Property mta_dropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

上記のコードを VSCode に貼り付けてコンパイルすると、コンパイラーは「%Object」という名前の型が ObjectScript に存在しないと通知しました。 IRIS ドキュメントによると、%JSON.Adaptor の %JSONImport() メソッドの最初のパラメーターは柔軟に設定できるようです。

「入力引数は、文字列またはストリームとしての JSON か、%DynamicAbstractObject のサブクラスのいずれかです。

最初のクラスで %OnJSONImport() の最初のパラメーターの「As %Object」プロパティを取り除き、2 つのクラスを個別のファイルに分けると、MyPkg.EmailCampaign クラスが正しくコンパイルされました。 ただし、MyPkg.CampaignCounters はコンパイルしませんでした。ChatGPT は(まだ)アンダースコアが ObjectScript で特殊文字(文字列連結演算子)であることを知りません。  

では、そのことを教えましょう。

私: ObjectScript では、アンダースコア文字「_」は特殊文字です。 名前にアンダースコアが使用されているプロパティをキャメルケース表記に変更してアンダースコアを削除してください。

ChatGPT の返答:

アンダースコアが使用された名前をキャメルケース表記に変換したプロパティでコードを更新しました。

Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As%Integer;Property appId As%Integer;Property appName As%String;Property contentId As%Integer;Property subject As%String;Property name As%String;Property counters As MyPkg.CampaignCounters;Property lastProcessingFinishedAt As%Library.PosixTime;Property lastProcessingStartedAt As%Library.PosixTime;Property lastProcessingStateChangeAt As%Library.PosixTime;Property numIncluded As%Integer;Property processingState As%String;Property scheduledAt As%Library.PosixTime;Property type As%String;ClassMethod%OnJSONImport(jsonObject As%Object, instance As MyPkg.EmailCampaign) As%Status
{
    Quit ..%JSONImport(jsonObject, .instance)
}
}

Class MyPkg.CampaignCounters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As%Integer;Property deferred As%Integer;Property unsubscribed As%Integer;Property statusChange As%Integer;Property bounce As%Integer;Property mtaDropped As%Integer;Property dropped As%Integer;Property delivered As%Integer;Property sent As%Integer;Property click As%Integer;PropertyopenAs%Integer;
}

説明も提示されました。

ChatGPT は、依頼されたことだけでなく、2 語で構成されたプロパティ名もキャメルケース表記に変更してくれました(statuschange)。同じように命名されているメインクラスの他のプロパティもすべてキャメルケース表記なので、この変更を維持します。

最後に生成されたコードでは 2 つの個別のファイルに分けられ(また %OnJSONImport() メソッドの定義から「As %Object」定義を削除して)、すべてのコードが正しくコンパイルされるようになりました。

これらの生成されたクラスは、求めているものの基礎として最適なコードです。このプロジェクトの他の REST データソースでもこのプロセスを繰り返して、大量の不要な入力作業を省きたいと思います。

0
0 23
記事 Hiroshi Sato · 9月 25, 2025 1m read

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

$System.Encryption.Base64Encodeに指定するデータは、UTF8にエンコードして渡す必要があります。

日本語が含まれるローカル変数をこのメソッドの引数として指定すると<ILLEGAL VALUE>エラーが返ります。

以下のようにUTF8に変換後引数として渡す必要があります。

 set wLineData=$ZCONVERT(wLineData, "O", "UTF8")

詳しくは以下をご参照ください。

ドキュメント: $System.Encryption.Base64Encodeの説明

0
0 16
記事 Hiroshi Sato · 9月 25, 2025 2m read

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

何の設定も行なっていない場合、GROUP BYやDISTINCTで指定したフィールドは大文字小文字を区別せずに全て大文字として処理されます。

これはGROUP BYやDISTINCTのグループ化がフィールドに対して定義された照合タイプに基づいて行われ、その文字列照合の既定値がSQLUPPERになっているためです。

以下のドキュメントに説明がある通り、DISTINCT は、フィールドに対して定義された照合タイプに基づいて、文字列値をグループ化します。

大文字/小文字の区別と DISTINCT の最適化

これを変更する方法は、以下の3種類になっています。

(A) %SQLSTRING または %EXACT照合関数を使用する
(B) フィールドの文字列照合を SQLSTRINGに変更する
 また、フィールドにインデックスが設定されている場合には、インデックスの文字列照合も SQLSTRINGに変更する
(C) 管理ポータルで設定を変更する 

※(B)について補足
・文字列照合をEXACTに設定しても動作しますが、一般的にはSQLSTRINGの使用が推奨されています。
・フィールドの文字列照合とインデックスの文字列照合は、同じ設定にすることが推奨されています。

※(C)の設定手順

0
0 21
記事 Mihoko Iijima · 9月 23, 2025 4m read

開発者の皆さん、こんにちは!

10月1日(水)から今年の「技術文書ライティングコンテスト」が始まります!💨みなさま、応募の準備は進んでいますか??👀

この記事では、昨年開催したコンテストにご応募いただいた素晴らしい作品を審査員コメントを添えてご紹介します。

(審査員コメントは昨年 11 月に開催したミートアップ内で行ったコンテスト表彰式で紹介した内容です)

@Akio Hashimoto さんが投稿された「Embedded Python を利用する時の注意点 

審査員コメント:

Embedded Pythonをこれから操作される人が同様の問題に遭遇したときの解決策が提示されているありがたい記事だと感じました。

昨年もコンテストに投稿いただき、今年同様に、これから体験される方向けの道標となるような素晴らしい記事を投稿いただいています。

@Yusuke Kojima さんが投稿された「FHIR Object Modelを使ったInteroperability開発

審査員コメント:

0
0 33
お知らせ Mihoko Iijima · 9月 9, 2025

開発者の皆さん、こんにちは!

今年で 3 回目となりますが、✍技術文書ライティングコンテスト✍ 開催します!

📣9/26更新:賞品、参加賞決定しました!

📣 9/29更新:コンテスト投稿一覧ページ準備完了です!

📣 11/6更新:応募期間を1週間延長し、応募締切は11月24日(月)に変更しました!

テーマはいつもと同じで InterSystems IRIS/InterSystems IRIS for Health に関連した内容であればどのような内容でもご応募いただけます。

🎁 参加賞:投稿いただいた方全員に「モバイルバッテリー」をプレゼント!

🏆 特別賞:選ばれた3作品に、今年も特別賞あります!詳細はこちら

コンテストへの応募はとても簡単です。2025年10月1日(水)~11月1724日(月)までの期間に開発者コミュニティに「IRISに関連した記事」を投稿してください。

もちろん!今年も🍆ボーナスポイント🍆あります!こちらをご参照ください!

1
0 100
記事 Megumi Kakechi · 9月 15, 2025 3m read

これは InterSystems FAQ サイトの記事です。
ビジネスサービスやビジネスオペレーションで EnsLib.CloudStorage.InboundAdapter アダプタを使用したり、%Net.Cloud.Storage.Client を使用することで、Amazon s3(クラウドストレージAPI)のファイルにアクセスすることが可能です。

いずれの場合も、事前に Javaランタイムをシステムにインストールし、インストールしたJavaランタイムの JAVA_HOME 情報を、管理ポータルにて設定する必要があります(手順は後述します)。


今回は、%Net.Cloud.Storage.Client クラスを使用したサンプルをご紹介します。
手順は以下のようになります。


【手順】

以下のS3パケットにアクセスする手順になります。

   

(1)  事前に、コマンドプロンプトにて aws コマンドを使用して動作確認をしておきます(S3に存在しているファイル一覧がプロンプトに返ればOKです)。

> aws s3 ls s3://kake-s3
2025-04-30 16:20:52         32 abc.txt
2025-04-30 16:14:00      21529 messages.log

もしくは

0
0 32
お知らせ Rie Tokue · 9月 9, 2025

   

いつもお世話になっております。

10月の開発者向けウェビナーの日時、内容が決まりました。

タイトル:「ベクトル検索でカスタマーサービスを向上 - 生成AIチャットボットの構築」

日時:10月16日(木)13時30分~14時

参加費無料・事前登録制

ご登録はこちらから

【概要】
IRISのベクトル検索機能を使用した生成AIチャットボットをInterSystems米国本社の教育サービスチームが開発しました。
全体アーキテクチャおよびこの構築を通じて学んだベストプラクティスをご紹介します。

本ウェビナーは2025年6月に米国フロリダ州で開催されたReady 2025のセッション
”Enhancing Customer Engagement with Vector Search - Building a AI Chatbot"の内容を日本語でお届けします

【こんな方にお勧め】
IRISのベクトル検索機能に関心のある方
IRISに蓄えられたデータの活用方法を検討されている方
生成AIチャットボットに興味のある方

ご多用中とは存じますが、皆様のご参加をお待ち申し上げております。

インターシステムズジャパン

0
0 44
質問 ima · 9月 1, 2025

1. 現象

>w $zv
IRIS for Windows (x86-64) 2024.3 (Build 217U) Thu Nov 14 2024 17:59:58 EST

大きなXMLファイル(約165MB)をライブラリー%XMLでパースすると、<FILEFULL>エラーが発生する。

エラーパート

    s libraryFile = "D:\iTunes3\iTunes Library.xml" ;サイズ=165M
    w !,"libraryFile = ",libraryFile
    w !,"##class(%File).GetFileSize(libraryFile)=",##class(%File).GetFileSize(libraryFile)
    w !,"s sc=##class(%XML.TextReader).ParseFile(libraryFile,.reader) 実行"
    Set sc = ##class(%XML.TextReader).ParseFile(libraryFile,.reader)
    w !,$SYSTEM.Status.GetErrorText(sc)
    q

2
0 64
記事 Hisa Unoura · 9月 4, 2025 9m read

開発者の皆様こんにちは。先日のWebinar「ベクトルであそぼう!」では、以下の内容でデータをベクトル化することの可能性をご紹介しました。

写真から魚の名前をあててみる

  • マルチモーダルモデル CLIP を利用して画像によるテキストの検索

ベクトルを「見える化」する

  • ベクトルを次元削減して 3 次元ベクトルに変換し、可視化

データの集まりを見る

  • K-Means によるデータのクラスタリング

変なデータ (=アノマリ) を見つける

  • K-Means による教師なしアノマリ検知や半教師ありアノマリ検知


一番お伝えしたかったのは 「データをベクトルに変換することで、データ利活用の幅が大きく広がる」 ということです。
本記事ではマルチモーダルAIおよびCLIPについておさらいし、Webinarでは時間の都合で触れきれなかったTips  - モダリティギャップというマルチモーダルモデル特有の現象についてお伝えします。

なお筆者は AI/機械学習の専門家ではありませんが、機械学習を利用したプロダクト・プロジェクトに携わり親しんでまいりました。ご質問・ご指摘などありましたらお気軽にコメント欄からお願いします。

マルチモーダル AI

近年、AI 分野では マルチモーダル AI が大きな注目を集めています。
「モーダル」とはデータの種類のことを指します。

0
0 45