パス式の使用

パス式は、階層的に構造化されたデータ内を移動するために使用します。Oracle NoSQL Databaseは、配列やレコードなどの様々な複合データ型をサポートしています。パス式を使用して、様々な複合データ型を操作する方法について学習します。

例のとおりに操作する場合は、スクリプトbaggageschema_loaddata.sqlをダウンロードして、次に示すように実行します。このスクリプトにより、例で使用する表が作成され、表にデータがロードされます。

KVSTOREまたはKVLiteを起動し、SQL.shellを開きます。
java -jar lib/kvstore.jar kvlite -secure-config disable
java -jar lib/sql.jar -helper-hosts localhost:5000 -store kvstore
loadコマンドを使用して、スクリプトを実行します。
load -file baggageschema_loaddata.sql

内部変数および別名の使用

Oracle NoSQL Databaseでは、内部変数の暗黙的な宣言も可能です。内部変数は、それを宣言する式の実行中に値にバインドされます。

問合せの表名の後に表の別名を付けることができます。表の別名は、基本的に、指定された表の行全体にわたる変数です。別名が指定されていない場合は、問合せでのスペルに従って表の名前を使用し、内部的に作成されます。

例1: 特定の予約コードのチケット番号と乗客の詳細を検索します。
SELECT bagDet.ticketNo, bagDet.fullName, bagDet.contactPhone FROM BaggageInfo bagDet
WHERE confNo="QB1O0J"

説明: この問合せでは、特定の予約コードのフルネーム、チケット番号、連絡先電話など、静的フィールドの値をフェッチします。BaggageInfo表の表の別名を使用します。

出力:
{"ticketNo":1762390789239,"fullName":"Zina
      Christenson","contactPhone":"987-210-3029"}

表の別名がドル記号($)で始まる場合、実際には、名前が別名である変数の変数宣言として機能します。この変数はコンテキスト行にバインドされます。

例2: 2019年以降に運搬されたすべての乗客手荷物についてフルネームとタグ番号をフェッチします。
SELECT fullName, bag.ticketNo FROM BaggageInfo bag WHERE
exists bag.bagInfo[$element.bagArrivalDate >="2019-01-01T00:00:00"]

説明: 各手荷物の到着日の値は2019年より後である必要があります。ここでは、$elementがコンテキスト行(顧客のそれぞれの手荷物)にバインドされています。EXISTS演算子は、入力式によって返された順序が空かどうかをチェックします。比較演算子>=によって返される順序は、2019年以降に到着したすべての手荷物について空ではありません。

出力:
{"fullName":"Lucinda Beckman","ticketNo":1762320569757}
{"fullName":"Adelaide Willard","ticketNo":1762392135540}
{"fullName":"Raymond Griffin","ticketNo":1762399766476}
{"fullName":"Elane Lemons","ticketNo":1762324912391}
{"fullName":"Zina Christenson","ticketNo":1762390789239}
{"fullName":"Zulema Martindale","ticketNo":1762340579411}
{"fullName":"Dierdre Amador","ticketNo":1762376407826}
{"fullName":"Henry Jenkins","ticketNo":176234463813}
{"fullName":"Rosalia Triplett","ticketNo":1762311547917}
{"fullName":"Lorenzo Phil","ticketNo":1762320369957}
{"fullName":"Gerard Greene","ticketNo":1762341772625}
{"fullName":"Adam Phillips","ticketNo":1762344493810}
{"fullName":"Doris Martin","ticketNo":1762355527825}
{"fullName":"Joanne Diaz","ticketNo":1762383911861}
{"fullName":"Omar Harvey","ticketNo":1762348904343}
{"fullName":"Fallon Clements","ticketNo":1762350390409}
{"fullName":"Lisbeth Wampler","ticketNo":1762355854464}
{"fullName":"Teena Colley","ticketNo":1762357254392}
{"fullName":"Michelle Payne","ticketNo":1762330498104}
{"fullName":"Mary Watson","ticketNo":1762340683564}
{"fullName":"Kendal Biddle","ticketNo":1762377974281}

配列の操作

配列は、ゼロ以上の項目を順序付けしたコレクションです。配列の項目は要素と呼ばれます。配列にNULL値を含めることはできません。

BaggageInfoスキーマには多数の配列があります。スキーマからの単純な配列は、それぞれのflightLegactions配列です。パス式を使用して、単純な配列またはネストされた配列をナビゲートできます。
"actions" : [ {
"actionAt" : "SYD",
"actionCode" : "ONLOAD to SIN",
"actionTime" : "2019.02.28 at 22:09:00 AEDT"
}, {
"actionAt" : "SYD",
"actionCode" : "BagTag Scan at SYD",
"actionTime" : "2019.02.28 at 21:51:00 AEDT"
}, {
"actionAt" : "SYD",
"actionCode" : "Checkin at SYD",
"actionTime" : "2019.02.28 at 20:06:00 AEDT"
} ]
例1: チケット番号が1762357254392の乗客について、それぞれの手荷物の第1区間の詳細(その区間で実行されたすべてのアクションを含む)をフェッチします。
SELECT bagDet.fullName, bagDet.bagInfo[].flightLegs[0]
AS Details FROM BaggageInfo bagDet WHERE ticketNo=1762357254392

前述の問合せで、flightLegsは配列です。スライス・ステップ[0]flightLegs配列に適用されます。配列要素は0で始まるため、これにより、配列内の最初のレコードが取得されます。乗客ごとにそれぞれの手荷物の第1区間情報を取得します。ticketNoを使用して追加フィルタを適用すると、1人の乗客情報のみがフェッチされます。

出力:
{"fullName":"Teena Colley",
"Details":[[
{"actionAt":"MSQ","actionCode":"ONLOAD to FRA","actionTime":"2019-02-13T07:17:00Z"},
{"actionAt":"MSQ","actionCode":"BagTag Scan at MSQ","actionTime":"2019-02-13T06:52:00Z"},
{"actionAt":"MSQ","actionCode":"Checkin at MSQ","actionTime":"2019-02-13T06:11:00Z"}],
"2019-02-13T09:00:00Z","2019-02-13T07:00:00Z","BM365","FRA","MSQ"]}

ノート:

スライス・ステップを使用して、その位置が[low: high]の範囲内にあるすべての配列要素を選択することもできます。ここで、lowとhighは範囲の限度を指定する式です。下限と上限が不要な場合は、lowとhighの式は省略できます。

例: チケット番号が1762357254392の乗客について、すべての区間の詳細(すべての区間で実行されたすべてのアクションを含む)をフェッチします。

スライス・ステップを使用して、flightLegs配列の最初の3つのレコードをフェッチします。
SELECT bagDet.fullName, bagDet.bagInfo[].flightLegs[0:2] AS Details
FROM BaggageInfo bagDet WHERE ticketNo=1762357254392
出力:
{"fullName":"Teena Colley",
"Details":[
 [
   {"actionAt":"MSQ","actionCode":"ONLOAD to FRA","actionTime":"2019-02-13T07:17:00Z"},  
   {"actionAt":"MSQ","actionCode":"BagTag Scan at MSQ","actionTime":"2019-02-13T06:52:00Z"},   
   {"actionAt":"MSQ","actionCode":"Checkin at MSQ","actionTime":"2019-02-13T06:11:00Z"}
 ],
 "2019-02-13T09:00:00Z","2019-02-13T07:00:00Z","BM365","FRA","MSQ", 
 [
   {"actionAt":"HKG","actionCode":"Offload to Carousel at HKG","actionTime":"2019-02-13T11:15:00Z"},
   {"actionAt":"FRA","actionCode":"ONLOAD to HKG","actionTime":"2019-02-13T10:39:00Z"},
   {"actionAt":"FRA","actionCode":"OFFLOAD from FRA","actionTime":"2019-02-13T10:37:00Z"}
 ],
 "2019-02-13T11:18:00Z","2019-02-13T07:17:00Z","BM313","HKG","FRA"
]}

ネストされたデータ型の操作

Oracle NoSQL Databaseは、ネストされたデータ型をサポートしています。つまり、あるデータ型を別のデータ型内に含めることができます。たとえば、配列内のレコード、配列内の配列などです。サンプルのBaggageinfoスキーマでは、配列の配列のネストされたデータ型を使用します。

例1: チケット番号が1762330498104の乗客について、第1区間で実行された様々なアクションをフェッチします。
SELECT bagDet.fullName, bagDet.bagInfo[].flightLegs[0].values().values() AS Action
FROM BaggageInfo bagDet WHERE ticketNo=1762330498104
説明: 前述の問合せでは、flightLegsはネストされたデータ型です。この配列には、レコードの配列であるactions配列があります。前述の問合せは2つのステップで実行されます。
  1. $bag.bagInfo[].flightLegs[0].values()は、flightLegs配列の最初のレコードのすべてのエントリを示します。これには、actions配列が含まれます。これを(values()を使用して)繰り返し、次に示すようにactions配列のすべてのレコードを取得できます。
  2. $bag.bagInfo[].flightLegs[0].values().values()は、actions配列のすべてのレコードを示します。
出力:
{"fullName":"Michelle Payne",
"Action":["SFO","ONLOAD to IST","2019-02-02T12:10:00Z","SFO",
"BagTag Scan at SFO","2019-02-02T11:47:00Z","SFO",
"Checkin at SFO","2019-02-02T10:01:00Z"]}
例2: チケット番号が1762340683564の乗客について、第1区間で実行された最後のトランジット・アクションの更新の詳細を表示します。
SELECT bagDet.fullName, (bagDet.bagInfo[].flightLegs[0].values())[2].actionCode
AS lastTransit_Update FROM BaggageInfo bagDet WHERE ticketNo=1762340683564
説明: 前述の問合せは次のステップを使用して処理されます。
  1. $bagDet.bagInfo[].flightLegs[0].values()は、flightLegs配列の最初のレコードのすべてのエントリを示します。
  2. bagInfo[].flightLegs[0].values())[2]は、flightLegs配列の最初の要素内のactions配列の3番目(最後)のレコードを示します。
  3. actions配列に複数のレコードがあります。bagInfo[].flightLegs[0].values())[2].actionCodeは、actionCode要素に対応する値をフェッチします。
出力:
{"fullName":"Mary Watson","lastTransit_Update":"Checkin at YYZ"}

ノート:

後の項で、size関数を使用して配列索引をハードコードすることなく、一般的な方法で同じ問合せを記述する方法について学習します。「複合データ型のサイズの検索」を参照してください。

複合データ型のサイズの検索

size関数を使用すると、複合データ型のサイズ(フィールドまたはエントリの数)を返すことができます。

例1: チケット番号が1762320569757の乗客の飛行区間/中継点の数を確認します。
SELECT bagDet.fullName, size(bagDet.bagInfo.flightLegs) as Noof_Legs
FROM BaggageInfo bagDet WHERE ticketNo=1762320569757

説明: 前述の問合せで、size関数を使用してflightLegs配列のサイズを取得します。

出力:
{"fullName":"Lucinda Beckman","Noof_Legs":3}
例2: チケット番号が1762357254392の乗客について、第1区間でのアクション・エントリ(手荷物のもの)の数を確認します。
SELECT bagDet.fullName, size(bagDet.bagInfo[].flightLegs[0].actions) AS FirstLeg_NoofActions
FROM BaggageInfo bagDet WHERE ticketNo=1762357254392
出力:
{"fullName":"Teena Colley","FirstLeg_NoofActions":3}
例3: チケット番号が1762340683564の乗客について、第1区間で実行された最後のトランジット・アクションの更新の詳細を表示します。
SELECT bagDet.fullName,
(bagDet.bagInfo[].flightLegs[0].values())[size(bagDet.bagInfo.flightLegs[0].actions)-1].actionCode
AS lastTransit_Update FROM BaggageInfo bagDet WHERE ticketNo=1762340683564
出力:
{"fullName":"Mary Watson","lastTransit_Update":"Checkin at YYZ"}

説明:

前述の問合せは、次のステップを使用して処理されます。
    1. $bagDet.bagInfo[].flightLegs[0].values()は、flightLegs配列の最初のレコードのすべてのエントリを示します。
    2. size(bagDet.bagInfo.flightLegs[0].actions)は、第1区間のactions配列のサイズを示します。
    3. actions配列に複数のレコードがあります。size関数の結果を使用して、アクション配列の最後のレコードを取得し、対応するactionCodeをフェッチできます。配列の索引が0で始まるため、サイズから1を減算します。

ノート:

「ネストされたデータ型の操作」のトピックでは、actions配列の索引をハードコードすることで、同じ問合せが記述されています。size関数を使用して、索引をハードコードすることなく、同じ問合せを一般的な方法でリライトしました。