FHIR クエリ フォールディング パターン

この記事では、FHIR 内で効果的なクエリ フォールディングを可能にするための Power Query パターンについて説明します。 ここでは、お客様が FHIR 用の Power Query コネクタを使い慣れていて、FHIR での Power Query フォールディングの基本的な目的と原則を理解していることを前提としています。

このドキュメントの使用方法

このドキュメントで示す例の一覧は完全なものではなく、クエリがフォールディングされるすべての検索パラメーターを網羅しているわけではありません。 ただし、お客様が目にすると考えられるクエリとパラメーターの種類については例を示します。 フィルター クエリ式を作成する場合は、フィルター処理を行うパラメーターを次のどれにするかを検討してください。

  • プリミティブ型 (Patient.birthDate など)。
  • 複合型。これは Power Query でレコードになります (Patient.meta など)。
  • プリミティブ型の配列。これは Power Query でリストになります (Patient.meta.profile など)。
  • 複合型の配列。これは Power Query でテーブルになります (多数の列を含む Observation.code.coding など)。

次に、以下の例の一覧を参照してください。 また、このような種類のフィルター処理パターンを、入れ子になった複数レベルのフィルター ステートメント内で組み合わせる例も示しています。 最後に、この記事では、複合検索パラメーターにフォールディングされる、より複雑なフィルター式について説明します。

各例では、フィルター式 (Table.SelectRows) と、各フィルター ステートメントのすぐ上に、式がどのような検索パラメーターと値にフォールディングされるかを説明するコメント // Fold: ... があります。

プリミティブ型に対するフィルター処理

ルート プロパティはリソースのルートに置かれ、通常はプリミティブ型 (文字列や日付など) ですが、コーディング フィールドとすることもできます (例: Encoding.class)。 このセクションでは、さまざまな種類のプリミティブ ルート レベル プロパティを検索する例を示します。

生年月日で患者をフィルター処理する:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "birthdate=lt1980-01-01"
    FilteredPatients = Table.SelectRows(Patients, each [birthDate] < #date(1980, 1, 1))
in
    FilteredPatients

and を使用して、1970 年代のみの期間の生年月日で患者をフィルター処理する:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "birthdate=ge1970-01-01&birthdate=lt1980-01-01"
    FilteredPatients = Table.SelectRows(Patients, each [birthDate] < #date(1980, 1, 1) and [birthDate] >= #date(1970, 1, 1))
in
    FilteredPatients

or を使用して、1970 年代以外の生年月日で患者をフィルター処理する:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "birthdate=ge1980-01-01,lt1970-01-01"
    FilteredPatients = Table.SelectRows(Patients, each [birthDate] >= #date(1980, 1, 1) or [birthDate] < #date(1970, 1, 1))
in
    FilteredPatients

アクティブな患者の代替検索:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "active=true"
    FilteredPatients = Table.SelectRows(Patients, each [active])
in
    FilteredPatients

アクティブではない患者 (参照不可なものを含む可能性がある) の代替検索:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "active:not=true"
    FilteredPatients = Table.SelectRows(Patients, each [active] <> true)
in
    FilteredPatients

男性の患者のみを保持するためのフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "gender=male"
    FilteredPatients = Table.SelectRows(Patients, each [gender] = "male")
in
    FilteredPatients

男性ではない患者のみを保持するためのフィルター処理 (その他を含む):

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "gender:not=male"
    FilteredPatients = Table.SelectRows(Patients, each [gender] <> "male")
in
    FilteredPatients

状態 final (コード) を使用した Observations のフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "status=final"
    FilteredObservations = Table.SelectRows(Observations, each [status] = "final")
in
    FilteredObservations

複合型に対するフィルター処理

最終更新日時に対するフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "_lastUpdated=2010-12-31T11:56:02.000+00:00"
    FilteredPatients = Table.SelectRows(Patients, each [meta][lastUpdated] = #datetimezone(2010, 12, 31, 11, 56, 2, 0, 0))
in
    FilteredPatients

class system および code (コーディング) に基づく Encounter のフィルター処理:

let
    Encounters = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Encounter" ]}[Data],

    // Fold: "class=s|c"
    FilteredEncounters = Table.SelectRows(Encounters, each [class][system] = "s" and [class][code] = "c")
in
    FilteredEncounters

code (コーディング) に基づく Encounter のフィルター処理:

let
    Encounters = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Encounter" ]}[Data],

    // Fold: "class=c"
    FilteredEncounters = Table.SelectRows(Encounters, each [class][code] = "c")
in
    FilteredEncounters

class system のみ (コーディング) に基づく Encounter のフィルター処理:

let
    Encounters = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Encounter" ]}[Data],

    // Fold: "class=s|"
    FilteredEncounters = Table.SelectRows(Encounters, each [class][system] = "s")
in
    FilteredEncounters

Observation.subject.reference (参照) に基づく Observations のフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "subject=Patient/1234"
    FilteredObservations = Table.SelectRows(Observations, each [subject][reference] = "Patient/1234")
in
    FilteredObservations

Observation.subject.reference (参照) でのバリエーションに基づく Observations のフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "subject=1234,Patient/1234,https://myfhirservice/Patient/1234"
    FilteredObservations = Table.SelectRows(Observations, each [subject][reference] = "1234" or [subject][reference] = "Patient/1234" or [subject][reference] = "https://myfhirservice/Patient/1234")
in
    FilteredObservations

同じ value (数量)、に基づく Quantity のフィルター処理:

let
    ChargeItems = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "ChargeItem" ]}[Data],

    // Fold: "quantity=1"
    FilteredChargeItems = Table.SelectRows(ChargeItems, each [quantity][value] = 1)
in
    FilteredChargeItems

value (数量) より大きい、に基づく Quantity のフィルター処理:

let
    ChargeItems = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "ChargeItem" ]}[Data],

    // Fold: "quantity=gt1.001"
    FilteredChargeItems = Table.SelectRows(ChargeItems, each [quantity][value] > 1.001)
in
    FilteredChargeItems

value system および code (数量) を使用した Quantity のフィルター処理:

let
    ChargeItems = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "ChargeItem" ]}[Data],

    // Fold: "quantity=lt1.001|s|c"
    FilteredChargeItems = Table.SelectRows(ChargeItems, each [quantity][value] < 1.001 and [quantity][system] = "s" and [quantity][code] = "c")
in
    FilteredChargeItems

(期間) 以降の開始に基づく、period のフィルター処理:

let
    Consents = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Consent" ]}[Data],

    // Fold: "period=sa2010-01-01T00:00:00.000+00:00"
    FiltertedConsents = Table.SelectRows(Consents, each [provision][period][start] > #datetimezone(2010, 1, 1, 0, 0, 0, 0, 0))
in
    FiltertedConsents

(期間) 以前の終了に基づく、period のフィルター処理:

let
    Consents = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Consent" ]}[Data],

    // Fold: "period=eb2010-01-01T00:00:00.000+00:00"
    FiltertedConsents = Table.SelectRows(Consents, each [provision][period][end] < #datetimezone(2010, 1, 1, 0, 0, 0, 0, 0))
in
    FiltertedConsents

複合型のテキスト フィールドのフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "code:text=t"
    FilteredObservations = Table.SelectRows(Observations, each [code][text] = "t")
in
    FilteredObservations

テキスト フィールドのフィルター処理 (次の値で始まる):

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "code:text=t"
    FilteredObservations = Table.SelectRows(Observations, each Text.StartsWith([code][text], "t"))
in
    FilteredObservations

リストのプロパティに対するフィルター処理

profile に基づく Patients のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "_profile=http://myprofile"
    FilteredPatients = Table.SelectRows(Patients, each List.MatchesAny([meta][profile], each _ = "http://myprofile"))
in
    FilteredPatients

カテゴリに基づく AllergyIntolerance のフィルター処理:

let
    AllergyIntolerances = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "AllergyIntolerance" ]}[Data],

    // Fold: "category=food"
    FilteredAllergyIntolerances = Table.SelectRows(AllergyIntolerances, each List.MatchesAny([category], each _ = "food"))
in
    FilteredAllergyIntolerances

欠落カテゴリに基づく AllergyIntolerance のフィルター処理:

let
    AllergyIntolerances = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "AllergyIntolerance" ]}[Data],

    // Fold: "category:missing=true"
    FilteredAllergyIntolerances = Table.SelectRows(AllergyIntolerances, each List.MatchesAll([category], each _ = null))
in
    FilteredAllergyIntolerances

よりシンプルな形式の欠落カテゴリに基づく AllergyIntolerance のフィルター処理:

let
    AllergyIntolerances = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "AllergyIntolerance" ]}[Data],

    // Fold: "category:missing=true"
    FilteredAllergyIntolerances = Table.SelectRows(AllergyIntolerances, each [category] = null)
in
    FilteredAllergyIntolerances

テーブルのプロパティに対するフィルター処理

正確な姓に基づく患者のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "family:exact=Johnson"
    FilteredPatients = Table.SelectRows(Patients, each Table.MatchesAnyRows([name], each [family] = "Johnson"))
in
    FilteredPatients

次の値で始まる姓に基づいた Patients のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "family=John"
    FilteredPatients = Table.SelectRows(Patients, each Table.MatchesAnyRows([name], each Text.StartsWith([family], "John")))
in
    FilteredPatients

John または Paul で始まる姓に基づいた Patients のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "family=John,Paul"
    FilteredPatients = Table.SelectRows(Patients, each Table.MatchesAnyRows([name], each Text.StartsWith([family], "John") or Text.StartsWith([family], "Paul")))
in
    FilteredPatients

John で始まる姓と、Paul で始まる名に基づいた Patients のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "family=John&given=Paul"
    FilteredPatients = Table.SelectRows(
        Patients,
        each
            Table.MatchesAnyRows([name], each Text.StartsWith([family], "John")) and
            Table.MatchesAnyRows([name], each List.MatchesAny([given], each Text.StartsWith(_, "Paul"))))
in
    FilteredPatients

Goal の期限日に対するフィルター処理:

let
    Goals = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Goal" ]}[Data],

    // Fold: "target-date=gt2020-03-01"
    FilteredGoals = Table.SelectRows(Goals, each Table.MatchesAnyRows([target], each [due][date] > #date(2020,3,1)))
in
    FilteredGoals

識別子に基づく患者のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "identifier=s|v"
    FilteredPatients = Table.SelectRows(Patients, each Table.MatchesAnyRows([identifier], each [system] = "s" and _[value] = "v"))
in
    FilteredPatients

Observation コード (CodeableConcept) に対するフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "code=s|c"
    FilteredObservations = Table.SelectRows(Observations, each Table.MatchesAnyRows([code][coding], each [system] = "s" and [code] = "c"))
in
    FilteredObservations

Observation のコードとテキスト (CodeableConcept) に対するフィルター処理 (CodeableConcept):

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "code:text=t&code=s|c"
    FilteredObservations = Table.SelectRows(Observations, each Table.MatchesAnyRows([code][coding], each [system] = "s" and [code] = "c") and [code][text] = "t")
in
    FilteredObservations

入れ子になった複数レベルのプロパティのフィルター処理

John で始まる姓と、Paul で始まる名に基づいた Patients のフィルター処理:

let
    Patients = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Patient" ]}[Data],

    // Fold: "family=John&given=Paul"
    FilteredPatients =
        Table.SelectRows(
            Patients,
            each
                Table.MatchesAnyRows([name], each Text.StartsWith([family], "John")) and
                Table.MatchesAnyRows([name], each List.MatchesAny([given], each Text.StartsWith(_, "Paul"))))
in
    FilteredPatients

Observations からのバイタル サインのみをフィルター処理する:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "category=vital-signs"
    FilteredObservations = Table.SelectRows(Observations, each Table.MatchesAnyRows([category], each Table.MatchesAnyRows([coding], each [code] = "vital-signs")))
in
    FilteredObservations

system と code を使用したカテゴリ coding に基づいて Observations をフィルター処理する:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "category=s|c"
    FilteredObservations = Table.SelectRows(Observations, each Table.MatchesAnyRows([category], each Table.MatchesAnyRows([coding], each [system] = "s" and [code] = "c")))
in
    FilteredObservations

複数のカテゴリ (OR) に基づいて Observations をフィルター処理する:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "category=s1|c1,s2|c2"
    FilteredObservations =
        Table.SelectRows(
            Observations,
            each
                Table.MatchesAnyRows(
                    [category],
                    each
                        Table.MatchesAnyRows(
                            [coding],
                            each 
                                ([system] = "s1" and [code] = "c1") or
                                ([system] = "s2" and [code] = "c2"))))
in
    FilteredObservations

テーブル内の入れ子になったリストのフィルター処理:

let
    AuditEvents = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "AuditEvent" ]}[Data],

    // Fold: "policy=http://mypolicy"
    FilteredAuditEvents = Table.SelectRows(AuditEvents, each Table.MatchesAnyRows([agent], each List.MatchesAny([policy], each _ = "http://mypolicy")))
in
    FilteredAuditEvents

複合検索パラメーターを使用したフィルター処理

FHIR には複合検索パラメーターが用意されています。これを使用すると、リソース内またはリソースのルートにある複合型に基づいて複数のフィールドを同時にフィルター処理することができます。 たとえば、特定のコード および 特定の値 (code-value-quantity 検索パラメーター) を使用して Observations を検索できます。 FHIR 用の Power Query コネクタでは、このような複合検索パラメーターにマップされたフィルター式の認識を試みます。 このセクションでは、これらのパターンの例をいくつか示します。 FHIR データの分析の状況では、特に Observation リソースに対する複合検索パラメーターが重要です。

code および value quantity (身長が 150 を超える) に基づいた Observations のフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "code-value-quantity=http://loinc.org|8302-2$gt150"
    FilteredObservations = Table.SelectRows(Observations, each Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8302-2") and [value][Quantity][value] > 150)
in
    FilteredObservations

component code および value quantity (最高血圧が 140 を超える) に基づいた Observations のフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "component-code-value-quantity=http://loinc.org|8480-6$gt140"
    FilteredObservations = Table.SelectRows(Observations, each Table.MatchesAnyRows([component], each Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8480-6") and [value][Quantity][value] > 140))
in
    FilteredObservations

複数の component code value quantity (AND) (最低血圧が 90 より高く、かつ 最高血圧が 140 を超える) に基づくフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "component-code-value-quantity=http://loinc.org|8462-4$gt90&component-code-value-quantity=http://loinc.org|8480-6$gt140"
    FilteredObservations = 
        Table.SelectRows(
            Observations, 
            each 
                Table.MatchesAnyRows(
                    [component],
                    each 
                        Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8462-4") and [value][Quantity][value] > 90) and 
                        Table.MatchesAnyRows([component], each Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8480-6") and [value][Quantity][value] > 140))
in
    FilteredObservations

複数の component code value quantity (OR) (最低血圧が 90 より高いか、または 最高血圧が 140 を超える) に基づくフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "component-code-value-quantity=http://loinc.org|8462-4$gt90,http://loinc.org|8480-6$gt140"
    FilteredObservations = 
        Table.SelectRows(
            Observations, 
            each 
                Table.MatchesAnyRows(
                    [component], 
                    each 
                        (Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8462-4") and [value][Quantity][value] > 90) or
                         Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8480-6") and [value][Quantity][value] > 140 ))
in
    FilteredObservations

リソースのルート上、またはコンポーネント配列内にある複数の code value quantity に基づいた Observations のフィルター処理:

let
    Observations = Fhir.Contents("https://myfhirserver.azurehealthcareapis.com", null){[Name = "Observation" ]}[Data],

    // Fold: "combo-code-value-quantity=http://loinc.org|8302-2$gt150"
    FilteredObservations =
        Table.SelectRows(
            Observations,
            each 
                (Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8302-2") and [value][Quantity][value] > 150) or
                (Table.MatchesAnyRows([component], each Table.MatchesAnyRows([code][coding], each [system] = "http://loinc.org" and [code] = "8302-2") and [value][Quantity][value] > 150)))
in
    FilteredObservations

まとめ

クエリ フォールディングにより、Power Query フィルター式は FHIR 検索パラメーターに変換されます。 FHIR 用の Power Query コネクタでは、特定のパターンを認識し、一致する検索パラメーターの識別を試みます。 これらのパターンの認識は、より効率的な Power Query 式を記述する上で役立ちます。

次のステップ

この記事では、FHIR 検索パラメーターにフォールディングされるいくつかの種類のフィルター式について説明しました。 次は、FHIR リソース間のリレーションシップの確立に関するページを参照してください。