13.12 JSON_TRANSFORMの演算子NESTED PATH

JSON_TRANSFORMの演算子NESTED PATHは、一連の操作を適用する範囲(データの特定の部分)を定義します。ネストしたパスによる操作の主なユースケースは、複数の配列要素の反復処理です。

有効範囲の限定のための構成として、ネストしたパス操作によって変更の対象をデータのサブセットに制限します。それ自体は、変更操作ではありません。

ネストしたパス操作の有効範囲内で実行される操作には、別のネストしたパス操作を含めることができます。そのため、ネストしたパス内でネストしたパスを使用でき、それを繰り返すことで、より広い有効範囲内に狭い有効範囲を定義して任意のレベルでデータを処理できます。特に、ネストしたパスを使用すると、任意の場所にネストした配列の要素を処理できます。

ネストした有効範囲は、演算子NESTED PATHの直後に続くターゲット・パスによって定義します(キーワードPATHは省略できます)。次に、そのパスの後に、カッコ(())で囲んでゼロ個以上の有効範囲指定操作のシーケンスを続けます。

ターゲット・パスのコンテキスト項目は、そのターゲットによるNESTED PATH操作が最上位(最も外側)のコンテキストにある場合は、そのパスで$を使用して指定します。それ以外の場合、つまり、そのターゲットによるNESTED PATH操作が別のNESTED PATHの内側にある場合は、@を使用してそれを指定します。

ターゲット・パスによって指定されているデータは、有効範囲指定操作のコンテキスト項目になります。そうした操作では、$ではなく@で示されます。

たとえば、'$.employees[*]'は最上位コンテキストでのターゲット・パスとして使用できます。'@.employees[*]'はネストした有効範囲でのターゲット・パスとして使用できます。対象とされるフィールドemployeesを持つオブジェクトは、最初のケースではトップ・レベルであり、2番目のケースではそれよりも下位のレベルです。

いずれのケースも、ターゲット・パスにより、配列employeesの各要素を有効範囲指定操作のコンテキスト項目として定義します。各操作は、これらの要素の1つずつに配列順に適用されます

同様に、'$.employees[2 to 10]'は、有効範囲指定操作を3番目から11番目の従業員に適用し、'$.employees[3,7]'は、それらの操作を4番目と7番目の従業員に順に適用します。(同様に、$のかわりに@を使用します)。

次のコードでは、ターゲット・パスは$.LineItems[*]であるため、カッコで囲まれた操作のシーケンスに現れる@$.LineItems[*]の略語になります。このコードは、配列LineItemsの各要素のUnitPrice1.02で乗算して変更します。

json_transform(data,
               NESTED PATH '$.LineItems[*]'
                 (SET '@Part.UnitPrice' = PATH '@.UnitPrice * 1.02'))

配列の各要素を対象とするには、配列自体ではなく、値が配列である対象フィールドの名前の後に明示的に[*]を含める必要があります。暗黙的な反復はありません。有効範囲が設定された操作では、特定の配列要素の参照(3番目の要素@[2]など)が必要な場合は、配列自体('$.employees'など)を対象にできます。ただし、これは一般的なユースケースではありません。

ネストしたパス有効範囲内の操作のLHSでは、$を使用できません。そのかわりに、@を使用する必要があります。これは、ネストした有効範囲の変換/変更が、その有効範囲に限定されるという別の方法であり、実行される操作はその範囲外では動作できません。

ただし、有効範囲指定操作のRHSでは$を使用できます。たとえば、このコードでは、まず各従業員に10%の昇給(*係数1.1)を与えてから、各従業員に同じ賞与($.department.bonusの値)を割り当てます。

json_transform(data,
               NESTED PATH '$.employees[*]'
                 (SET '@.salary' = PATH '@.salary * 1.1',
                  SET '@.bonus'  = PATH '$.department.bonus'))

有効範囲指定操作のRHSに現れる$は、常にjson_transform呼出しの最上位(最も外側)のコンテキストを参照します。

ネストした操作内(再掲):

  • @は、ネストしたパスによって対象とされるデータを参照します。

  • $は、最上位(最も外側)のコンテキスト項目を参照し、操作のRHSでのみ使用できます。

例13-21 JSON_TRANSFORMのKEEPによるプルーニングを制限するための、NESTED PATHを使用した有効範囲の限定

この例では、KEEP操作の有効範囲を特定のネストしたパスに制限します。その有効範囲外のデータはプルーニングされません。この結果は、UnitPriceQuantityを除くすべてのフィールドが削除された、配列LineItemsの要素のみです。

json_transform(data,
               NESTED PATH '$.LineItems[*]'
                 (KEEP '@.Part.UnitPrice', '@.Quantity'))

例13-22 JSON_TRANSFORM: NESTED PATHの使用による配列要素の集計

この例では、j_purchaseorder.data内のすべての文書をオンザフライで変換して新しいフィールドOrderTotal (発注書内のすべての明細項目エントリの原価)を追加します。これは、まず各明細項目の原価を計算し、次にそれらの原価を合計することで実現されます。明細項目原価は新規フィールド内の明細項目オブジェクトに追加されます(それは、これらの項目原価が合計されて注文金額が生成された後に削除されます)。

これらの操作は次の順序で実行されます:

  1. 操作NESTED PATHSETとともに使用して、新しいフィールドLineItemTotal (単価から計算される)を配列LineItemsの各要素に追加します。

  2. 操作SETを使用して、新しい最上位フィールドOrderTotalを追加します。その値は、すべてのLineItemTotal値の合計です。

  3. 操作REMOVEを使用して、明細項目からLineItemTotalフィールドを削除します。

これはSELECT操作のみであることに注意してください。この例では、変換された文書はj_purchaseorder.dataに格納されません。それを行うには、UPDATE文を使用します。

SELECT json_transform(
         data, 
         NESTED PATH '$.LineItems[*]'
           (SET '@.LineItemTotal' = PATH '@.Part.UnitPrice * @.Quantity'),
         SET '$.OrderTotal' = PATH '$.LineItems[*].LineItemTotal.sum()',
         REMOVE '$.LineItems[*].LineItemTotal')
  FROM j_purchaseorder;

演算子NESTED PATHに使用できるハンドラはありません