記事
· 2023年10月2日 8m read

FHIRリポジトリ導入時の備忘録として

皆さまこんにちは。
IRIS for Healthを用いてFHIRの開発に携わっている者です。

FHIRリポジトリの導入を検討している方々に向けて、足がかり的な記事になればと思い投稿致します。

 

<アジェンダ>
■IISでの環境構築
■POSTMANを利用しないリソースへのデータアクセス
■Patientリソースの作成について
■FHIRリポジトリを使ってみての感想

■おまけEmbedded Pythonを使って、サンプルファイルからFHIRリソースへアクセスする方法

 

■IISでの環境構築

 以前IISを利用しての環境構築を投稿しましたが、少し詳細に記載致します。

 ①FHIR endpointの作成

  「URL」は極力短い名前が良いと考えます(例:「/test」)

  

 ②IISの設定

  「エイリアス」をendpointの「URL」に揃える(例:「test」)

  「物理パス」は任意

   

  ハンドラーマッピング

   「要求パス」は「*」
   「モジュール」はCSPms
   「名前」は任意
   「要求の制限」では、「マップ」タブのチェックボックスをOFF

   

 

■POSTMANを利用しないリソースへのデータアクセス

  Web APIの設計・開発・テストを行う際に、最初に候補として名前が挙がるのがPOSTMANだと思います。
  とても使いやすく、機能が充実しているため開発・テストはこれのみで問題無いレベルです。

   https://www.postman.com/

 

  ただ今回は折角なのでPOSTMANを使用せず、ObjectscriptでFHIRリソースの登録・取得を確認する方法を記載致します。
  FHIR機能とinteroperabilityを組み合わせる際も、Objectscriptで記述出来る方法を知っておいた方が色々都合が良いと考えます。

 

   コードの書き方は、下記ドキュメントに記載されています。

   https://docs.intersystems.com/irisforhealth20231/csp/docbookj/DocBook.UI.Page.cls?KEY=HXFHIR_server_applications

 

  上記関数以外にも簡易的に使用できる関数があるので、そちらを利用して患者リソースの登録・更新・取得・検索・削除を行ってみます。

   サンプルソース:https://github.com/ikeda-kou/writingContest.git

     ※GetEndpoint()・・・エンドポイント取得関数

       JsonAnalysis()・・・jsonを見やすくパースする関数

 

   【登録】

     Create()関数の第二引数は、FHIRリソース(例:Patientリソース)で%Stream型か%String型の何れかを受け取ります

ClassMethod POSTTest()
{
    s clientObj = ##class(HS.FHIRServer.RestClient.FHIRService).CreateInstance(..GetEndpoint())
    s res = clientObj.Create("Patient", ..GetPatient().%ToJSON())
    
    w !,$$$FormatText("id=%1, status=%2", res.Id, res.Status)
}

  ※テストデータは、jpcoreのサンプルデータを使用しています。

ClassMethod GetPatient() As %DynamicObject [ CodeMode = expression ]
{
{
  "resourceType" : "Patient",
  "meta" : {
    "profile" : [
      "http://jpfhir.jp/fhir/core/StructureDefinition/JP_Patient"
    ]
  },
 
 ~~ 略 ~~
 
  "address" : [
    {
      "text" : "東京都新宿区",
      "postalCode" : "1600023"
    }
  ]
}
}

   登録したデータは^HSFNNS.PatientDに登録されます。

    →「03」はエンドポイントの作成回数との事

     

 

   【更新】

     同じリソースIDで更新データを作成します。

      →サンプルは苗字を山田→海田へ変更する

ClassMethod PUTTest(id As %String)
{
	s clientObj = ##class(HS.FHIRServer.RestClient.FHIRService).CreateInstance(..GetEndpoint())
	
	s json = ..GetPatient()
	s json.id = id
	s json.name."0".family = "海田"
	s res = clientObj.Update("Patient", id, json.%ToJSON())
	
	w !,$$$FormatText("id=%1, status=%2", res.Id, res.Status)
}

 

   【取得】

     リソースIDを使用して、データの取得を行います。

     戻り値の「.Json」に取得したリソースがJSON形式で格納されています。

ClassMethod GETTest(id As %String)
{
	s clientObj = ##class(HS.FHIRServer.RestClient.FHIRService).CreateInstance(..GetEndpoint())
	s res = clientObj.Read("GET", "Patient", id)
	
	d ..JsonAnalysis(res.Json)
}

   ↓ターミナルでの実行サンプル

   

 

   【検索】

     検索を行い、Bundleリソースとして結果を受け取ります。

ClassMethod SearchTest(patientId As %String)
{
	s clientObj = ##class(HS.FHIRServer.RestClient.FHIRService).CreateInstance(..GetEndpoint())
	s res = clientObj.Search("GET", "Patient", , , "identifier="_patientId)
	
	d ..JsonAnalysis(res.Json)
}

 

   【削除】

     指定したリソースIDを削除します。

ClassMethod DELETETest(id As %String)
{
	s clientObj = ##class(HS.FHIRServer.RestClient.FHIRService).CreateInstance(..GetEndpoint())
	s res = clientObj.Delete("Patient", id)
	
	w !,res.Status
}

 

  上記関数が無事に実行できれば、Interoperabilityのオペレーション「HS.FHIRServer.Interop.Operation」にメッセージを投げても問題無く動作します。

   ※これで、InteroperabilityでのFHIR実装がスムーズに行えると思います。

 

■Patientリソースの作成について
  IRIS内でPatientリソースデータを作成する方法は、私の知っている中では下記3つの方法があります。

  1. FHIRTempleteを利用する
  2. 自力でJSONを記述する (前述したGetPatient()メソッド等)
  3. HS.FHIR.DTL.vR4.Model.Resourceのクラスを利用する


  1. FHIRTempleteを利用する

   https://github.com/Intersystems-jp/JSONTemplate

   公式ではこちらを利用しての運用をすすめているようです。

    →メンテナンス性が高く、packageのバージョンアップにも対応し易い

 

  しかし、FHIRTemplate.Patient.clsをそのまま利用するのであれば、サンプルデータの「extension」を入力するフィールドがありません。
  「extension」を出力するのであれば、下記何れかの方法を行う必要があります。

  •  JSON化した後、追加を行う。
  • FHIRTemplate.Patient.clsをExtendして、継承したクラスにextensionプロパティを追加する
  • FHIRTemplate.Resource.clsをExtendして新規Patientクラスを作成する

 

  3. HS.FHIR.DTL.vR4.Model.Resourceのクラスを利用する

   少々癖が強いものの、簡易的な利用であればボチボチ使えるのでサンプルを作成してみました。

   R4用のパッケージなので、今後のアップデートを踏まえてスキーマを変数としています。

 

   関数の最後にある「ToJSON」関数を実行すると、戻り値として%Stream型のPatientリソースが返ってきます。

ClassMethod MakePatient(schema As %String, ver As %String) As %Stream.TmpCharacter
{
    s o = $ClassMethod(schema_"Resource.Patient", "%New")
    
    // meta
    s o.meta = $ClassMethod(schema_"Base.Meta", "FromJSONHelper", {
        "profile" : [ "http://jpfhir.jp/fhir/core/StructureDefinition/JP_Patient" ]
    }, ver)

    ~~ 略 ~~
    
    // address
    d o.address.Insert($ClassMethod(schema_"Datatype.Address", "FromJSONHelper", {
        "text" : "東京都新宿区",
        "postalCode" : "1600023"
    }, ver))
    
    
    return o.ToJSON()
}

 

  戻り値をさらにJSON型に変換する場合は、下記コマンドを実行する。

   

 

 【使用した所感】

   両者を使用した所感を下記に記載致します。
   ※あくまで主観で記載しているので、参考程度に捉えていただけると幸いです。

    HS.FHIR.DTL.vR4.Model.Resourceパッケージ
     メリット
      ・リソースを作成するクラスとしては完成しているので、そのままで使用可能
      ・各プロパティの型が決まっている為、コーディングミスやマッピングミスが減る

     デメリット
      ・パッケージのバージョンアップ対応が手間かも
      ・コーディング量が多い為可読性が下がる

    FHIRTemplateパッケージ
     メリット
      ・メンテナンス性が高く自由な調整が可能
      ・コーディング量が少なく可読性が高い

     デメリット
      ・カスタマイズが必要になるリソースが多いイメージ

 

■FHIRリポジトリを使ってみて

 FHIR環境の構築と聞いて、二の足を踏んでしまう方もいらっしゃるかと思います。
 しかしIRISを使う事で、下記FHIRで必要な環境が容易に構築する事が可能となります。
   ・FHIRリポジトリ、FHIRサーバ等々
   ・REST API
   ・機器接続等(interopearbility[相互運用])

 

 実際に作業を行ってみると、FHIR環境の導入へのハードルがかなり低いと感じました。
  # むしろFHIRリソースへのマッピング作業の方がハードルが高く感じます。

 

 ドキュメントもIRISのバージョンが上がるごとにFHIR関連の記事が増加しており、充実感を覚えます。
  ※ただし、管理ポータルのHealth系画面は英語で構成されおり、ドキュメントはそれらを全て翻訳しているため、項目名に差異が発生しています。
   多少の慣れが必要。今後の修正に期待致します。

 

 

■おまけEmbedded Pythonを使って、サンプルファイルにアクセスしFHIRリソースへアクセスする方法

 

<アジェンダ>

■準備

■Embedded Python実行

■所感

 

■準備

  先ず管理ポータルからサービスを1つ有効にする必要があります。

  [システム管理] > [セキュリティ] > [サービス] %Service_CallInの「サービス有効」「パスワード」にチェックを入れます。

   

    

  サンプルファイルを[IRISインストールディレクトリ]\lib\python 直下に配置します。

   

 

   [IRISインストールディレクトリ]\bin にてコマンドプロンプトを立ち上げ、下記を入力します。

   set IRISUSERNAME=<user_name>
   set IRISPASSWORD=<password>
   set IRISNAMESPACE=<name_space>

   

 

■Embedded Python実行
 全ての準備が終わったら、サンプルファイルを実行します。

 コマンドは下記になります。

 irispython D:\IRIS\lib\python\fhir.py GETTest -i 2276

 

 

■所感

 そもそもRest APIを使用してFHIRリポジトリが構築できるので、直接Embedded Pythonを使用してFHIRリポジトリへアクセスする機会はないかもしれません。

 ただ、このような簡単な手順でPythonとIRISを連携させる事ができます。

 夢が広がりますね。
 

 ※ただし、pythonは3.9.5で固定されている為(IRIS 2023.1.1.380)、バージョン管理は注意が必要です。

 

ディスカッション (3)2
続けるにはログインするか新規登録を行ってください

こんにちは。初めまして。
こちらの投稿について、1点質問がございます。

REST APIを作成して、FHIRリポジトリからPatient情報を取得する際、
登録されている全リソースをGETすることは可能でしょうか。

Documentationで記載されていたGETのコード(※)では、
指定したIDのリソースしか登録できなかったので、
全件取得する方法があるのかと疑問になり質問させていただきました。

https://docs.intersystems.com/irisforhealth20231/csp/docbookj/DocBook.UI.Page.cls?KEY=HXFHIR_server_applications

よろしくお願いいたします。

ご質問ありがとうございます。

回答が遅くなり大変申し訳ありません。

私の記憶している範囲ですが、GETでも名称検索等で複数リソースを取得する事は可能です。

 →サンプルでは、「Search」が該当しており、検索文言の変更で全リソースを対象にすれば良いと思います。


 →Documentのサンプルソースで対応するのであれば、下記になります。

set request.RequestPath = "/Patient" // リソースIDは省略
set request.QueryString = "xxx" // 全リソースを検索対象とする検索文言を設定



しかし、最大取得リソース数が設定されている為、その件数を超えて取得する事は出来ません。

 →エンドポイントの設定の「Max Search Results」の設定値に依存していたと記憶しています。


全ての患者リソースを取得するのであれば、Bulk FHIR Coordinatorの機能を使うと実現できるかもしれません。

 ※私もこの機能は使ったことがないので、求める回答になっていなかったら申し訳ありません。


【以下は非推奨です!】

※若しくは・・・ですが、SQLで「HSFXXS.Patient」を検索する・・・方法もあります。

エンドポイントの作成回数でテーブル名の「XX」が変わるので、適宜対応できるよう工夫すれば実現可能かと思います

ご回答ありがとうございます。
また、返信ができておらず申し訳ございません。

私の記憶している範囲ですが、GETでも名称検索等で複数リソースを取得する事は可能です。

 →サンプルでは、「Search」が該当しており、検索文言の変更で全リソースを対象にすれば良いと思います。

 こちらの内容を実際に試してみたところ、求めていたことを実現することができました。
ありがとうございました。