問題点
ここで新しい頭字語を試してみます - B2G - Business To GIS - つまり外部管理データをArcGISに配信することを意味します。外部(「ビジネス」)システムがJSONのような共通フォーマットデータを取得するために呼び出せるREST APIを提供することは非常に一般的ですが、サーバーが複数のチャンク(つまり「ページ」)でデータセットを配信し、JSONがGeoJSONのような明確に定義された方言ではなく、構造体や配列オブジェクトからカラムにパースする必要があることも非常に一般的です。
この投稿は、ArcGIS Data Interoperabilityを使ってコーディングなしでページネーションとパースという2つの課題を克服する方法についてです。
私の対象データは、2024年にフィルタリングされた連邦通信委員会(FCC)の迷惑電話に関する顧客苦情データです。受信JSONの様子を見たい場合はこちらで1000件のランダムレコードを見ることができますが、こちらがフィーチャサービスとしての最終結果です:
FCC Customer Complaints - unwanted calls
調査すると、いくつかの一般的なページネーション手法があることがわかります:
- 開始行位置と行数を定義するoffsetとlimitパラメータで、順序付けられたデータを読み取る。
- この方法にはソート順序を設定するプロパティのための別のパラメータが含まれる場合があります
- ページ番号と(オプションで)ページサイズのパラメータ。
- 開始行が論理クエリで定義され、それに続くクエリも示唆するクエリベースのページネーション。
- 時間ベースのクエリ、クエリベースページネーションの特別なケース。
- APIが結果内に次ページを含むページ名を提供するカーソルベースのページネーション。
- 上記の組み合わせ。
最初の2つの方法が最も単純(そして私が使った唯一の方法)であり、サーバーがページ作成計算を行い、クライアントは単純なカウンターを追跡しながらデータが尽きるまでリクエストを送信します。
こちらはoffsetとlimitベースのAPIの例で、こちらはページベースAPIの例です。
#6 の例として #3 と #4 の組み合わせについては、ホストされたフィーチャレイヤーへのクエリをご覧ください。ArcGISはレイヤークエリ作成を自動で処理します。
パースも簡単にできるでしょうか?レコードを型付きカラムとジオメトリに変換しなければなりません!
{
"issue_type" : "Phone",
"caller_id_number" : "830-210-2001",
"state" : "IL",
"method" : "Wired",
"advertiser_business_phone_number" : "None",
"issue_time" : "8:41 am",
"issue" : "Unwanted Calls",
"zip" : "60629",
"type_of_call_or_messge" : "Live Voice",
"issue_date" : "2024-01-04T00:00:00.000",
"id" : "3739134",
"location_1" : {
"latitude" : "41.781382",
"human_address" : "{\"address\": \"\", \"city\": \"IL\", \"state\": \"\", \"zip\": \"60629-5219\"}",
"needs_recoding" : false,
"longitude" : "-87.732853"
}
}
問題ありません!始めましょう。
ページネーション
ここではREST APIを呼び出しています。このAPIはページネーションされたレスポンスを提供します。ArcGIS Data InteroperabilityではこれはHTTPCallerトランスフォーマーをループ内で呼び出すことを意味し、この場合はoffset, limit, orderパラメータでオフセット値を各呼び出しごとにインクリメントし、すべてのデータが受信されレスポンスが空配列になるまで繰り返します。ビジュアルプログラミング環境でループできることをご存じなかったかもしれませんが、できますし簡単です。私のワークスペース左上近くにあるミントグリーン色のカスタムトランスフォーマー「UnwantedCallsLooper」がその役割を果たしています。これはループカスタムトランスフォーマーです。
親ETLワークスペース
カスタムトランスフォーマーはメインキャンバスに埋め込まれており(含まれており)、独自の同名タブに存在します。カスタムトランスフォーマーはメインキャンバス内で一つ以上の通常トランスフォーマーを選択し、右クリックによるコンテキストメニューからカスタムトランスフォーマー作成オプションを選ぶことで作成します。私の場合はHTTPCallerトランスフォーマー単体を選択しました。
カスタムトランスフォーマー作成後、更なる編集ステップとしてループ設定があります:
- キャンバス内コンテキストメニューからループ戻り接続追加
- ループ戻り前に完了判定テスト追加
- offsetパラメータ増分設定
以下は私のカスタムトランスフォーマーの様子です。実行時にはメインキャンバスから到着した各フィーチャーにoffset属性があり、それがHTTPCallerトランスフォーマーで使用されます。limitとorderパラメータは変わらずHTTPCaller内で「ハードコード」されています。下側ストリームはループ継続条件で、レスポンスが空配列ではない場合データはまだ尽きていないのでoffsetを増やしてループします!
ループカスタムトランスフォーマー
パース
各APIレスポンスはJSON構造体配列で、「_response_body」という属性に格納されています。この配列はJSONFragmenterによって個別フィーチャーへ展開されます。JSON Queryパラメータはトップレベル配列断片化を意味し、他の設定は上記コードブロックに似た断片提供を保証します。
JSONFragmenter
次に各断片フィーチャーをJSONExtractorでパースします。
JSONExtractor
Extract Queriesグリッドでは出力属性名と断片内データ取得元を定義しています。JSONクエリはシンプルな構文に従いますが、入力できるだけでなく、JSON構造をナビゲートしクエリ生成を自動化するための便利なピッカーを使う簡単なコツがあります。JSONExtractorの前に、一時的にSamplerで単一のフィーチャをサンプリングし、ファイルに書き出し、その後JSONExtractorの入力ソースをこのファイルに一時的に設定すると、クエリ用の便利なピッカーが得られます!抽出クエリを入力したらSamplerを削除し、JSONFragmenterの入力ソースを_response_body内のドキュメントにリセットしてください。<\/P>
これでページネーションとパースが解明されました!ブログダウンロードには2つのワークスペースソースfmwファイルがあります。CreateFCはファイルジオデータベース出力を作成し、datetimeフィールドの作成を妨げていたデータエラー修正などのデータ処理を理解した場所です。初期フィーチャクラスが欲しかったので、それをターゲットホストされたフィーチャサービスとしてシンボル化・共有しました。UpdateFSはCreateFCのデータ処理ステップを借用していますが、ループするカスタムトランスフォーマーとETLツール実行時にデータ変更を検出・適用するロジックが含まれており、本番環境で必要になるでしょう。<\/P>
質問やご意見があればこの投稿にコメントしてください。ページングを楽しんでください!<\/P>
<\/P>