この章では、ビッグ・データ環境での空間データのロード、格納、アクセス、および使用に関する概念と使用状況の情報について説明します。
Oracle Big Data Spatial and Graphの機能では、位置情報に基づく意思決定のために、空間データを迅速かつ効率的に格納、アクセス、および分析できます。
空間データは、実際の空間または地理情報システム(GIS)やその他の位置情報アプリケーション上の概念的な空間に関連する実際、または概念的なオブジェクトの位置特性を表します。
空間機能を使用して、特定の位置の2次元および3次元の地理イメージに対して位置情報を付加、補完、視覚化、変換、ロード、処理を行い、GIS機能におけるジオメトリ形状を操作します。
Oracle Big Data Spatial and Graph on Apache Hadoopとは、MapReduceプログラムとHadoopクラスタの分析機能を使用して空間データを格納し、データにアクセスし、分析するフレームワークです。空間機能によってスキーマが提供され、空間データ・コレクションの格納、取得、更新、および問合せが容易になります。Big Data Spatial and Graph on Hadoopでは、ジオメトリ形状、ラスターまたはベクトル・イメージのいずれかの空間イメージの格納と処理をサポートしており、サポート対象の数百種類の形式のいずれかで保存されます。
注意:
空間のコンセプト、データ、および操作の概要は、『Oracle Spatial and Graph開発者ガイド』を参照してください
Oracle Big Data Spatial and Graphの使用には、次の利点があります。
一部のGISを中心とした空間処理システムやエンジンとは異なり、Oracle Big Data Spatial and Graphでは、空間情報が構造化されていても、構造化されていなくても処理が可能です。
顧客の環境で保存するデータ形式が1つに限定されることはありません。空間データと空間以外のビジネスデータの両方が保存されていても、Oracle Big Dataで空間処理を実行できます。
これはフレームワークであるため、顧客は提供されているAPIを使用して、アプリケーションや操作をカスタムで作成できます。
Oracle Big Data Spatialでは、ベクトル・タイプとラスター・タイプの両方の情報やイメージを処理できます。
空間データはSpatialサーバーによって問合せと分析のためにロードされ、イメージはイメージ処理フレームワークによって保存され、処理されます。Oracle Big Data Spatial and Graphサーバーは、Hadoop上で次のために使用できます。
地勢図上の足跡、ジオメトリのリソースの可用性などの地理空間情報のカタロギング。
地図上の位置で最も近い距離などを計算する距離演算の位相処理。
地図要素内で人口統計の相関を作成することによって、階層型の地勢図を構築し、地図を補完するためのカテゴリ化。
Oracle Big Data Spatial and Graphには、次の機能が組み込まれています。
空間データをすばやく取得するための索引付け機能。
地図上に足跡を表示するマップ機能。
特定の地勢地域をズームインおよびズームアウトするズーム機能。
モザイク操作またはサブセット操作の作成を処理するために一連のイメージ・ファイルをグループ化するモザイクおよびグループ機能。
デカルトおよび測地座標系で、空間データを表すデカルトおよび測地座標の機能。
国、州、都市、郵便番号などのジオメトリック階層を構築し、関連付ける階層機能。この機能では、ドキュメントまたは緯度/経度座標の形式で入力データを処理できます。
Oracle Big Data Spatial and Graphでは、ベクトルおよびラスター空間データの両方の保管と処理をサポートしています。
ラスター・データの処理では、GDALローダーがラスター空間データまたはイメージをHDFS環境にロードします。ラスター空間データでは、次の基本操作を実行できます。
モザイク: 複数のラスター・イメージを組み合せて単一のモザイク・イメージを作成します。
サブセット: 個々のイメージに対してサブセット操作を実行します。
ラスター代数演算: ラスター内のすべてのピクセルに対して代数演算を実行します(add、divide、multiply、log、pow、sine、sinhおよびacosなど)。
ユーザー定義の処理: ラスター処理は、マッピング・フェーズおよびリデュース・フェーズで実行されるようユーザーが設定するクラスに基づいています。
この機能は、ラスター分析操作のためのMapReduceフレームワークをサポートしています。ユーザーは、ラスター・データの代数関数などの独自のラスター操作をカスタムで構築できます。たとえば、地形など、数値標高モデルや空間的表面の3次元の表現の各基盤の傾斜を計算します。詳細は、「ラスター・データ処理のためのOracle Big Data Spatial Hadoop Image Processing Framework」を参照してください。
この機能は、空間ベクトル・データの処理をサポートしています。
Hadoop HDFS環境へのロードおよび格納
デカルトまたは測地データとして格納
格納された空間ベクトル・データは次の問合せ操作などの実行に使用されます。
ポイントインポリゴン
距離計算
Anyinteract
バッファ作成
空間ベクトル・データでは、複数のデータ・サービス操作がサポートされています。
データ・エンリッチメント
データ・カテゴリ化
空間の結合
また、HTML5形式にのみ限定されますが、Map Visualization APIもサポートされています。このようなAPIにアクセスして、カスタム操作を作成できます。詳細は、「Oracle Big Data Spatial Vector Analysis」を参照してください。
Oracle Spatial Hadoop Image Processing Frameworkを使用すると、一連の並列処理フェーズの結果として生成される新しい結合イメージの作成が可能になります。
次の機能が含まれます。
HDFSイメージ・ストレージでは、各ブロック・サイズ分割が個別の四角形として格納され、その後のそれぞれの処理に使用されます
MapReduceフレームワークを使用した、サブセット操作、ユーザー定義操作、および地図代数演算の並列処理
マッピング・フェーズまたはリデュース・フェーズで透過的に並列して実行されるカスタム処理クラスの追加機能
ジオリファレンスされるイメージの高速処理
GDAL形式、複数帯域イメージ、DEM (数値標高モデル)、複数ピクセル深度、およびSRIDのサポート
Java APIでは、WebサービスまたはスタンドアロンJavaアプリケーションに使用できるフレームワーク操作にアクセスできます
ローカル環境でユーザー処理クラスをテストおよびデバッグするためのフレームワーク
Oracle Spatial Hadoop Image Processing Frameworkは、LoaderとProcessorと呼ばれる2つのモジュールで構成されており、次の図に示すように、それぞれがHadoopクラスタ内の別のステージで実行されるHadoopジョブで表されます。また、Image Server Webアプリケーションを使用してイメージをロードおよび処理し、Java APIを使用してフレームワークの機能を公開できます。
インストールと構成について詳しくは、次を参照してください。
Image Loaderは、特定のイメージまたはイメージ・グループをHDFSにロードするHadoopジョブの1つです。
イメージはインポート中、HDFSブロックとして四角形処理され、格納されます。
GDALはイメージの四角形処理に使用されます。
それぞれの四角形は個々のマッパーによってロードされるため、並列で読み取られ、高速になります。
それぞれの四角形は一定のバイト数(ユーザー入力)が重なっているため、隣接する四角形の領域にかかっています。
MapReduceジョブでは、それぞれの四角形の情報をロードするマッパーを使用します。マッパーの数は、四角形の数、イメージ解像度、およびブロック・サイズに応じて'n'個になります。
イメージごとのリデュース・フェーズでは、マッパーによってロードされた情報をすべてまとめ、そのイメージを解像度、帯域、オフセット、イメージ・データを含む特別な.ohif形式で格納します。これにより、それぞれの四角形を含むファイル・オフセットとノード場所が明らかになります。
それぞれの四角形には、各帯域の情報が含まれます。これは、一部の四角形のみを処理し、それに対応するブロックのみをロードする場合に役立ちます。
次の図はImage Loaderの処理を示しています。
Image Processorは、ユーザー入力に基づいて処理対象の四角形をフィルタ処理し、並列処理によって新しい1つのイメージを作成するためのHadoopジョブです。
ユーザーが識別した特定のイメージの四角形を処理します。識別できる処理クラスは1つ、ゼロ、または複数です。これらのクラスは、構成に応じてマッピング・フェーズまたはリデュース・フェーズで実行されます。マッピング・フェーズの場合、処理クラスの実行後、モザイク操作を実行し、ピクセルを調整してユーザーが要求した最終的な出力形式にします。モザイク操作が要求されなかった場合、入力ラスターがそのままリデュース・フェーズに送信されます。リデュース・フェーズの場合、ユーザー・リデュース処理クラス用として入力されるGDALデータ・セットにすべての四角形がまとめられます。これにより、ユーザーのニーズに応じて最終出力を変更または分析できるようになります。
マッパーは、データのローカル性を保ちながら、1つの四角形に対応するデータをロードします。
データがロードされると、マッパーはユーザーが要求した帯域をフィルタ処理します。
フィルタされた情報は、リデュース・フェーズで各マッパーに送信され、そこでバイト数がまとめられ、ユーザーの要求に応じて最終的な処理イメージがHDFSまたは通常のファイル・システムに格納されます。
次の図はImage Processorジョブを示しています。
Oracle Spatial and Graph Hadoop Image Processing Frameworkを使用してイメージを処理するには、最初にイメージを実際にHDFSに保存し、次に各イメージをそれぞれ別のスマート・タイルに保存します。
ここでは、四角形をそれぞれ使用してジョブを処理できます。Image Loaderでは、単一イメージ、またはイメージのコレクションを並列でHDFSにインポートできるため、ロード時間を短縮できます。
Image Loaderはファイル・システムのイメージをHDFSにインポートし、そこでブロックにイメージのすべての帯域のデータを含められるため、特定の位置でその後処理が必要になった場合、その情報を単一ノードで処理できます。
イメージ・ロード・ジョブには、イメージを関連イメージに分割するカスタム入力形式があります。分割は、次の方法で特定される、定義済の領域をカバーするイメージの四角形のブロックを読み取るアルゴリズムに基づいて計算されます
領域 = ((ブロックサイズ - メタデータ・バイト数) / 帯域数) / 1ピクセル当たりのバイト数。
ブロック・サイズ全体を使用しない部分については、残りのバイト数がゼロで埋められます。
分割は複数のマッパーに割り当てられ、そこでImageSplit情報に基づき、割当て済の四角形がすべてGDALによって読み取られます。その結果、ImageDataWritableインスタンスが作成され、コンテキストに保存されます。
ImageDataWritableインスタンスのメタデータ・セットは、四角形処理したイメージを操作および処理できるように、処理クラスでの設定に使用されます。ソース・イメージは複数のマッパーから読み取られるため、並列ロードが高速で実行されます。
マッパーが読取りを完了すると、 リデューサがコンテキストから四角形を選択してまとめ、ファイルをHDFSに保存します。イメージを再度読み取るには、特殊な読取り処理が必要です。
次の入力パラメータをHadoopコマンドに指定します。
hadoop jar /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageloader.jar -files <SOURCE_IMGS_PATH> -out <HDFS_OUTPUT_FOLDER> -gdal <GDAL_LIB_PATH> -gdalData <GDAL_DATA_PATH> [-overlap <OVERLAPPING_PIXELS>] [-thumbnail <THUMBNAIL_PATH>] [-expand <false|true>] [-extractLogs <false|true>] [-logFilter <LINES_TO_INCLUDE_IN_LOG>]
説明:
SOURCE_IMGS_PATHはソース・イメージまたはフォルダのパスです。入力が複数の場合はカンマで区切ります。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。HDFS_OUTPUT_FOLDERはロードしたイメージを格納するHDFS出力フォルダです。OVERLAPPING_PIXELSはそれぞれの四角形の境界線上で重なるピクセルの任意の数であり、このパラメータが指定されていない場合、重なっている2つのピクセルのデフォルトが使用されます。GDAL_LIB_PATHはGDALライブラリの場所を示すパスです。GDAL_DATA_PATHはGDALデータ・フォルダの場所を示すパスです。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。THUMBNAIL_PATHはロードしたイメージのサムネイルを格納する任意のパスです。NFSを介してクラスタ内のすべてにアクセスでき、Yarnユーザーの書込みアクセス権のあるパスを指定する必要があります。-expandは、ロードされたラスターのHDFSパスによってソース・パス(すべてのディレクトリを含む)が拡張されるかどうかを制御します。これをfalseに設定すると、.ohifファイルは、(-oオプションを使用して指定された)出力ディレクトリに直接格納され、この場合、このラスター内のこのディレクトリのパスは含まれません。-extractLogsは、実行したアプリケーションのログをシステムの一時ディレクトリに抽出するかどうかを制御します。デフォルトでは有効ではありません。抽出には、Oracle Frameworkクラスの一部ではないログは含まれません。-logFilter <LINES_TO_INCLUDE_IN_LOG>は、たとえば、カスタム処理クラス・パッケージを含めるために、抽出したログに含めるすべてのパターンがリストされたカンマ区切りの文字列です。たとえば、次のコマンドでは、imagesフォルダ内のジオリファレンスされたイメージすべてをロードし、該当するすべての境界線に重なる10ピクセルを追加します。HDFS出力フォルダはohiftestであり、ロードしたイメージのサムネイルがprocesstestフォルダに格納されます。
hadoop jar /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageloader.jar -files /opt/shareddir/spatial/demo/imageserver/images/hawaii.tif -out ohiftest -overlap 10 -thumbnail /opt/shareddir/spatial/processtest –gdal /opt/oracle/oracle-spatial-graph/spatial/raster/gdal/lib –gdalData /opt/shareddir/data
デフォルトでは、マッパーとリデューサは2GBのJVMを取得できるよう構成されていますが、この設定、またはその他のジョブ構成プロパティは、コマンドを実行する同じフォルダの場所で、ユーザーがimagejob.propプロパティ・ファイルを追加することによってオーバーライドできます。このプロパティ・ファイルは、オーバーライドする構成プロパティをすべてリストできます。次に例を示します。
mapreduce.map.memory.mb=2560 mapreduce.reduce.memory.mb=2560 mapreduce.reduce.java.opts=-Xmx2684354560 mapreduce.map.java.opts=-Xmx2684354560
Javaヒープ・メモリー(java.optsプロパティ)は、マッパーとリデューサ(mapreduce.map.memoryとmapreduce.reduce.memory)に割り当てられたメモリーの合計以下である必要があります。したがって、Javaヒープ・メモリーを増やす場合、マッパーとリデューサのメモリーも増やすことが必要である場合があります。
リデューサは、入力イメージごとに2つの出力ファイルを生成します。1つ目は、ソース・イメージのすべての四角形を集める.ohifファイルであり、それぞれの四角形は処理マッパーによって別のインスタンスとして処理されます。四角形は内部でHDFSブロックとして格納されます。ブロックは複数のノードに配置され、1つのノードには特定の.ohifファイルのブロックが1つ以上含まれます。.ohifファイルは、–expandが使用されなかった場合、/user/<USER_EXECUTING_JOB>/OUT_FOLDER/<PARENT_DIRECTORIES_OF_SOURCE_RASTER>フォルダの下にあるユーザー指定フォルダに、-outフラグを付けて格納されます。それ以外の場合、.ohifは/user/<USER_EXECUTING_JOB>/OUT_FOLDER/に配置され、このファイルはoriginal_filename.ohifとして識別できます。
2つ目の出力は、メタデータ・ファイルに関連しており、イメージのすべてのピースをリストし、それぞれがカバーする座標を示します。ファイルはメタデータの場所にあるHDFSに置かれており、その名前はohifファイルの名前を使用してハッシュ生成されます。このファイルはOracle内部専用であり、ソース・ラスターの重要なメタデータをリストします。メタデータ・ファイルのサンプル行の一部は次のとおりです。
srid:26904 datatype:1 resolution:27.90809458890406,-27.90809458890406 file:/user/hdfs/ohiftest/opt/shareddir/spatial/data/rasters/hawaii.tif.ohif bands:3 mbr:532488.7648166901,4303164.583549625,582723.3350767174,4269619.053853762 0,532488.7648166901,4303164.583549625,582723.3350767174,4269619.053853762 thumbnailpath:/opt/shareddir/spatial/thumb/
-thumbnailフラグが指定されている場合、ソース・イメージのサムネイルが関連フォルダに格納されます。これは.ohifファイルの変換を視覚化する方法の1つです。ジョブ実行ログには、コマンドyarn logs -applicationId <applicationId>を使用してアクセスできます。
イメージはHDFSにロードされると、Oracle Spatial Hadoop Image Processing Frameworkによって並列で処理されます。
出力を指定すると、フレームワークによって出力に適合するようフィルタおよび処理され、まとめて1つのファイルに格納されます。地図代数演算も可能であり、設定されていれば、処理フェーズの最初の部分になります。最終的な出力がフレームワークによって作成される前であれば、実行する処理クラスを追加で指定できます。
Image Processorは、入力(モザイク記述または単一のラスター)に基づいて特定のデータ・ブロックをロードし、最終的な出力に適合する帯域およびピクセルのみを選択します。指定した処理クラスはすべて実行され、最終的な出力は、ユーザーの要求に応じてHDFSまたはファイル・システムに格納されます。
イメージ処理ジョブには、ユーザーによって要求された処理のタイプに応じて異なるフローがあります。
デフォルトのイメージ処理ジョブ・フロー: モザイク操作、単一のラスター操作、または基本的な複数のラスター操作が含まれる処理に対して実行されます。
複数のラスター・イメージ処理ジョブ・フロー: 複雑な複数のラスター代数演算が含まれる処理に対して実行されます。
デフォルトのイメージ処理ジョブ・フローは、次の処理のいずれかが要求されたときに実行されます。
モザイク操作
単一のラスター操作
基本的な複数のラスター代数演算
このフローには、独自のカスタムFilterInputFormatがあり、SRIDおよび座標に基づいて処理対象の四角形を決定します。モザイク入力のデータ型(ピクセル深度)と同じデータ型(モザイク深度)のイメージのみが該当します。ユーザーがモザイク出力に指定した座標と交差する四角形のみが含まれます。単一のラスター操作または基本的な複数のラスター代数演算(モザイクを除く)の場合、処理は完全なイメージに対して実行されるため、フィルタには、入力ラスターのすべての四角形が含まれます。四角形が選択されると、イメージごとにカスタムImageProcessSplitが作成されます。
マッパーがImageProcessSplitを受け取ると、ImageSplitの指定に基づいて情報が読み取られ、ユーザーが指定した帯域のみを選択するようフィルタ処理され、地図操作、および(要求に定義されていれば)処理クラスのリストが実行されます。
それぞれのマッパー処理は、データがあるノードで実行されます。地図代数演算および処理クラスが実行された後、検証により、ユーザーがモザイク操作を要求しているかどうか、または分析に完全なイメージが含まれるかどうかが検証されます。モザイク操作が要求されている場合、最終処理によってこの操作が実行されます。モザイク操作では、すべての四角形から出力に適合するピクセルのみを選択し、必要に応じて解像度を変更してモザイク出力に追加します。単一の処理操作では、前のラスターの四角形のバイトがそのままコピーされます。結果として得られたバイトは、リデューサによってリカバリされる対象としてNFSに格納されます。
1つのリデューサで複数の四角形を選択し、それをまとめます。基本的な複数のラスター代数演算を指定した場合、これは、四角形が最終出力にマージされるときに同時に実行されます。この操作は、モザイク出力内の交差ピクセルのみに影響するか、モザイク操作が要求されなかった場合はすべてのピクセルに影響します。リデューサ処理クラスを指定した場合、出力ラスターとともにGDALデータ・セットが分析および処理のためにこのクラスに送信されます。HDFS出力を選択した場合、ImageLoaderが呼び出され、結果がHDFSに格納されます。それ以外の場合、イメージはデフォルトでGDALによって用意され、ファイル・システム(NFS)に格納されます。
複数のラスター・イメージ処理ジョブ・フローは、複雑な複数のラスター代数演算が要求されるときに実行されます。これは、同じMBR、ピクセル・タイプ、ピクセル・サイズおよびSRIDを持つラスターに適用されます。なぜなら、これらの操作は対応するセルにピクセル単位で適用され、この場合、すべてのピクセルが同じ座標を表します。
このフローには、独自のカスタムMultipleRasterInputFormatがあり、SRIDおよび座標に基づいて処理対象の四角形を決定します。同じMBR、ピクセル・タイプ、ピクセル・サイズおよびSRIDを持つイメージのみが考慮されます。カタログ内の最初のラスターによって指定された座標と一致するラスターのみが含まれます。入力ラスターのすべての四角形が考慮されますが、これは、処理が完全なイメージに対して実行されるからです。
四角形が選択されると、カスタムMultipleRasterSplitが作成されます。この分割には、ブロック・サイズに応じてすべての元の四角形の小さい領域が含まれますが、これは、小さい領域であってもすべてのラスターを分割に含める必要があるからです。これらはそれぞれIndividualRasterSplitと呼ばれ、これらは親MultipleRasterSplitに含まれます。
マッパーがMultipleRasterSplitを受け取ると、親分割に含まれるすべてのラスターの四角形の情報が読み取られ、ユーザーが指定した帯域のみ、およびこの特定のマッパーで処理する対応する小さい領域のみを選択するようフィルタ処理され、複雑な複数のラスター代数演算が実行されます。
同じノード内にない可能性がある単一のマッパーに複数のラスターが含まれるため、処理のこの部分ではデータのローカル性が失われる可能性があります。すべてのピクセルに関して結果として得られたバイトは、リデューサによってリカバリされる対象としてコンテキストに取り込まれます。
1つのリデューサでピクセル値を選択し、それをまとめます。リデューサ処理クラスを指定した場合、出力ラスターとともにGDALデータ・セットが分析および処理のためにこのクラスに送信されます。このシナリオではこのクラスの四角形のリストはnullを受け取り、このクラスは出力データ・セットのみを操作できます。HDFS出力を選択した場合、ImageLoaderが呼び出され、結果がHDFSに格納されます。それ以外の場合、イメージはデフォルトでGDALによって用意され、ファイル・システム(NFS)に格納されます。
次の入力パラメータをHadoopコマンドに指定できます。
hadoop jar /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageprocessor.jar -config <MOSAIC_CONFIG_PATH> -gdal <GDAL_LIBRARIES_PATH> -gdalData <GDAL_DATA_PATH> [-catalog <IMAGE_CATALOG_PATH>] [-usrlib <USER_PROCESS_JAR_PATH>] [-thumbnail <THUMBNAIL_PATH>] [-nativepath <USER_NATIVE_LIBRARIES_PATH>] [-params <USER_PARAMETERS>] [-file <SINGLE_RASTER_PATH>]
説明:
MOSAIC_CONFIG_PATHは、出力の機能を定義するモザイク構成xmlへのパスです。GDAL_LIBRARIES_PATHはGDALライブラリの場所を示すパスです。GDAL_DATA_PATHはGDALデータ・フォルダの場所を示すパスです。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。IMAGE_CATALOG_PATHは、処理対象のHDFSイメージをリストするカタログxmlへのパスです。–fileフラグを使用して処理する単一のラスターも指定できるため、これはオプションです。USER_PROCESS_JAR_PATHは任意のユーザー定義jarファイルまたはjarファイルのカンマ区切りのリストであり、これらにはそれぞれ、ソース・イメージに適用される追加の処理クラスが含まれています。THUMBNAIL_PATHはロードしたイメージのサムネイル作成を有効化するための任意のフラグです。このパスは、クラスタ内のすべてのノードへのNFSを介してアクセスし、HDFS出力の場合のみ有効です。USER_NATIVE_LIBRARIES_PATHは、分析で使用する追加のネイティブ・ライブラリの任意のカンマ区切りのリストです。これはまた、アプリケーションにロードするすべてのネイティブ・ライブラリが含まれるディレクトリである場合もあります。USER_PARAMETERSは、ユーザー処理クラスの入力データを定義するために使用する任意のキー/値のリストです。セミコロンを使用して、パラメータを区切ります。たとえば、azimuth=315;altitude=45などですSINGLE_RASTER_PATHは、ジョブによって処理される.ohifファイルへの任意のパスです。これが設定されている場合、カタログを設定する必要はありません。たとえば、次のコマンドは、testFS.xmlファイルに設定されているモザイク出力定義を使用して、カタログ・ファイルinput.xmlファイルにリストされるすべてのファイルを処理します。
hadoop jar /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageprocessor.jar -catalog /opt/shareddir/spatial/demo/imageserver/images/input.xml -config /opt/shareddir/spatial/demo/imageserver/images/testFS.xml -thumbnail /opt/shareddir/spatial/processtest –gdal /opt/oracle/oracle-spatial-graph/spatial/raster/gdal/lib –gdalData /opt/shareddir/data
デフォルトでは、マッパーとリデューサは2GBのJVMを取得できるよう構成されていますが、この設定、またはその他のジョブ構成プロパティは、コマンドを実行する同じフォルダの場所で、ユーザーがimagejob.propプロパティ・ファイルを追加することによってオーバーライドできます。
次の例は、イメージ処理ジョブによって生成されるモザイク操作に必要なすべてのソース・イメージをリストする入力カタログXMLを示します。
-<catalog> -<image> <raster>/user/hdfs/ohiftest/opt/shareddir/spatial/data/rasters/maui.tif.ohif</raster> <bands datatype='1' config='1,2,3'>3</bands> </image> </catalog>
<catalog>要素には処理対象の<image>要素のリストが含まれています。
それぞれの<image>要素は、<raster>要素内にソース・イメージまたはソース・フォルダを定義します。フォルダ内のすべてのイメージが処理されます。
<bands>要素はイメージの帯域数を指定し、datatype属性には、ラスター・データ型があり、config属性はモザイク出力帯域の順序にどの帯域が表示されるかを指定します。たとえば、3,1,2はモザイク出力帯域番号1にはこのラスターの帯域番号3、モザイク帯域番号2にはソース帯域1、およびモザイク帯域番号3にはソース帯域2があることを示します。この順序はラスターからベクトルへ変更されることがあります。
次の例は、イメージ処理ジョブで生成される出力の機能を定義する場合に必要なモザイク構成XMLを示します。
-<mosaic exec="false">
-<output>
<SRID>26904</SRID>
<directory type="FS">/opt/shareddir/spatial/processOutput</directory>
<!--directory type="HDFS">newData</directory-->
<tempFSFolder>/opt/shareddir/spatial/tempOutput</tempFSFolder>
<filename>littlemap</filename>
<format>GTIFF</format>
<width>1600</width>
<height>986</height>
<algorithm order="0">2</algorithm>
<bands layers="3" config="3,1,2"/>
<nodata>#000000</nodata>
<pixelType>1</pixelType>
</output>
-<crop>
-<transform>
356958.985610072,280.38843650364862,0,2458324.0825054757,0,-280.38843650364862 </transform>
</crop>
<process><classMapper params="threshold=454,2954">oracle.spatial.hadoop.twc.FarmTransformer</classMapper><classReducer params="plot_size=100400">oracle.spatial.hadoop.twc.FarmAlignment</classReducer></process>
<operations>
<localif operator="<" operand="3" newvalue="6"/>
<localadd arg="5"/>
<localsqrt/>
<localround/>
</operations>
</mosaic>
<mosaic>要素は処理出力の仕様を定義します。exec属性は、処理にモザイク操作が含まれるかどうかを指定します。“false”に設定されている場合、モザイク操作は実行されず、単一のラスターが処理されます。“true”に設定されているか一切設定されていない場合、モザイク操作は実行されます。次の要素の一部はモザイク操作に対してのみ必要であり、単一のラスター処理の場合は無視されます。
<output>要素は出力に使用される<SRID>などの機能を定義します。異なるSRIDのすべてのイメージは、モザイクSRIDに変換され、その四角形がモザイクに適合するかどうかが判断されます。出力ラスターが入力と同じSRIDを持つため、この要素は単一のラスター処理には必要ありません。
<directory>要素は出力の場所を定義します。これは、タグの型で指定される、通常のファイルシステム(FS)またはHDFSのいずれかです。
<tempFsFolder>要素はモザイク出力を一時的に格納するパスを設定します。属性delete=”false”を指定することにより、出力の出力をHDFSに格納するためにローダーが実行されていた場合でも、この出力を保持できます。
<filename>および<format>要素は、出力ファイル名を指定します。<filename>は、単一のラスター処理には必要ありません。これが指定されていない場合、(ジョブの呼出し時に-file属性によって決定される)入力ファイルの名前が出力ファイルに使用されます。出力ラスターが入力と同じ形式であるため、<format>は単一のラスター処理には必要ありません。
<width>および<height>要素はモザイク出力の解像度を設定します。出力ラスターが入力と同じ解像度を持つため、これらは単一のラスター処理には必要ありません。
<algorithm>要素はイメージの順序アルゴリズムを設定します。1はソースの最終変更日付順、2はイメージ・サイズ順を示します。順序タグは昇順モードまたは降順モードを表します。(これらのプロパティは、複数のラスターが重複する可能性があるモザイク操作用です。)
<bands>要素は出力モザイクの帯域数を指定します。この数より帯域の少ないイメージは破棄されます。config属性を単一のラスター処理に使用することにより、カタログがない場合に出力の帯域構成を設定できます。
<nodata>要素は、値のないモザイク出力のすべてのピクセルのうち、最初の3帯域の色を指定します。
<pixelType>要素はモザイク出力のピクセル・タイプを設定します。同じピクセル・サイズのないソース・イメージは処理段階で破棄されます。この要素は、単一のラスター処理には必要ありません。これが指定されていない場合、ピクセル・タイプは入力と同じものになります。
<crop>要素は、モザイク出力に含まれる座標を、startcoordinateX、pixelXWidth、RotationX、startcoordinateY、RotationY、pixelheightYの順に定義します。この要素は、単一のラスター処理には必要ありません。これが指定されていない場合、完全なイメージが分析用として考慮されます。
<process>要素はモザイク操作の前に実行するクラスをすべてリストします。
<classMapper>要素は、マッピング・フェーズ中に実行されるクラスに使用され、<classReducer>要素は、リデュース・フェーズ中に実行されるクラスに使用されます。両方の要素がparams属性を持ち、この場合、ニーズに応じて処理クラスに入力パラメータを送信できます。
<operations>要素は、この要求で処理される地図代数演算をすべてリストします。
ジョブの最初のステップは、出力に適合する四角形をフィルタ処理することです。最初に、四角形のメタデータを保持している位置ファイルがInputFormatに送信されます。
pixelTypeを抽出すると、フィルタにより、関連するソース・イメージが処理に有効かどうかが判別されます。カタログxmlで作成したユーザー定義に基づき、次のいずれかが実行されます。
イメージが処理に有効な場合、次にSRIDが評価されます
ユーザー定義と異なる場合、すべての四角形のMBR座標がユーザーSRIDに変換され、評価されます。
この方法では、すべての四角形が出力定義と交差するかどうかが評価されます。
モザイク処理要求の場合、交差する四角形のみが選択され、これらの1つずつに分割が作成されます。
単一のラスター処理要求の場合、すべての四角形が選択され、これらの1つずつに分割が作成されます。
複雑な複数のラスター代数演算要求の場合、MBRおよびピクセル・サイズが同じであれば、すべての四角形が選択されます。選択したラスターの数およびブロックサイズに応じて、(完全な元のラスターの四角形が必ずしも含まれるわけではない)すべての四角形のラスターの特定の領域が単一の親分割に含まれます。
マッパーでは、格納先のノードでそれぞれの分割が処理されます。(複雑な複数のラスター代数演算の場合、分割に複数のラスターからのデータが含まれるため、データのローカル性が失われる可能性があります。)マッパーでは、ユーザーが定義した地図代数演算および処理クラスが順に実行され、次に、要求された場合、モザイク処理が実行されます。単一のリデューサにより、マッパーの結果がまとめられ、ユーザー指定のリデュース処理クラスの場合、これらのクラスに出力データ・セットが分析または処理のために設定されます。最後に、ユーザーの要求に応じてイメージがFSまたはHDFSに格納されます。ユーザーがHDFSへの出力の格納を要求した場合、ImageLoaderジョブが起動され、イメージが.ohifファイルとして格納されます。
デフォルトでは、マッパーとリデューサは1GBのJVMを取得できるよう構成されていますが、この設定、またはその他の構成プロパティは、コマンドを実行する同じフォルダの場所で、imagejob.propプロパティ・ファイルを追加することによってオーバーライドできます。
カタログXMLで指定した処理クラスは、ジョブで正しく処理できるように、次の一連のルールを遵守している必要があります。マッピング・フェーズのすべての処理クラスにImageProcessorInterfaceインタフェースが実装されている必要があります。リデューサ・フェーズの場合、ImageProcessorReduceInterfaceインタフェースが実装されている必要があります。
処理クラスを実装するには、そのオブジェクト表現ImageBandWritableを使用してラスターを操作する必要があります。処理クラスの例はフレームワークで提供され、DEMの傾斜を計算できます。関数によってピクセル値を別の値に変換する場合などは、マッピング操作を作成できます。ImageBandWritableインスタンスは、解像度、サイズ、ピクセルなど、四角形のコンテンツを定義します。これらの値は、四角形の定義を作成するプロパティに反映する必要があります。モザイク出力の整合性は、これらのプロパティの操作が正しいかどうかによって決まります。
ImageBandWritableインスタンスは、解像度、サイズ、ピクセルなど、四角形のコンテンツを定義します。これらの値は、四角形の定義を作成するプロパティに反映する必要があります。出力の整合性は、これらのプロパティの操作が正しいかどうかによって決まります。
表2-1 ImageBandWritableプロパティ
| タイプ - プロパティ | 説明 |
|---|---|
IntWritable dstWidthSize |
四角形の幅のサイズ |
IntWritable dstHeightSize |
四角形の高さのサイズ |
IntWritable bands |
四角形の帯域数 |
IntWritable dType |
四角形のデータ型 |
IntWritable offX |
ソース・イメージに関連し、Xピクセルから開始 |
IntWritable offY |
ソース・イメージに関連し、Yピクセルから開始 |
IntWritable totalWidth |
ソース・イメージの幅のサイズ |
IntWritable totalHeight |
ソース・イメージの高さのサイズ |
IntWritable bytesNumber |
四角形のピクセルを含み、baseArrayに格納されるバイト数 |
BytesWritable[] baseArray |
四角形のピクセルを表すバイト数を含む配列であり、それぞれのセルが1つの帯域を表します |
IntWritable[][] basePaletteArray |
四角形のパレットを表す整数値を含む配列であり、それぞれの配列が帯域を表します。それぞれの整数が色テーブルの各色のエントリを表し、色ごとに4つのエントリがあります |
IntWritable[] baseColorArray |
色の解釈を表す整数値を含む配列であり、それぞれのセルが1つの帯域を表します |
DoubleWritable[] noDataArray |
イメージのNODATA値を含む配列であり、それぞれのセルに関連する帯域の値が含まれます |
ByteWritable isProjection |
四角形にByte.MAX_VALUEの予測情報が含まれている場合に指定します |
ByteWritable isTransform |
四角形にByte.MAX_VALUEの地図変換配列情報が含まれている場合に指定します |
ByteWritable isMetadata |
四角形にByte.MAX_VALUEのメタデータ情報が含まれている場合に指定します |
IntWritable projectionLength |
予測情報の長さを指定します |
BytesWritable projectionRef |
予測情報のバイト数を指定します |
DoubleWritable[] geoTransform |
地理変換配列を含みます |
IntWritable metadataSize |
四角形の中のメタデータ値の数 |
IntWritable[] metadataLength |
それぞれのメタデータ値の長さを指定する配列 |
BytesWritable[] metadata |
四角形のメタデータの配列 |
GeneralInfoWritable mosaicInfo |
モザイクxml内のユーザー定義情報。モザイク出力機能は変更しないでください。新しい名前で元のxmlファイルを変更し、その新しいxmlを使用して実行および処理します |
MapWritable extraFields |
分析のためにリデューサ・フェーズに渡されるすべての四角形に固有のパラメータのキー/値ペアがリストされた地図 |
処理クラスおよびメソッド
四角形のピクセルを変更する場合は、次のメソッドを使用して、最初に帯域情報を配列に取り込みます。
byte [] bandData1 =(byte []) img.getBand(0);
帯域1の四角形のピクセルを表すバイト数は、現在bandData1配列にあります。底の索引はゼロです。
getBand(int bandId)メソッドは指定したbandIdの位置のラスターの帯域を取得します。取得したオブジェクトをラスターの配列型へのキャストに使用できます。これはbyte、short (unsigned int 16ビット、int 16ビット)、int (unsigned int 32ビット、int 32ビット)、float (float 32ビット)、またはdouble (float 64ビット)のいずれかです。
配列でピクセルを使用できる場合は、この時点でユーザーの要求に応じて変換できます。
ピクセルの処理後、ImageBandWritableの同じインスタンスを使用する必要がある場合は、次のメソッドを実行します。
img.removeBands;
これにより、前の帯域のコンテンツが削除され、新しい帯域の追加を開始できます。新しい帯域を追加するには、次のメソッドを使用します。
img.addBand(Object band);
それ以外の場合は、次のメソッドを使用して特定の帯域を置き換えることもできます。
img.replaceBand(Object band, int bandId)
前述のメソッドでは、bandは、ピクセル情報が含まれる配列であり、bandIDは、置換対象の帯域の識別子です。処理操作の結果、影響を受けるインスタンス・サイズ、データ型、bytesNumberおよびその他のプロパティを必ず更新してください。各プロパティには、セッターを使用できます。
Oracle Image Serverコンソールを使用している場合は、すべての処理クラスが単一のJARファイルに含まれます。コマンドライン・オプションを使用している場合、処理クラスはそれぞれ異なるJARファイルに配置されます。
クラスパス内に新しいクラスが表示されている場合、これらを<process><classMapper>または<process><classReducer>セクションのモザイクXMLに追加する必要があります。追加されたすべての<class>要素は、表示されている順序で実行されます。マッパーの場合は最終モザイク操作が実行される直前、リデューサの場合はすべての処理済四角形が単一のデータ・セットにまとめられる直後です。
ローカル地図代数演算は入力ラスター上で処理でき、そこではピクセル数が操作に応じて変更されます。構成XMLの操作の順序によって、処理される操作の順序が決まります。すべての地図代数演算が処理されると、処理クラスが実行され、最後にモザイク操作が実行されます。
次の地図代数演算はモザイク構成XMLの<operations>要素に追加でき、演算名を要素名として使用できます。(各操作がサポートされているデータ型は、カッコで囲まれてリストされています。)
localnot: 各ピクセルの否定を取得し、ビット・パターンを反転します。結果が負の値でデータ型が符号なしの場合、NODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(バイト、Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット)
locallog: ピクセルの自然対数(底e)を返します。結果がNaNの場合は元のピクセル値が設定され、結果が無限の場合はNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
locallog10: ピクセルの底10の対数が返されます。結果がNaNの場合は元のピクセル値が設定され、結果が無限の場合はNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localadd: 指定した値を引数としてピクセルに追加します。例: <localadd arg="5"/>。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localdivide: 各ピクセルの値を、引数として指定した値セットで除算します。例: <localdivide arg="5"/>。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localif: 各ピクセルの値を引数として指定した値および条件に基づいて変更します。有効な演算子: =、<、>、>=、< !=。例: <localif operator="<" operand="3" newvalue="6"/>、ここでは、値が3未満のピクセルがすべて変更され、新しい値が6に設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localmultiply: 各ピクセルの値に、引数として指定した値を乗算します。例: <localmultiply arg="5"/>。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localpow: 各ピクセルの値を、指定した引数の値のべき乗に切り上げます。例: <localpow arg="5"/>。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localsqrt: 各ピクセルを正しく四捨五入した正の値の平方根を返します。結果が無限またはNaNの場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localsubstract: すべてのピクセル値から引数として指定した値を減算します。例: <localsubstract arg="5"/>。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localacos: ピクセルの逆余弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localasin: ピクセルの逆正弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localatan: ピクセルの逆正接を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localcos: ピクセルの余弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localcosh: ピクセルの逆双曲線余弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localsin: ピクセルの正弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localtan: ピクセルの正接を計算します。ピクセルの余弦が0の場合、このピクセルは変更されません。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localsinh: ピクセルの逆双曲線正弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localtanh: ピクセルの双曲線正接を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localdefined: セルの値がNODATAではない場合は整数型指定のピクセルが1にマップされ、それ以外の場合は0にマップされます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット、Float 32ビット)
localundefined: セルの値がNODATAではない場合は整数型指定のラスターが0にマップされ、それ以外の場合は1にマップされます。(Unsigned int 16ビット、Unsigned int 32ビット、Int 16ビット、Int 32ビット)
localabs: 符号付きピクセルの絶対値を返します。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localnegate: 各ピクセルの値から1を引いた数を乗算します。(Int 16ビット、Int 32ビット、Float 32ビット、Float 64ビット)
localceil: ピクセル値以上であり、ある数学的整数と等しい最小値を返します。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Float 32ビット、Float 64ビット)
localfloor: ピクセル値以下であり、ある数学的整数と等しい最小値を返します。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。(Float 32ビット、Float 64ビット)
localround: 各ピクセルに最も近い整数値を返します。(Float 32ビット、Float 64ビット)
複数のラスターが含まれるラスター代数演算を処理できます。この場合、操作に応じて、および同じセル内の関連するすべてのラスターのピクセルを考慮して、ピクセルが変更されます。
一度に処理できる操作は1つのみであり、この操作は、<multipleops>要素を使用して構成XMLに定義されます。その値は、処理対象の操作です。
操作には2つのタイプがあります。
基本的な複数のラスター代数演算は、ユーザーのリデュース処理クラスの直前のリデュース・フェーズで実行されます。
複雑な複数のラスター代数演算は、マッピング・フェーズで実行されます。
基本的な複数のラスター代数演算は、ジョブのリデュース・フェーズで実行されます。
これらは、モザイク操作または単なる処理要求とともに要求できます。モザイク操作とともに要求された場合、入力ラスターは同じMBR、ピクセル・サイズ、SRIDおよびデータ型を持つ必要があります。
モザイク操作を実行する場合、交差するピクセル(両方のラスターで同一のピクセル)のみが影響を受けます。
この操作が処理されるのは、マッピング四角形が出力データ・セットにまとめられ、(モザイク操作が要求された場合は)交差するピクセル値、または(モザイクが要求されていない場合は)すべてのピクセルが要求された操作に応じて変更される場合です。
ラスターがデータ・セットに追加される順序は、モザイク操作が要求された場合はモザイク操作の順序であり、それ以外の場合は、カタログ内の表示の順序です。
次の基本的な複数のラスター代数演算が使用可能です。
add: ラスター・シーケンスの同じセル内のすべてのピクセルを加算します。
substract: ラスター・シーケンスの同じセル内のすべてのピクセルを減算します。
divide: ラスター・シーケンスの同じセル内のすべてのピクセルを除算します。
multiply: ラスター・シーケンスの同じセル内のすべてのピクセルを乗算します。
min: ラスター・シーケンスの同じセル内のピクセルの最小値を割り当てます。
max: ラスター・シーケンスの同じセル内のピクセルの最大値を割り当てます。
mean: ラスター・シーケンスの同じセル内のすべてのピクセルの平均値を計算します。
and: ラスター・シーケンスの同じセル内のすべてのピクセルのバイナリ“and”演算を処理し、“and“演算によって結果にビットがコピーされます(両方のオペランドに存在する場合)。
or: ラスター・シーケンスの同じセル内のすべてのピクセルのバイナリ“or”演算を処理し、“or“演算によってビットがコピーされます(どちらかのオペランドに存在する場合)。
xor: ラスター・シーケンスの同じセル内のすべてのピクセルのバイナリ“xor”演算を処理し、“xor“演算によってビットがコピーされます(1つのオペランドに存在するが両方には存在しない場合)。
複雑な複数のラスター代数演算は、ジョブのマッピング・フェーズで実行され、ジョブはこの演算のみを処理できます。SRIDのサイズ変更、変更、またはカスタム・マッピングに対する要求は前に実行されている必要があります。このジョブの入力は、同じMBR、SRID、データ型およびピクセル・サイズを持つ一連のラスターです。
このジョブの四角形には、カタログ内のすべてのラスターの一部が含まれます。このため、すべてのマッパーがすべてのラスター内のセルの領域にアクセスでき、演算はそこで処理されます。結果として生成されたすべてのセルのピクセルはこのコンテキストで書き込まれるため、リデューサはリデューサ処理クラスを処理する前に結果を出力データ・セットに配置できます。
ラスターが演算を評価すると見なされる順序は、カタログ内に表示される順序です。
次の複雑な複数のラスター代数演算が使用可能です。
combine: ラスター・シーケンスの同じセル内の入力値の一意の組合せごとに一意の出力値を割り当てます。
majority: 最も多数のラスター・シーケンスの同じセル内の値を割り当てます。値が結合されている場合、右側の値が選択されます。
minority: 最も少数のラスター・シーケンスの同じセル内の値を割り当てます。値が結合されている場合、右側の値が選択されます。
variety: ラスター・シーケンスの同じセルごとに一意の値のカウントを割り当てます。
mask: 最初のラスターの値を使用してラスターを生成しますが、シーケンスの残りのラスター内の対応するピクセルが特定のマスク値に設定されているピクセルのみが含まれます。それ以外の場合は、0が設定されます。
inversemask: 最初のラスターの値を使用してラスターを生成しますが、シーケンスの残りのラスター内の対応するピクセルが特定のマスク値に設定されていないピクセルのみが含まれます。それ以外の場合は、0が設定されます。
equals: バイト・データ型でラスターを作成します。この場合、すべての入力ラスターに対応するセルが同じ値を持つ場合、セル値は1です。それ以外の場合は、0が設定されます。
unequal: バイト・データ型でラスターを作成します。この場合、すべての入力ラスターに対応するセルが異なる値を持つ場合、セル値は1です。それ以外の場合は、0が設定されます。
greater: バイト・データ型でラスターを作成します。この場合、最初のラスター内のセル値が、すべての入力ラスターに対応する残りのセル値より大きい場合、セル値は1です。それ以外の場合は、0が設定されます。
greaterorequal: バイト・データ型でラスターを作成します。この場合、最初のラスター内のセル値が、すべての入力ラスターに対応する残りのセル値以上である場合、セル値は1です。それ以外の場合は、0が設定されます。
less: バイト・データ型でラスターを作成します。この場合、最初のラスター内のセル値が、すべての入力ラスターに対応する残りのセル値より小さい場合、セル値は1です。それ以外の場合は、0が設定されます。
lessorequal: バイト・データ型でラスターを作成します。この場合、最初のラスター内のセル値が、すべての入力ラスターに対応する残りのセル値以下である場合、セル値は1です。それ以外の場合は、0が設定されます。
このフレームワークでは、XMLを作成せずに、Javaアプリケーションを使用してラスターをロードし、処理するラスター処理APIが用意されています。このアプリケーションはクラスタ内またはリモート・ノード上で実行できます。
このAPIはフレームワーク操作へのアクセスが可能であり、WebサービスまたはスタンドアロンJavaアプリケーションに使用できます。
いずれかのジョブを実行するには、HadoopConfigurationオブジェクトを作成する必要があります。このオブジェクトは、ジョブの作成、ラスターの操作、およびジョブの実行に必要な構成情報(JARファイル名やGDALパスなど)の設定に使用されます。基本のロジックは次のとおりです。
//Creates Hadoop Configuration
HadoopConfiguration hadoopConf = new HadoopConfiguration();
//Assigns GDAL_DATA location based on specified SHAREDDIR, this data folder is required by gdal to look for data tables that allow SRID conversions
String gdalData = sharedDir + ProcessConstants.DIRECTORY_SEPARATOR + "data";
hadoopConf.setGdalDataPath(gdalData);
//Sets jar name for processor
hadoopConf.setMapreduceJobJar("hadoop-imageprocessor.jar");
//Creates the job
RasterProcessorJob processor = (RasterProcessorJob) hadoopConf.createRasterProcessorJob();
APIがリモート・ノードで使用されている場合は、Hadoop Configurationオブジェクトでプロパティを設定してクラスタに接続できます。次に例を示します。
//Following config settings are required for standalone execution. (REMOTE ACCESS)
hadoopConf.setUser("hdfs");
hadoopConf.setHdfsPathPrefix("hdfs://den00btb.us.oracle.com:8020");
hadoopConf.setResourceManagerScheduler("den00btb.us.oracle.com:8030");
hadoopConf.setResourceManagerAddress("den00btb.us.oracle.com:8032");
hadoopConf.setYarnApplicationClasspath("/etc/hadoop/conf/,/usr/lib/hadoop/*,/usr/lib/hadoop/lib/*," +
"/usr/lib/hadoop-hdfs/*,/usr/lib/hadoop-hdfs/lib/*,/usr/lib/hadoop-yarn/*," +
"/usr/lib/hadoop-yarn/lib/*,/usr/lib/hadoop-mapreduce/*,/usr/lib/hadoop-mapreduce/lib/* ");
ジョブは作成後、その実行のプロパティをジョブ・タイプに応じて設定する必要があります。ジョブ・クラスには、ラスターをHDFSにロードするRasterLoaderJob、およびそれを処理するRasterProcessorJobの2つがあります。
次の例では、ハワイのラスターをAPICALL_HDFSディレクトリにロードします。ここでは、共有フォルダにサムネイルを作成し、四角形のそれぞれの辺と重なる10ピクセルを指定します。
private static void executeLoader(HadoopConfiguration hadoopConf){
hadoopConf.setMapreduceJobJar("hadoop-imageloader.jar");
RasterLoaderJob loader = (RasterLoaderJob) hadoopConf.createRasterLoaderJob();
loader.setFilesToLoad("/net/den00btb/scratch/zherena/hawaii/hawaii.tif");
loader.setTileOverlap("10");
loader.setOutputFolder("APICALL");
loader.setRasterThumbnailFolder("/net/den00btb/scratch/zherena/processOutput");
try{
loader.setGdalPath("/net/den00btb/scratch/zherena/gdal/lib");
boolean loaderSuccess = loader.execute();
if(loaderSuccess){
System.out.println("Successfully executed loader job");
}
else{
System.out.println("Failed to execute loader job");
}
}catch(Exception e ){
System.out.println("Problem when trying to execute raster loader " + e.getMessage());
}
}
}
次の例では、ロードしたラスターを処理します。
private static void executeProcessor(HadoopConfiguration hadoopConf){
hadoopConf.setMapreduceJobJar("hadoop-imageprocessor.jar");
RasterProcessorJob processor = (RasterProcessorJob) hadoopConf.createRasterProcessorJob();
try{
processor.setGdalPath("/net/den00btb/scratch/zherena/gdal/lib");
MosaicConfiguration mosaic = new MosaicConfiguration();
mosaic.setBands(3);
mosaic.setDirectory("/net/den00btb/scratch/zherena/processOutput");
mosaic.setFileName("APIMosaic");
mosaic.setFileSystem(RasterProcessorJob.FS);
mosaic.setFormat("GTIFF");
mosaic.setHeight(3192);
mosaic.setNoData("#FFFFFF");
mosaic.setOrderAlgorithm(ProcessConstants.ALGORITMH_FILE_LENGTH);
mosaic.setOrder("1");
mosaic.setPixelType("1");
mosaic.setPixelXWidth(67.457513);
mosaic.setPixelYWidth(-67.457513);
mosaic.setSrid("26904");
mosaic.setUpperLeftX(830763.281336);
mosaic.setUpperLeftY(2259894.481403);
mosaic.setWidth(1300);
processor.setMosaicConfigurationObject(mosaic.getCompactMosaic());
RasterCatalog catalog = new RasterCatalog();
Raster raster = new Raster();
raster.setBands(3);
raster.setBandsOrder("1,2,3");
raster.setDataType(1);
raster.setRasterLocation("/user/hdfs/APICALL/net/den00btb/scratch/zherena/hawaii/hawaii.tif.ohif");
catalog.addRasterToCatalog(raster);
processor.setCatalogObject(catalog.getCompactCatalog());
boolean processorSuccess = processor.execute();
if(processorSuccess){
System.out.println("Successfully executed processor job");
}
else{
System.out.println("Failed to execute processor job");
}
}catch(Exception e ){
System.out.println("Problem when trying to execute raster processor " + e.getMessage());
}
}
前の例でモザイクの結果がHDFSに格納される場合は、サムネイルがオプションになります。JARファイルの処理が指定されている場合(追加のユーザー処理クラスが指定されている場合に使用)、このクラスを含むJARファイルの場所を指定する必要があります。モザイクを正しく生成するには、その他のパラメータが必要です。
処理APIを使用するいくつかの例については、/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/srcを参照してください。Javaクラスを確認し、その目的を理解します。これらは/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/cmdにあるそれぞれの例に示すスクリプトを使用して実行できます。
スクリプトを実行してその結果を検証した後、用意されているスクリプト/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/build.xmlを使用して、試験を実行し、コンパイルできるようにJavaソース・ファイルを変更します。/opt/oracle/oracle-spatial-graph/spatial/raster/jlib directoryへの書込みアクセスが可能であることを確認します。
カスタム処理クラスを作成する場合、Oracle Spatial Hadoop Raster Simulator Frameworkを使用して、これらをOracle Raster Processing Frameworkにプラグインすることを「偽装」することにより、次を実行できます。
ローカル・コンピュータでのユーザー処理クラスの開発
ユーザー処理クラスをクラスタ内またはBig Data Lite内でデプロイして正しく機能するかどうかを検証する必要性の回避
ユーザー処理クラスのデバッグ
小さいローカルデータ・セットの使用
ローカル・デバッグ出力の作成
ユニット・テストの自動化
シミュレータ・フレームワークにより、ローカル環境内のロード・プロセスおよび処理プロセスがクラスタ内で実行されているかのように、これらがエミュレートされます。このため、必要なのは、1つ以上のラスターをロードしてXMLまたは構成オブジェクト内の仕様に応じてこれらを処理するJunitテスト・ケースを作成することのみです。
タイルは指定したブロック・サイズに応じて生成されるため、ブロック・サイズを設定する必要があります。実行するマッパーおよびリデューサの数は、通常のクラスタ実行の場合と同じように、タイルの数によって決まります。ロード・プロセス中に生成されるOHIFファイルは、HDFSが必要ないため、ローカル・ディレクトリに格納されます。
シミュレータ(“モック”)オブジェクト
ユーザーのローカル環境要件
ラスターをロードおよび処理するためのサンプル・テスト・ケース
シミュレータ(“モック”)オブジェクト
ラスターをロードし、処理可能な.OHIFファイルに変換するには、RasterLoaderJobMockを実行する必要があります。このクラス・コンストラクタは、ブロック・サイズ、ロード対象のディレクトリまたはラスター、OHIFファイルを格納するための出力ディレクトリ、およびgdalディレクトリを含める必要があるHadoopConfigurationを受け取ります。入力ファイルおよびユーザー構成を表すパラメータは、これらを指定する方法によって変化します。
カタログおよびユーザー構成XMLファイルの場所の文字列
カタログ・オブジェクト(CatalogMock)
構成オブジェクト(MosaicProcessConfigurationMockまたはSingleProcessConfigurationMock)
単一のラスター処理およびユーザー構成の場所(MosaicProcessConfigurationMockまたはSingleProcessConfigurationMock)
ユーザーのローカル環境要件
テスト・ケースを作成する前に、ローカル環境を構成する必要があります。
1. ディレクトリにネイティブgdalライブラリgdal-dataおよびlibprojがあることを確認します。
Linuxの場合:
「Cartographic Projections Libraryの取得およびコンパイル」の手順に従いlibproj.soを取得します。
クラスタまたはBigDataLite VM (/opt/oracle/oracle-spatial-graph/spatial/raster/gdal)にあるSpatialインストールからgdalディストリビューションを取得します。
libproj.soを残りのネイティブgdalライブラリとともにgdal/libの下のローカルgdalディレクトリに移動します。
Windowsの場合:
クラスタまたはBigDataLite VM (/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/mock/lib/gdal_windows.x64.zip)にあるSpatialインストールからgdalディストリビューションを取得します。
Visual Studioがインストールされていることを確認します。インストールする場合、「Common Tools for Visual C++」を選択していることを確認します。
PROJ 4ソース・コード、バージョン・ブランチ4.9をhttps://trac.osgeo.org/proj/browser/branches/4.9からダウンロードします。
Visual Studio開発者コマンド・プロンプトを開き、以下を入力します。
cd PROJ4/src_dir nmake /f makefile.vc
proj.dllを残りのネイティブgdalライブラリとともにgdal/binの下のローカルgdalディレクトリに移動します。
GDALネイティブ・ライブラリをシステム・パスに追加します。
Linuxの場合: LD_LIBRARY_PATHを対応するネイティブgdalライブラリ・ディレクトリとともにエクスポートします。
Windowsの場合: Path環境変数にネイティブgdalライブラリ・ディレクトリを追加します。
JavaプロジェクトにJunitライブラリがあることを確認します。
Javaプロジェクトのクラスパス内に次のHadoop jarおよびOracle Image Processing Frameworkファイルが含まれることを確認します。これらは、Oracle BigDataLite VMまたはクラスタから取得できます。これらはすべて、Hadoopディストリビューションに含まれるjarです。特定のフレームワークのjarについては、/opt/oracle/oracle-spatial-graph/spatial/raster/jlibを参照してください。
(次のリストでは、VERSION_INCLUDEDは、ファイルが含まれるHadoopインストールからのバージョン番号です。これは、BDAクラスタである場合やBigDataLite VMである場合があります。)
commons-collections-VERSION_INCLUDED.jar commons-configuration-VERSION_INCLUDED.jar commons-lang-VERSION_INCLUDED.jar commons-logging-VERSION_INCLUDED.jar commons-math3-VERSION_INCLUDED.jar gdal.jar guava-VERSION_INCLUDED.jar hadoop-auth-VERSION_INCLUDED-cdhVERSION_INCLUDED.jar hadoop-common-VERSION_INCLUDED-cdhVERSION_INCLUDED.jar hadoop-imageloader.jar hadoop-imagemocking-fwk.jar hadoop-imageprocessor.jar hadoop-mapreduce-client-core-VERSION_INCLUDED-cdhVERSION_INCLUDED.jar hadoop-raster-fwk-api.jar jackson-core-asl-VERSION_INCLUDED.jar jackson-mapper-asl-VERSION_INCLUDED.jar log4j-VERSION_INCLUDED.jar slf4j-api-VERSION_INCLUDED.jar slf4j-log4j12-VERSION_INCLUDED.jar
ラスターをロードおよび処理するためのサンプル・テスト・ケース
Javaプロジェクトがテスト・ケース用として準備された後、ラスターのロードおよび処理をテストできます。
次の例では、setUpメソッドを使用してクラスを作成し、gdal、ロード対象のラスター、構成XMLファイル、出力サムネイル、ohifファイルおよび処理結果用のディレクトリを構成します。また、ブロック・サイズ(8 MB)も構成しています。(単一のコンピュータの場合はブロック・サイズを小さくすることをお薦めします。) /**
* Set the basic directories before starting the test execution
*/
@Before
public void setUp(){
String sharedDir = "C:\\Users\\zherena\\Oracle Stuff\\Hadoop\\Release 4\\MockTest";
String allAccessDir = sharedDir + "/out/";
gdalDir = sharedDir + "/gdal";
directoryToLoad = allAccessDir + "rasters";
xmlDir = sharedDir + "/xmls/";
outputDir = allAccessDir;
blockSize = 8;
}
次の例では、RasterLoaderJobMockオブジェクトを作成し、ロード対象のラスター、およびOHIFファイルの出力パスを設定します。
/**
* Loads a directory of rasters, and generate ohif files and thumbnails
* for all of them
* @throws Exception if there is a problem during load process
*/
@Test
public void basicLoad() throws Exception {
System.out.println("***LOAD OF DIRECTORY WITHOUT EXPANSION***");
HadoopConfiguration conf = new HadoopConfiguration();
conf.setBlockSize(blockSize);
System.out.println("Set block size of: " +
conf.getProperty("dfs.blocksize"));
RasterLoaderJobMock loader = new RasterLoaderJobMock(conf,
outputDir, directoryToLoad, gdalDir);
//Puts the ohif file directly in the specified output directory
loader.dontExpandOutputDir();
System.out.println("Starting execution");
System.out.println("------------------------------------------------------------------------------------------------------------");
loader.waitForCompletion();
System.out.println("Finished loader");
System.out.println("LOAD OF DIRECTORY WITHOUT EXPANSION ENDED");
System.out.println();
System.out.println();
}
次の例では、RasterProcessorJobMockオブジェクトに対するカタログおよびユーザー構成XMLファイルを指定します。catalog xmlがローカルOHIFファイルの正しい場所を指し示していることを確認します。
/**
* Creates a mosaic raster by using configuration and catalog xmls.
* Only two bands are selected per raster.
* @throws Exception if there is a problem during mosaic process.
*/
@Test
public void mosaicUsingXmls() throws Exception {
System.out.println("***MOSAIC PROCESS USING XMLS***");
HadoopConfiguration conf = new HadoopConfiguration();
conf.setBlockSize(blockSize);
System.out.println("Set block size of: " +
conf.getProperty("dfs.blocksize"));
String catalogXml = xmlDir + "catalog.xml";
String configXml = xmlDir + "config.xml";
RasterProcessorJobMock processor = new RasterProcessorJobMock(conf, configXml, catalogXml, gdalDir);
System.out.println("Starting execution");
System.out.println("------------------------------------------------------------------------------------------------------------");
processor.waitForCompletion();
System.out.println("Finished processor");
System.out.println("***********************************************MOSAIC PROCESS USING XMLS ENDED***********************************************");
System.out.println();
System.out.println();
RasterProcessorJobMockに対してサポートされている様々な構成を使用した追加例は、/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/mock/srcに用意されています。これらには、外部処理クラスを使用した例が含まれており、このクラスも組み込まれていて、デバッグすることもできます。
Oracle Big Data Spatial Raster Processing for Apache Sparkは、Spatial Raster Processing API for Javaです。
このAPIでは、次の機能を使用して、一連のユーザー定義の処理フェーズの結果からイメージを組み合わせて新たに作成できます。
各ブロック・サイズ分割が個別の四角形として格納され、その後のそれぞれの処理に使用される、HDFSイメージ・ストレージ
処理を分割するためにSparkを使用して並行して処理されるサブセット、モザイクおよびラスター代数演算。
GDAL形式、複数帯域イメージ、DEM (数値標高モデル)、複数ピクセル深度、およびSRIDのサポート
Spark Java API用のラスター処理を使用するには、最初にイメージをHDFSに保存し、次に各イメージをそれぞれ別のスマート・タイルに保存します。これにより、プロセッサを使用して各四角形を個別に処理できます。Sparkラスター・ローダーでは、単一イメージ、またはイメージのコレクションを並列でHDFSにインポートできるため、ロード時間を短縮できます。各ブロックにはすべてのラスター帯域のデータが含まれるため、特定のピクセルでその後処理が必要になった場合、その情報を単一ノードで処理できます。
Sparkラスター・ローダーの基本的なワークフローは、次のとおりです。
GDALを使用して、ラスターがインポートされ、ブロック・サイズに応じてこれらが四角形に分けられてから、各四角形がHDFSブロックとして格納されます。
ロード対象のラスターのセットが、JavaRDDの拡張機能であるSpatialRasterJavaRDDに読み込まれます。このRDDは、帯域の数、ピクセル・サイズ、HDFSブロック・サイズおよびラスター解像度に基づいてラスターごとに作成される四角形の情報を表すImagePieceWritableオブジェクトのコレクションです。これは、Spatial Hadoopローダーで使用されるカスタム入力形式を使用することによって実現されます。
各四角形のラスター情報がロードされます。このロードは、各四角形のエグゼキュータによって実行されるため、読込みは並行して実行されます。それぞれの四角形は一定のバイト数(ユーザー入力)が重なっているため、隣接する四角形の領域にかかっています。Sparkエグゼキュータの数は、四角形の数、イメージ解像度、およびブロック・サイズに応じて“n”個になります。
RDDはキーによってグループ化されるため、同じラスターに対応する四角形はすべて同じレコードの一部になります。このRDDは、OhifOutputFormatを使用してOHIFとして保存されます。このクラスは、エグゼキュータによってロードされた情報をすべてまとめ、そのイメージを解像度、帯域、オフセット、イメージ・データを含む特別な.ohif形式で格納します。これにより、それぞれの四角形を含むファイル・オフセットとノード場所が明らかになります。イメージを読み込み戻すには、特別な読込みプロセスが必要であり、このプロセスは、Spark SQLラスター・プロセッサに含まれています。
それぞれの四角形には、各帯域の情報が含まれます。これは、一部の四角形のみを処理し、それに対応するブロックのみをロードする場合に役立ちます。
ローダーは、コマンドラインでパラメータを設定するか、Spark APIを使用することにより、構成できます。
次の例は、spark-submitコマンドを使用して提供される入力パラメータを示します。
spark-submit --class <DRIVER_CLASS> --driver-memory <DRIVER_JVM> --driver-class-path <DRIVER_CLASSPATH> --jars <EXECUTORS_JARS> <DRIVER_JAR> -files <SOURCE_IMGS_PATH> -out <HDFS_OUTPUT_FOLDER> -gdal <GDAL_LIB_PATH> -gdalData <GDAL_DATA_PATH> [-overlap <OVERLAPPING_PIXELS>] [-thumbnail <THUMBNAIL_PATH>] [-expand <false|true>]
説明:
DRIVER_CLASSは、ドライバ・コードを持ち、Sparkによって実行されるクラスです。
DRIVER_JVMは、ドライバのJVMに割り当てるメモリーです。
DRIVER_CLASSPATHは、ドライバ・クラスのクラスパスで、jarはコロンによって区切られます。
EXECUTOR_JARSは、エグゼキュータに配布されるクラスパスで、jarはカンマによって区切られます。
DRIVER_JARは、Sparkによって実行される<DRIVER_CLASS>が含まれるjarです。
SOURCE_IMGS_PATHは、ソース・ラスターまたはフォルダのパスです。入力が複数の場合はカンマで区切ります。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。
HDFS_OUTPUT_FOLDERはロードしたイメージを格納するHDFS出力フォルダです。
OVERLAPPING_PIXELSはそれぞれの四角形の境界線上で重なるピクセルの任意の数であり、このパラメータが指定されていない場合、重なっている2つのピクセルのデフォルトが使用されます。
GDAL_LIB_PATHはGDALライブラリの場所を示すパスです。
GDAL_DATA_PATHはGDALデータ・フォルダの場所を示すパスです。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。
THUMBNAIL_PATHはロードしたイメージのサムネイルを格納する任意のパスです。NFSを介してクラスタ内のすべてにアクセスでき、Yarnユーザーの書込みアクセス権のあるパスを指定する必要があります。
-expandは、ロードされたラスターのHDFSパスによってソース・パス(すべてのディレクトリを含む)が拡張されるかどうかを制御します。これをfalseに設定すると、.ohifファイルは、(-oオプションを使用して指定された)出力ディレクトリに直接格納され、この場合、このラスター内のこのディレクトリのパスは含まれません。
それぞれの四角形には、各帯域の情報が含まれます。これは、一部の四角形のみを処理し、それに対応するブロックのみをロードする場合に役立ちます。
ローダーは、コマンドラインでパラメータを設定するか、Spark APIを使用することにより、構成できます。
Sparkラスター・ローダーに対する各出力イメージには、入力イメージごとに2つの出力ファイルがあります。
ソース・イメージのすべての四角形を集める.ohifファイル。各四角形(HDFSブロックとして格納されます)は、処理エグゼキュータによって別のインスタンスとして処理される場合があります。.ohifファイルは、–expandが使用されなかった場合、/user/<USER_EXECUTING_JOB>/OUT_FOLDER/<PARENT_DIRECTORIES_OF_SOURCE_RASTER>の下にあるユーザー指定フォルダに、-outフラグを付けて格納されます。それ以外の場合、.ohifは/user/<USER_EXECUTING_JOB>/OUT_FOLDER/に配置され、このファイルはoriginal_filename.ohifとして識別できます。
イメージのすべてのピースをリストし、それぞれがカバーする座標を示す関連メタデータ・ファイル。このファイルは、spatial_raster/metadataの場所にあるHDFSに置かれており、その名前は.ohifファイルの名前を使用してハッシュ生成されます。このファイルはOracle内部専用であり、ソース・ラスターの重要なメタデータをリストします。メタデータ・ファイルのサンプル行の一部は次のとおりです。
size:3200,2112 srid:26904 datatype:1 resolution:27.90809458890406,-27.90809458890406 file:/user/hdfs/ohiftest/opt/shareddir/spatial/data/rasters/hawaii.tif.ohif bands:3 mbr:532488.7648166901,4303164.583549625,582723.3350767174,4269619.053853762 0,532488.7648166901,4303164.583549625,582723.3350767174,4269619.053853762 thumbnailpath:/opt/shareddir/spatial/thumb/
-thumbnailフラグが指定されている場合、ソース・イメージのサムネイルが関連フォルダに格納されます。これは.ohifファイルの変換を視覚化する方法の1つです。実行ログには、コマンドyarn logs -applicationId <applicationId>を使用してアクセスできます。
イメージがHDFSにロードされたら、Spark SQLラスター・プロセッサを使用して処理できるようになります。モザイク定義XML構造またはSpark APIを使用して予想されるラスター出力機能を指定すると、モザイクUDFにより、四角形がその出力に適合するようフィルタおよび処理されます。ラスター代数演算はUDFで実行可能です。
Hadoopラスター処理フレームワークでも使用されるカスタムInputFormatは、ラスターSRIDおよび座標を使用して入力(モザイクの記述または単一のラスター)に基づいて特定のデータのブロックをロードし、処理操作を受け入れる前に最終出力に適合する帯域およびピクセルのみを選択します。
モザイク処理要求の場合、交差する四角形のみが選択され、これらの1つずつに分割が作成されます。
単一のラスター処理要求の場合、すべての四角形が選択され、これらの1つずつに分割が作成されます。
Spark SQLラスター・プロセッサを使用すると、四角形を表すすべての行とともに、入力カタログまたはラスターに基づいてOHIF四角形をフィルタしてDataframeにまとめ、Spatial UDF Spark機能を使用してこれらを処理できます。
簡略化されたSpark SQLラスター処理の擬似コード表現は、次のとおりです。
sqlContext.udf().register("localop", new LocalOperationsFunction(), DataTypes.StringType);
tileRows.registerTempTable("tiles");
String query = "SELECT localop(tileInfo, userRequest, \"localnot\"), userRequest FROM tiles";
DataFrame processedTiles = sqlContext.sql(query);
Spark SQLラスター・プロセッサの基本的なワークフローは、以下のとおりです。
処理対象のラスターが最初に四角形メタデータにRDDとしてロードされます。ユーザーがモザイク操作用の構成を設定している場合、これらの四角形をフィルタできます。RDDは後で、2つの複雑な行のSpark DataFrameに変換されます。最初の行は、四角形のすべてのメタデータが含まれるtileInfoで、2番目の行は、ラスタークライアントの予想される機能がリストされたユーザー入力構成が含まれるuserRequestです。
DataFrameが作成されたら、ドライバは、処理対象の問合せを実行する前に、“localop” UDFを登録するとともに、DataFrameも表として登録する必要があります。モザイクUDFを実行できるのは、ユーザーが必要なパラメータをすべて正しく構成した場合のみです。XMLが使用されておらず、APIを使用して構成が設定されている場合、setExecuteMosaic(false)メソッドが設定されていない限り、デフォルトでは、モザイク操作構成が予想されます。
モザイク操作では、すべての四角形から出力に適合するピクセルのみを選択し、必要に応じて解像度を変更してモザイク出力に追加します。
問合せが実行されたら、エグゼキュータにより、データのローカル性を保ちながら、四角形に対応するデータがロードされ、指定したローカル・ラスター代数演算が実行されます。
DataFrame内の行が新しいピクセル・データを使用して更新され、後処理が必要になった場合のためにドライバに返されます。
処理が完了したら、DataFrameは、処理された四角形のMapReduce表現であるImageBandWritableオブジェクトのリストに変換されます。これらは、ProcessedRasterCreatorに入力されます。ここでは、ローカル・ラスター代数演算および/またはモザイク操作の結果として生成されたバイトがまとめられ、ユーザーの要求に応じて最終的なラスターがHDFSまたは通常のファイル・システムに格納されます。
ユーザー構成入力のデータ型(ピクセル深度)と同じデータ型(モザイク深度)のイメージのみが該当します。ユーザーがモザイク出力に指定した座標と交差する四角形のみが含まれます。単一のラスター操作の場合、処理は完全なイメージに対して実行されるため、フィルタには、入力ラスターのすべての四角形が含まれます。
次の例は、spark-submitコマンドを使用して提供される入力パラメータを示します。
spark-submit --class <DRIVER_CLASS> --driver-memory <DRIVER_JVM> --driver-class-path <DRIVER_CLASSPATH> --jars <EXECUTORS_JARS> <DRIVER_JAR> -config <MOSAIC_CONFIG_PATH> -gdal <GDAL_LIBRARIES_PATH> -gdalData <GDAL_DATA_PATH> [-catalog <IMAGE_CATALOG_PATH>] [-file <SINGLE_RASTER_PATH>]
説明:
DRIVER_CLASSは、ドライバ・コードを持ち、Sparkによって実行されるクラスです。
DRIVER_JVMは、ドライバのJVMに割り当てるメモリーです。
DRIVER_CLASSPATHは、ドライバ・クラスのクラスパスで、jarはコロンによって区切られます。
EXECUTOR_JARSは、エグゼキュータに配布されるクラスパスで、jarはカンマによって区切られます。
DRIVER_JARは、Sparkによって実行される<DRIVER_CLASS>が含まれるjarです。
MOSAIC_CONFIG_PATHは、出力の機能を定義するモザイク構成XMLへのパスです。
GDAL_LIBRARIES_PATHはGDALライブラリの場所を示すパスです。
GDAL_DATA_PATHはGDALデータ・フォルダの場所を示すパスです。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。
IMAGE_CATALOG_PATHは、処理対象のHDFSイメージをリストするカタログxmlへのパスです。–fileフラグを使用して処理する単一のラスターも指定できるため、これはオプションです。
SINGLE_RASTER_PATHは、ジョブによって処理される.ohifファイルへの任意のパスです。これが設定されている場合、カタログを設定する必要はありません。
次の例のコマンドは、testFS.xmlファイルに設定されているモザイク出力定義を使用して、カタログ・ファイルinputSPARK.xmlにリストされるすべてのファイルを処理します。
spark-submit --class oracle.spatial.spark.raster.test.SpatialRasterTest --driver-memory 2048m --driver-class-path /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-raster-fwk-api.jar:/opt/oracle/oracle-spatial-graph/spatial/raster/jlib/gdal.jar:/opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageloader.jar:/opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageprocessor.jar --jars /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageloader.jar,/opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageprocessor.jar,/opt/oracle/oracle-spatial-graph/spatial/raster/jlib/gdal.jar /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/spark-raster-fwk-api.jar -taskType algebra -catalog /opt/shareddir/spatial/data/xmls/inputSPARK.xml -config /opt/shareddir/spatial/data/xmls/testFS.xml -gdal /opt/oracle/oracle-spatial-graph/spatial/raster/gdal/lib –gdalData /opt/shareddir/data
SparkラスターAPIを使用して、ドライバ・クラスを作成することによってラスターをロードおよび処理できます。
一部のクラス例は、/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/srcの下に用意されています。また、/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/cmdディレクトリにも、これらの例をコマンドラインから実行するためのスクリプトが含まれています。
スクリプトを実行してその結果を検証した後、用意されているスクリプト/opt/oracle/oracle-spatial-graph/spatial/raster/examples/java/build.xmlを使用して、試験を実行し、コンパイルできるようにJavaソース・ファイルを変更できます。/opt/oracle/oracle-spatial-graph/spatial/raster/jlibへの書込みアクセスが可能であることを確認します。
イメージ・ロードを実行するには、SpatialRasterLoaderオブジェクトを作成する必要があります。このオブジェクトを使用して、実行に必要な構成情報を設定します。インスタンスの作成には2つの方法があります。
//args is the String[] received from command line SpatialRasterLoader core = new SpatialRasterLoaderCore(args);
このトピックの対象であるAPIを使用してドライバ・クラス内で直接構成します
ローダーAPIを使用して、GDALライブラリ・パスを設定します。これにより、SparkContextおよび対応するHadoop構成が内部的に初期化されるためです。次に例を示します。
SpatialRasterLoader core = new SpatialRasterLoader();
core.setGdalLibrary("/opt/sharedddir/spatial/gdal");
core.setFilesToLoad("/opt/shareddir/spatial/rasters");
core.setHDFSOutputDirectory("ohifsparktest");
core.setGdalData("/opt/shareddir/data");
core.setOverlap("20");
core.setThumbnailDirectory("/opt/shareddir/spatial/");
関連するラスターの最も一般的なサイズに応じて、ブロック・サイズを必要に応じて変更できます。たとえば、クラスタのHDFSのブロック・サイズがデフォルトでは大きすぎるときに(256MBなど)、ユーザー・ラスターの平均サイズが64MBである場合、ピクセルによってブロックが埋められていなくてもHDFS内のブロックがすべての四角形によって占有されるため、実際のデータが含まれないHDFS空間の使用は避ける必要があります。このシナリオでは、次の例のように、ブロック・サイズを64MBに変更できます。
JavaSparkContext sc = core.getRasterSparkContext();
core.getHadoopConfiguration().set("dfs.blocksize", "67108864");
ローダーを実行するには、ラスターのロードが成功した場合はtrueを返し、失敗した場合はfalseを返すloadRastersメソッドを使用します。次に例を示します。
if (core.loadRasters(sc, StorageLevel.DISK_ONLY())) {
LOG.info("Successfully loaded raster files");
}
処理が指示終了した場合、OHIFファイルはHDFS内に格納され、対応するサムネイルは、ユーザー検証のために指定されたディレクトリに格納されます。
プロセッサを実行するには、SpatialRasterProcessorオブジェクトを作成し、実行に必要な構成情報を設定する必要があります。インスタンスの作成には2つの方法があります。
コマンドラインから受け取った引数の配列をパラメータとして送信します。次に例を示します。
//args is the String[] received from command line SpatialRasterProcessor processor = new SpatialRasterProcessor(args);
このトピックの対象であるAPIを使用してドライバ・クラス内で直接構成します
ローダーAPIを使用して、GDALライブラリ・パスを設定します。これにより、SparkContextおよび対応するHadoop構成が内部的に初期化されるためです。次に例を示します。
SpatialRasterProcessor processor = new SpatialRasterProcessor();
processor.setGdalLibrary("/opt/sharedddir/spatial/gdal");
processor.setGdalData("/opt/sharedddir/spatial/data");
処理対象のラスターを指定します。
処理するラスターのカタログの追加については、モザイク操作を実行する場合は特に、次の例を考慮してください。
String ohifPath = "ohifsparktest/opt/shareddir/spatial/data/rasters");
//Creates a catalog to list the rasters to process
RasterCatalog catalog = new RasterCatalog();
//Creates a raster object for the catalog
Raster raster = new Raster();
//raster of 3 bands
raster.setBands(3);
//the tree bands will appear in order 1,2,3. You may list less bands here.
raster.setBandsOrder("1,2,3");
//raster data type is byte
raster.setDataType(1);
raster.setRasterLocation(ohifPath + "hawaii.tif.ohif");
//Add raster to catalog
//catalog.addRasterToCatalog(raster);
Raster rasterKahoolawe = new Raster();
rasterKahoolawe.setBands(3);
rasterKahoolawe.setBandsOrder("1,2,3");
rasterKahoolawe.setDataType(1);
rasterKahoolawe.setRasterLocation(ohifPath + "kahoolawe.tif.ohif");
catalog.addRasterToCatalog(rasterKahoolawe);
//Sets the catalog to the job
processor.setCatalogObject(catalog.getCompactCatalog());
単一のラスターの処理については、次の例を考慮してください。
String ohifPath = "ohifsparktest/opt/shareddir/spatial/data/rasters"); //Set the file to process to the job processor.setFileToProcess(ohifPath + "NapaDEM.tif.ohif");*/
出力ラスターの詳細を定義するユーザー構成要求を設定します。
モザイク操作を実行する場合、予想される出力のすべての機能(座標を含む)をMosaicConfigurationオブジェクトに設定する必要があります。次の例では、以前にカタログに追加されたハワイのラスターが両方とも含まれるラスターを作成します。
MosaicConfiguration mosaic = new MosaicConfiguration();
mosaic.setFormat("GTIFF");
mosaic.setBands(3);
mosaic.setFileSystem(RasterProcessorJob.FS);
mosaic.setDirectory("/opt/shareddir/spatial/processtest");
mosaic.setFileName("HawaiiIslands");
mosaic.setHeight(986);
//value for pixels where there is no data, starts with #, followed by
//two characters per band
mosaic.setNoData("#FFFFFF");
//byte datatype
mosaic.setPixelType("1");
//width for pixels in X and Y
mosaic.setPixelXWidth(280.388143);
mosaic.setPixelYWidth(-280.388143);
mosaic.setSrid("26904");
//upper left coordinates
mosaic.setUpperLeftX(556958.985610);
mosaic.setUpperLeftY(2350324.082505);
mosaic.setWidth(1600);
mosaic.setOrderAlgorithm(ProcessConstants.ALGORITHM_FILE_LENGTH);
mosaic.setOrder(RasterProcessorJob.DESC);
//mosaic configuration must be set to the job
processor.setUserRequestConfigurationObject(mosaic.getCompactMosaic());
モザイク操作を実行しない場合は、より簡単な構成が必要です。次に例を示します。
MosaicConfiguration mosaic = new MosaicConfiguration();
mosaic.setExecuteMosaic(false);
mosaic.setBands(1);
mosaic.setLayers("1");
mosaic.setDirectory("/opt/shareddir/spatial/processtest");
mosaic.setFileSystem(RasterProcessorJob.FS);
mosaic.setNoData("#00");
この時点で、必要な構成がすべて完了しました。これで、処理を開始できます。
ラスターに対して問合せを実行する前に、すべての行が分割を表しているDataFrameにこれらをロードする必要があります。これらの分割はまとめて四角形のSpatialJavaRDDとして作成され、これがDataFrameに変換されます。使用可能なJVMランタイム・メモリーに応じて、DataFrameをメモリーまたはディスクにキャッシュすることをお薦めします。ディスクにキャッシュする場合、SparkインストールにKryoが使用されている必要があります。
DataFrameは、tileInfoとuserRequestという2つの複雑な列で構成されています。
tileInfo: ピクセル情報だけでなくメタデータの詳細を含む、すべての四角形に関するデータ。
表2-2 tileInfo列データ
| 列 | データ型 | NULL値可能 | 説明 |
|---|---|---|---|
dstWidthSize |
Integer |
False |
幅 |
dstHeightSize |
Integer |
False |
高さ |
bands |
Integer |
False |
帯域の数 |
dType |
Integer |
False |
データ型 |
piece |
Integer |
False |
ソース・ラスター内のピース合計のピース数 |
offX |
Integer |
False |
X内のオフセット |
offY |
Integer |
False |
Y内のオフセット |
sourceWidth |
Integer |
False |
ソース・ラスターの幅 |
sourceHeight |
Integer |
False |
ソース・ラスターの高さ |
bytesNumber |
Integer |
False |
バイトの数 |
baseArray |
[[Pixel DataType]] |
False |
ピクセルの配列(帯域ごとに1つ) |
basePaletteArray |
[[整数]] |
True |
パレット解釈の配列(ラスターに含まれる場合、帯域ごとに1つ) |
baseColorArray |
[Integer] |
False |
色の配列(帯域ごとに1つ) |
noDataArray |
[Double] |
False |
NODATA値の配列(帯域ごとに1つ) |
Overlap |
Integer |
False |
重なるピクセルの数 |
leftOv |
Byte |
False |
左側に重なるピクセルがあるかどうかを示すフラグ |
rightOv |
Byte |
False |
右側に重なるピクセルがあるかどうかを示すフラグ |
upOv |
Byte |
False |
上側に重なるピクセルがあるかどうかを示すフラグ |
downOv |
Byte |
False |
下側に重なるピクセルがあるかどうかを示すフラグ |
projectionRef |
String |
False |
予測参照 |
geoTransform |
[Double] |
False |
地理変換配列 |
Metadata |
[String] |
False |
場所メタデータ |
lastModified |
Long |
False |
ソース・ラスターの最終変更日 |
imageLength |
Double |
False |
ソース・ラスターの長さ |
dataLength |
Integer |
True |
モザイク後のバイトの数 |
xCropInit |
Integer |
True |
モザイク後のX内の開始ピクセル |
yCropInit |
Integer |
True |
モザイク後のY内の開始ピクセル |
xCropLast |
Integer |
True |
モザイク後のX内の終了ピクセル |
yCropLast |
Integer |
True |
モザイク後のY内の終了ピクセル |
catalogOrder |
Integer |
False |
カタログ内の順序 |
baseMountPoint |
String |
False |
ソース・ラスターのパス |
sourceResolution |
String |
False |
ソース・ラスターの解像度 |
extraFields |
[String] |
True |
その他のフィールド・マップ、NA |
userRequest: 予想される出力ラスター機能が定義されているユーザー要求構成。
表2-3 userRequest列データ
| 列 | データ型 | NULL値可能 | 説明 |
|---|---|---|---|
offset |
Long |
False |
オフセット |
piece |
Integer |
False |
ピース数 |
splitSize |
Long |
False |
分割サイズ |
bandsToAdd |
String |
False |
出力に含める帯域(“1,2,3”など) |
upperLeftX |
Double |
True |
モザイクの要求時に使用されるXの左上の出力の座標 |
upperLeftY |
Double |
True |
モザイクの要求時に使用されるYの左上の出力の座標 |
lowerRightX |
Double |
True |
モザイクの要求時に使用されるXの右下の出力の座標 |
lowerRightY |
Double |
True |
モザイクの要求時に使用されるYの右下の出力の座標 |
width |
Integer |
True |
モザイクが要求されたときに使用される出力の幅 |
height |
Integer |
True |
モザイクが要求されたときに使用される出力の高さ |
srid |
String |
True |
モザイクが要求されたときに使用される出力のSRID |
order |
String |
True |
モザイクが要求されたときに使用される出力の順序(昇順または降順) |
format |
String |
True |
モザイクが要求されたときに使用される出力のGDAL形式 |
noData |
String |
False |
出力のNODATA値(#の後ろに帯域当たり2桁の数値、たとえば、3帯域出力の場合は“#000000”) |
pixelType |
String |
True |
モザイクが要求されたときに使用される出力のGDALデータ型 |
Directory |
String |
False |
出力ディレクトリ |
pixelXWidth |
Double |
True |
モザイクが要求されたときに使用される出力のピクセルの幅 |
pixelYWidth |
Double |
True |
モザイクが要求されたときに使用される出力のピクセルの高さ |
wkt |
String |
False |
ソース予測参照 |
mosaicWkt |
String |
True |
モザイクが要求されたときに使用される出力の予測参照 |
processingClasses |
String |
True |
実行対象のユーザー処理クラス(Sparkではまだサポートされていません) |
reducingClasses |
String |
True |
実行対象のユーザー・リデュース・クラス(Sparkではまだサポートされていません) |
tempOut |
String |
True |
HDFS出力が要求された場合の一時出力フォルダ(Sparkではまだサポートされていません) |
filename |
String |
False |
出力のファイル名 |
contextId |
String |
False |
実行コンテキストID |
sourceResolution |
String |
False |
ソース・ラスターの解像度 |
catalogOrder |
Integer |
False |
カタログ内のソース・ラスターの順序 |
executeMosaic |
Boolean |
False |
モザイク操作が要求されたかどうかを示すフラグ |
次の例では、DataFrameを作成し、これに関する情報を表示します。
JavaSparkContext sc = processor.getRasterSparkContext();
SpatialRasterJavaRDD<GeneralInfoWritable> spatialRDD = processor.getProcessSplits();
HiveContext sqlContext = new HiveContext(sc.sc());
DataFrame tileRows = spatialRDD.createSpatialTileDataFrame(sqlContext, StorageLevel.DISK_ONLY());
Row[] rows = tileRows.collect();
System.out.println("First Tile info: ");
System.out.println("Width " + rows[0].getStruct(0).getInt(0));
System.out.println("Height " + rows[0].getStruct(0).getInt(1));
System.out.println("Total width " + rows[0].getStruct(0).getInt(7));
System.out.println("Total height " + rows[0].getStruct(0).getInt(8));
System.out.println("File " + rows[0].getStruct(0).getString(30));
System.out.println("First Tile User request data: ");
System.out.println("Bands to add " + rows[0].getStruct(1).getString(3));
Spark UDF localopを使用すると、Hadoopイメージ・プロセッサを使用してイメージを処理するために、「地図代数演算」で説明されているラスター代数演算を実行できます。Spark SQL UDF用の演算名およびサポート対象のデータ型は、Hadoopの場合と同じです
任意の問合せが実行される前に、ドライバ・クラスでは、UDFを登録するとともに、四角形のDataFrameを一時表として登録する必要があります。次に例を示します。
sqlContext.udf().register("localop", new LocalOperationsFunction(),
DataTypes.StringType);
tileRows.registerTempTable("tiles");
これで、localop UDFが登録され、使用する準備が整いました。この関数は、2つのパラメータを受け取ります。
tileInfo行
実行対象のラスター代数演算が含まれる文字列。同じ問合せ内で複数の演算を実行でき、これらはセミコロンで区切る必要があります。パラメータを受け取る演算の場合、これらをカンマで区切る必要があります。
この関数により、問合せに送信されたtileInfoが返されますが、これとともに、実行された演算に基づいて更新されたピクセル・データも返されます。
以下に、様々な演算の実行の例を示します。
String query = "SELECT localop(tileInfo, \"localnot\"),
userRequest FROM tiles";
String query = "SELECT localop(tileInfo,\"localadd,456;localdivide,2;
localif,>,0,12;localmultiply,20;
localpow,2;localsubstract,4;
localsqrt;localacos\"),
userRequest FROM tiles";
String query = "SELECT localop(tileInfo,\"localnot;localatan;localcos;
localasin;localtan;localcosh;
localtanh\"), userRequest FROM tiles";
問合せを実行するには、以下を入力します。
DataFrame cachedTiles = processor.queryAndCache(query, sqlContext);
この新しいDataFrameには、更新されたピクセルがあります。必要に応じて、特定の四角形のコンテンツをTIFファイルとして保存でき、このファイル内でこの四角形は構成済の出力ディレクトリ内に格納されます。次に例を示します。
Row[] pRows = cachedTiles.collect();
processor.debugTileBySavingTif(pRows[0],
processor.getHadoopConfiguration());
モザイク操作を実行するには、最初に任意のラスター代数演算を実行してから、モザイク操作を実行します。新しいSpark UDFがモザイク操作に使用されます。これは、tileInfoおよびuserRequest列を受け取り、モザイクに適合するよう更新されたtileInfoを返します。次に例を示します。
sqlContext.udf().register("mosaic", new MosaicFunction(),
DataTypes.StringType);
cachedTiles.registerTempTable("processedTiles");
String queryMosaic = "SELECT mosaic(tileInfo, userRequest), userRequest
FROM processedTiles";
DataFrame mosaicTiles = processor.queryAndCache(queryMosaic,
sqlContext);
処理が完了したら、内部操作用の一時HDFSディレクトリ、マージ対象のDataFrame、およびSparkコンテキストをHadoop構成から受け取るProcessedRasterCreatorを使用することにより、四角形を出力ラスターにまとめることができます。これにより、指定した出力ディレクトリ内に予想される出力ラスターが作成されます。次に例を示します。
try {
ProcessedRasterCreator creator = new ProcessedRasterCreator();
creator.create(new Text("createOutput"), mosaicTiles,
sc.hadoopConfiguration());
LOG.info("Finished");
} catch (Exception e) {
LOG.error("Failed processor job due to " + e.getMessage());
throw e;
}
Oracle Big Data Spatial Vector AnalysisはSpatial Vector Analysis APIであり、Hadoopジョブとして実行され、HDFSに格納されているデータの空間処理のためのMapReduceコンポーネントを提供します。
これらのコンポーネントでは、Spatial Java APIを利用して空間分析タスクを実行します。このAPIには、Webコンソールも用意されています。
関連項目:
次の情報を参照し、実装について詳しく理解してください。
Oracle Big Data Spatial Vector Analysisには、新旧両方の(コンテキスト・オブジェクト) Hadoop API用のクラスが用意されています。通常、mapredパッケージ内のクラスが古いAPIとともに使用され、mapreduceパッケージ内のクラスが新しいAPIとともに使用されます
このガイドの例では古いHadoop APIを使用しますが、すべての古いHadoop Vector APIクラスが新しいAPI内に同等のクラスを持ちます。たとえば、古いクラスであるoracle.spatial.hadoop.vector.mapred.job.SpatialIndexingは、oracle.spatial.hadoop.vector.mapreduce.job.SpatialIndexingという名前の新しい同等のクラスを持ちます。通常、別途記述がない限り、新しいHadoop API Vectorクラスを使用するには、mapredからmapreduceに変更するだけですみます。
mapredまたはmapreduceパッケージに含まれていないoracle.spatial.hadoop.vector.RecordInfoなどのクラスには、両方のHadoop APIとの互換性があります。
空間の索引付けは、キー/値ペアの形式をとり、Hadoop MapFileとして生成されます。それぞれのMapFileエントリには、元のデータの分割の1つに対する空間索引付けが含まれます。キー/値ペアには次の情報が含まれます。
キー: パス + 開始オフセット + 長さの形式の分割識別子。
値: 実際に索引付けしたレコードを含む空間索引の構造。
次の図は、ユーザー・データに関連する空間索引を表します。レコードはr1、r2、のように表現されます。レコードは分割(Split 1、Split 2、Split 3、Split n)ごとにまとめられます。それぞれの分割にはキー/値ペアがあり、キーは分割を表し、値はその分割のレコード上にあるRtree索引を表します。
空間の索引付けのレコードは、クラスoracle.spatial.hadoop.vector.RecordInfoを使用して表現されます。RecordInfoには通常、元のレコード・データのサブセット、およびレコードが格納されているファイル内でレコードを特定する方法が含まれています。それぞれのRecordInfoデータは次の2つに応じて異なります。
データの読取りに使用するInputFormat
レコードのデータを提供するRecordInfoProvider実装
RecordInfoには次のフィールドが含まれています。
Id: レコードIDを含むテキスト・フィールド。
Geometry: レコード・ジオメトリのあるJGeometryフィールド。
Extra fields: その他の任意のレコード・フィールドを名前/値ペアとして追加できます。値は常にテキストで表現されます。
Start offset: バイト・オフセットとしてのファイル内のレコードの位置。この値は元のデータを読み取るInputFormatによって異なります。
Length: 元のレコードの長さ(バイト単位)。
Path: ファイル・パスはオプションで追加できます。ファイル・パスは空間の索引付けエントリ・キーとして把握できるため、これはオプションです。ただし、空間索引を作成するときにRecordInfoインスタンスへのパスを追加するには、構成プロパティoracle.spatial.recordInfo.includePathFieldキーの値がtrueに設定されます。
空間索引はFileSplitInputFormat、SpatialIndexingMapper、InputFormat、およびRecordInfoProviderを組み合せて作成されますが、この最後の2つはユーザーが提供します。次のコードの例は、HDFSフォルダ/user/dataで特定されたデータの空間索引を作成するジョブを実行するために必要な構成の一部を示します。
//input
conf.setInputFormat(FileSplitInputFormat.class);
FileSplitInputFormat.setInputPaths(conf, new Path("/user/data"));
FileSplitInputFormat.setInternalInputFormatClass(conf, GeoJsonInputFormat.class);
FileSplitInputFormat.setRecordInfoProviderClass(conf, GeoJsonRecordInfoProvider.class);
//output
conf.setOutputFormat(MapFileOutputFormat.class);
FileOutputFormat.setOutputPath(conf, new Path("/user/data_spatial_index"));
//mapper
conf.setMapperClass(SpatialIndexingMapper.class);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(RTreeWritable.class);
この例では次のとおりです。
FileSplitInputFormatはジョブInputFormatとして設定されています。FileSplitInputFormatは、データを読み取るための別のInputFormat実装(internalInputFormat)を使用する抽象クラスであるCompositeInputFormat (新しいHadoop APIバージョン内のWrapperInputFormat)のサブクラスです。内部InputFormatおよびRecordInfoProvider実装はユーザーによって指定され、それぞれGeoJsonInputFormatおよびGeoJsonRecordInfoProviderに設定されます。
MapFileOutputFormatは、MapFileを生成するためにOutputFormatとして設定されます
マッパーはSpatialIndexingMappperに設定されます。マッパー出力キーおよび値のタイプは、Text (分割識別子)およびRTreeWritable (実際の空間索引)です。
リデューサ・クラスが指定されていないため、デフォルトのリデューサで実行されます。出力MapFileキーをソートするには、リデュース・フェーズが必要です。
また、この構成は、oracle.spatial.hadoop.vector.mapred.job.SpatialIndexingクラスを使用すると設定が容易になります。SpatialIndexingは空間索引を作成するジョブ・ドライバです。次の例では、SpatialIndexingインスタンスが作成および設定され、configure()メソッドを呼び出してジョブ構成への設定の追加に使用されます。構成が設定されると、ジョブが開始されます。
SpatialIndexing<LongWritable, Text> spatialIndexing = new SpatialIndexing<LongWritable, Text>();
//path to input data
spatialIndexing.setInput("/user/data");
//path of the spatial index to be generated
spatialIndexing.setOutput("/user/data_spatial_index");
//input format used to read the data
spatialIndexing.setInputFormatClass(TextInputFormat.class);
//record info provider used to extract records information
spatialIndexing.setRecordInfoProviderClass(TwitterLogRecordInfoProvider.class);
//add the spatial indexing configuration to the job configuration
spatialIndexing.configure(jobConf);
//run the job
JobClient.runJob(jobConf);
作成されるすべての空間索引にメタデータ・ファイルが生成されます。空間索引メタデータを使用すると、索引付きレコードの数、索引付きデータの最小外接矩形(MBR)、および空間索引と索引付きソース・データの両方のパスなど、空間索引に関連する情報を簡単に検索できます。空間索引メタデータは、空間索引名を使用して取得できます。
空間索引メタデータ・ファイルには、次の情報が含まれます。
空間索引名
空間索引へのパス
索引付きレコードの数
ローカル索引の数
索引付きレコードに含まれる追加フィールド
SRID、次元、許容差、境界、およびジオメトリが測地であるかどうかの是非などのジオメトリ・レイヤー情報
各ローカル空間索引ファイルに関する次の情報: 索引付きデータへのパス、ローカル索引へのパス、および索引付きデータのMBR
SpatialIndexingクラスを使用して空間索引を作成する場合、次のメタデータ・プロパティを設定できます。
indexName: 空間索引の名前。設定されていない場合、出力フォルダ名が使用されます。
metadataDir: メタデータ・ファイルの格納先のディレクトリへのパス。 デフォルトでは、ユーザー・ディレクトリへの相対パスであるoracle_spatial/index_metadataに格納されます。ユーザーがhdfsである場合は、/user/hdfs/oracle_spatial/index_metadataになります。
overwriteMetadata: trueに設定すると、現在のmetadataDir内で同じindexNameを持つ空間索引に対して空間索引メタデータ・ファイルがすでに存在する場合、この空間索引メタデータが上書きされます。falseに設定し、現在のmetadataDir内で同じindexNameを持つ空間索引に対して空間索引メタデータ・ファイルがすでに存在する場合、エラーが発生します。
次の例では、メタデータ・ディレクトリおよび空間索引名を設定し、索引がすでに存在する場合は既存の任意のメタデータを上書きするよう指定します。
spatialIndexing.setMetadataDir("/user/hdfs/myIndexMetadataDir");
spatialIndexing.setIndexName("testIndex");
spatialIndexing.setOverwriteMetadata(true);
indexNameのみを指定するとともに、必要に応じて索引メタデータがあるindexMetadataDirを指定することにより、既存の空間索引を他のジョブに渡すことができます。索引名が提供されている場合、空間索引パスや入力形式を指定する必要はありません。
次のジョブ・ドライバは、indexNameをパラメータとして受け取ります。
oracle.spatial.hadoop.vector.mapred.job.Categorization
oracle.spatial.hadoop.vector.mapred.job.SpatialFilter
oracle.spatial.hadoop.vector.mapred.job.Binning
oracle.spatial.hadoop.vector.InputDataSetを受け取るドライバ(SpatialJoinやPartitioningなど)
索引名がindexMetadataDirパスで見つからない場合、空間索引が見つからなかったことを示すエラーがスローされます。
次の例は、ビニング・ジョブの入力データ・セットとして設定されている空間索引を示します。
Binning binning = new Binning();
binning.setIndexName("indexExample");
binning.setIndexMetadataDir("indexMetadataDir");
InputFormatは次のサポート対象の要件と一致している必要があります。
FileInputFormatのサブクラスであること。
getSplits()メソッドがFileSplitまたはCombineFileSplit分割タイプを返すこと。
古いHadoop APIの場合、RecordReaderのgetPos()メソッドが現在の位置を返し、空間索引のレコードをユーザー・ファイルの元のレコードにトラック・バックすること。現在の位置が返されない場合、空間索引では元のレコードが見つかりません。
ただし、空間索引は引き続き作成でき、元のレコードの読取りを必要としない操作に使用できます。たとえば、他のフィールドを追加フィールドとして追加すると、元のレコード全体を読み取る必要はありません。
注意:
それぞれの分割がgetSplits()メソッドから返されたら、その分割に対して空間索引が作成されます。空間索引をフィルタ処理に使用する(空間のフィルタ処理)場合は、空間索引を作成したものと同じInputFormat実装を使用して、分割索引があるかどうか確認することをお薦めします。
getPos()メソッドはHadoopの新しいAPIから削除されていますが、org.apache.hadoop.mapreduce.lib.input.TextInputFormatおよびCombineTextInputFormatはサポートされており、引き続きレコードの開始オフセットの取得に使用できます。
新しいAPIのその他の入力形式もサポートされていますが、レコード開始オフセットは空間索引に含まれません。このため、元のレコードは検索できません。新しいAPI入力形式の要件は、古いAPIのものと同じです。ただし、新しいAPI FileInputFormat、FileSplit、およびCombineFileSplitに変換する必要があります。
Vector APIには、GeoJSONおよびShapefileファイル形式のためのInputFormat実装、およびRecordInfoProvider実装が提供されています。
次のInputFormat/RecordInfoProviderペアは、それぞれGeoJSONおよびShapeFilesの読取りと解釈に使用されます。
oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat / oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider oracle.spatial.hadoop.vector.shapefile.mapred.ShapeFileInputFormat / oracle.spatial.hadoop.vector.shapefile.ShapeFileRecordInfoProvider
使用方法とプロパティについて詳しくは、Javadocを参照してください。
次を実行することにより、前に生成した空間索引を削除できます。
oracle.spatial.hadoop.vector.util.Tools removeSpatialIndex indexName=<INDEX_NAME> [indexMetadataDir=<PATH>] [removeIndexFiles=<true|false*>]
説明:
indexName: 前に生成した索引の名前。
indexMetadataDir (オプション): 索引メタデータ・ディレクトリへのパス。指定されていない場合、ユーザー・ディレクトリに対する相対パスとしてoracle_spatial/index_metadataが使用されます
removeIndexFiles (オプション): 索引メタデータファイルに加えて生成された索引地図ファイルを削除する必要がある場合はtrueです。デフォルトでは、falseです。
MVSuggestは、ジオメトリがなく、テキスト・フィールドのあるレコードの推定の位置を取得するための空間の索引付けに使用できます。このテキスト・フィールドはレコードの位置の特定に使用されます。MVSuggestから返されたジオメトリが、空間索引内のレコードの包括に使用されます。
すべてのレコードについて検索テキストを含むフィールドを把握する必要があるため、RecordInfoProvider実装では、LocalizableRecordInfoProviderも実装する必要があります。または、検索テキストを含むフィールドの名前で、構成パラメータoracle.spatial.recordInfo.locationFieldを設定できます。詳細は、LocalizableRecordInfoProviderのJavadocを参照してください。
MVSuggestのスタンドアロン・バージョンがVector APIに用意されているため、入力パラメータとしてMVSConfigを受け入れる一部のジョブに使用できます。
次のジョブ・ドライバはMVSuggestで使用でき、そのすべてにMVSConfigのインスタンスを受け入れるsetMVSConfig()メソッドがあります。
oracle.spatial.hadoop.vector.mapred.job.SpatialIndexing: ジオメトリを含まないレコードの推定の空間位置を取得するためのMVSuggestオプションがあります。
oracle.spatial.hadoop.vector.mapred.job.Categorization: MVSuggestを使用して、USAの州のレイヤーのカリフォルニアの機能など、レイヤー内の特定の機能にレコードを割り当てます。
oracle.spatial.hadoop.vector.mapred.job.SuggestService: 入力レコードごとの検索テキストとその一致を含むファイルを生成する単一のジョブです。
MVSuggestの構成は、MVSConfigまたはLocalMVSConfigクラスを使用してジョブに渡されます。基本のMVSuggestプロパティは次のとおりです。
serviceLocation: MVSuggestを使用するために必要な最小のプロパティです。これにはパスまたはURLが含まれており、MVSuggestディレクトリのある場所、URLの場合はMVSuggestサービスがデプロイされている場所を示します。
serviceInterfaceType: 使用するMVSuggest実装のタイプ。スタンドアロン・バージョンの場合はLOCAL (デフォルト)、Webサービス・バージョンの場合はWEBです。
matchLayers: 検索の実行に使用するレイヤー名の配列。
MVSuggestのスタンドアロン・バージョンを使用する場合は、MVSuggestディレクトリまたはリポジトリをserviceLocationとして指定する必要があります。MVSuggestディレクトリは次のような構造である必要があります。
mvsuggest_config.json repository folder one or more layer template files in .json format optionally, a _config_ directory optionally, a _geonames_ directory
examplesフォルダには多数のレイヤー・テンプレート・ファイルがあり、_config_ディレクトリには各テンプレートの構成があります。
リポジトリ・フォルダ(テンプレートを含むもの)をMVSuggestディレクトリ全体ではなく、mvsLocationとして設定できます。この場合、次の例に示すように、クラスLocalMVSConfigをMVSConfigのかわりに使用して、repositoryLocationプロパティをtrueに設定できます。
LocalMVSConfig lmvsConf = new LocalMVSConfig(); lmvsConf.setServiceLocation(“file:///home/user/mvs_dir/repository/”); lmvsConf.setRepositoryLocation(true); lmvsConf.setPersistentServiceLocation(“/user/hdfs/hdfs_mvs_dir”); spatialIndexingJob.setMvsConfig(lmvsConf);
前の例では、リポジトリ・フォルダをMVSサービスの場所として設定しています。setRepositoryLocationはtrueに設定され、サービスの場所がMVSuggestディレクトリ全体のかわりにリポジトリになることを示します。ジョブを実行すると、指定のリポジトリの場所を使用してMVSuggestディレクトリ全体が作成されます。リポジトリはジョブの完了時に索引付けられ、一時フォルダに置かれます。最初に索引付けしてあったMVSuggestディレクトリは維持されるため、後で使用できます。前の例では、生成されたMVSuggestディレクトリをHDFSパス/user/hdfs/hdfs_mvs_dirに保存します。MVSuggestディレクトリがすでに存在する場合はMVSDirectoryを使用します。
空間索引は生成後、データの空間フィルタ処理に使用できます。データの読取り中、マッパーに達するまではフィルタ処理が実行されます。次のサンプル・コードは、SpatialFilterInputFormatをデータの空間フィルタ処理に使用する方法を示しています。
//set input path and format
FileInputFormat.setInputPaths(conf, new Path("/user/data/"));
conf.setInputFormat(SpatialFilterInputFormat.class);
//set internal input format
SpatialFilterInputFormat.setInternalInputFormatClass(conf, TextInputFormat.class);
if( spatialIndexPath != null )
{
//set the path to the spatial index and put it in the distributed cache
boolean useDistributedCache = true;
SpatialFilterInputFormat.setSpatialIndexPath(conf, spatialIndexPath, useDistributedCache);
}
else
{
//as no spatial index is used a RecordInfoProvider is needed
SpatialFilterInputFormat.setRecordInfoProviderClass(conf, TwitterLogRecordInfoProvider.class);
}
//set spatial operation used to filter the records
SpatialOperationConfig spatialOpConf = new SpatialOperationConfig();
spatialOpConf.setOperation(SpatialOperation.IsInside);
spatialOpConf.setJsonQueryWindow("{\"type\":\"Polygon\", \"coordinates\":[[-106.64595, 25.83997, -106.64595, 36.50061, -93.51001, 36.50061, -93.51001, 25.83997 , -106.64595, 25.83997]]}");
spatialOpConf.setSrid(8307);
spatialOpConf.setTolerance(0.5);
spatialOpConf.setGeodetic(true);
SpatialFilterInputFormatはジョブのInputFormatとして設定する必要があります。実際にデータを読み取るInputFormatは、内部InputFormatとして設定する必要があります。この例では、内部InputFormatはTextInputFormatです。
空間索引が指定されている場合、それがフィルタ処理に使用されます。それ以外の場合は、RecordInfoProviderを指定してレコードのジオメトリを取得する必要があり、フィルタ処理がレコードごとに実行されます。
最終ステップとして、空間フィルタ処理を実行する空間操作と問合せウィンドウが設定されます。空間索引が作成されている場合、または少なくとも実装で分割の生成に同じ基準が使用されている場合は、使用されている同じ内部InputFormat実装を使用することをお薦めします。詳細は、「空間索引の入力形式」を参照してください。
単一の空間フィルタ処理のみ(つまり、問合せウィンドウとやり取りするレコードの取得のみ)を実行する必要がある場合、ビルトインのジョブ・ドライバoracle.spatial.hadoop.vector.mapred.job.SpatialFilterをかわりに使用できます。このジョブ・ドライバは索引付き入力と索引のない入力、およびSpatialOperationConfigを受け入れてフィルタ処理を実行します。
次の手順は、SpatialFilterInputFormatおよび空間索引を使用してレコードをフィルタ処理するときに実行します。
SpatialFilterInputFormat getRecordReader()メソッドは、マッパーが現在の分割にRecordReaderを要求すると呼び出されます。
現在の分割の空間索引が取得されます。
空間索引を使用して、そこに含まれるレコードに空間問合せが実行されます。
その結果、空間フィルタと一致するレコードを含む分割の範囲が判別されます。たとえば、分割がファイル位置1000から2000になる場合、空間フィルタの実行時に空間条件を満たすレコードが1100-1200、1500-1600、および1800-1950の範囲であることが特定されます。そのため、この段階の空間フィルタ処理の実行結果は、さらに小さい分割を含む元のフィルタのサブセットになります。
内部InputFormat RecordReaderは、結果の分割サブセットを細分した分割すべてに要求されます。
RecordReaderが呼出し元のマッパーに返されます。返されるRecordReaderは、内部InputFormatから返された1つ以上のRecordReadersのある実際のラッパーRecordReaderです。
マッパーがRecordReaderを呼び出すたびに、レコードを読み取る次のメソッドへの呼び出しが内部RecordReaderに委任されます。
次の空間フィルタ処理の相互作用の図にこれらの手順を示します。
前に生成した空間索引は、入力形式実装oracle.spatial.hadoop.vector.mapred.input.SpatialIndexInputFormat (またはmapredの代わりにmapreduceパッケージと同等の新しいHadoop API)を使用して読み取ることができます。SpatialIndexInputFormatは、入力パスを受け入れ、ジョブの入力家として設定される点において、他の任意のFileInputFormatサブクラスと同じように使用されます。返されるキーおよび値は、空間索引に格納されているレコードのID (Text)およびレコード情報(RecordInfo)です。
また、空間操作構成を入力形式に指定して空間フィルタ操作を実行することにより、一部の空間的相互作用と一致するレコードのみがマッパーに返されるようにすることもできます。次の例は、特定の領域内にあるすべてのレコードを取得するための空間索引を読み取るジョブを構成する方法を示します。
JobConf conf = new JobConf();
conf.setMapperClass(MyMapper.class);
conf.setInputFormat(SpatialIndexInputFormat.class);
SpatialOperationConfig spatialOpConf = new SpatialOperationConfig();
spatialOpConf.setOperation(SpatialOperation.IsInside);
spatialOpConf.setQueryWindow(JGeometry.createLinearPolygon(new double[]{47.70, -124.28, 47.70, -95.12, 35.45, -95.12, 35.45, -124.28, 47.70, -124.28}, 2, 8307));
SpatialIndexInputFormat.setFilterSpatialOperationConfig(spatialOpConf, conf);
前の例のマッパーでは、次の例に示すように、RecordInfoの追加フィールドを使用することにより、空間以外のフィルタを追加できます。
public class MyMapper extends MapReduceBase implements Mapper<Text, RecordInfo, Text, RecordInfo>{
@Override
public void map(Text key, RecordInfo value, OutputCollector<Text, RecordInfo> output, Reporter reporter)
throws IOException {
if( Integer.valueOf(value.getField("followers_count")) > 0){
output.collect(key, value);
}
}
}
Vector Analysis APIでは、データを階層エンティティに分類する方法があります。たとえば、大陸部、国、および州などの行政区分のレベルが定義されている一連の特定のカタログの場合、ユーザー・データのレコードを階層データ・セットの各レベルに結合できます。次の例では、大陸部、国および州ごとのユーザー・レコードの数が含まれる各階層レベルの集計カウントを生成します。
Categorization catJob = new Categorization();
//set a spatial index as the input
catJob.setIndexName("indexExample");
//set the job's output
catJob.setOutput("hierarchy_count");
//set HierarchyInfo implementation which describes the world administrative boundaries hierarchy
catJob.setHierarchyInfoClass( WorldDynaAdminHierarchyInfo.class );
//specify the paths of the hierarchy data
Path[] hierarchyDataPaths = {
new Path("file:///home/user/catalogs/world_continents.json"),
new Path("file:///home/user/catalogs/world_countries.json"),
new Path("file:///home/user/catalogs/world_states_provinces.json")};
catJob.setHierarchyDataPaths(hierarchyDataPaths);
//set the path where the index for the previous hierarchy data will be generated
catJob.setHierarchyIndexPath(new Path("/user/hierarchy_data_index/"));
//setup the spatial operation which will be used to join records from the two datasets (spatial index and hierarchy data).
SpatialOperationConfig spatialOpConf = new SpatialOperationConfig();
spatialOpConf.setOperation(SpatialOperation.IsInside);
spatialOpConf.setSrid(8307);
spatialOpConf.setTolerance(0.5);
spatialOpConf.setGeodetic(true);
catJob.setSpatialOperationConfig(spatialOpConf);
//add the previous setup to the job configuration
catJob.configure(conf);
//run the job
RunningJob rj = JobClient.runJob(conf);
前の例では、Categorizationジョブ・ドライバを使用します。構成は次のカテゴリに分けられます。
入力データ: 前に生成した(ジョブ入力として受け取った)空間索引。
出力データ: 階層レベルごとのサマリー数を含むフォルダ。
階層データ構成: これには次のものが含まれます。
HierarchyInfoクラス: 現在の階層データを記述するHierarchyInfoクラスの実装です。ここでは階層レベルの数、レベル名、および各レベルに含まれるデータを示します。
階層データ・パス: 各階層カタログへのパスです。これらのカタログはHierarchyInfoクラスによって読み取られます。
階層索引パス: 階層データ索引が格納されるパスです。階層データは、階層レベル間の親子関係を判別するために事前処理する必要があります。この情報は1回処理され、階層索引に保存されるため、後で現在のジョブまたは他のジョブに使用できます。
空間操作の構成: ユーザー・データと階層データの間で、両方のデータセットを結合するために実行する必要のある空間操作です。ここで設定するパラメータは、空間操作タイプ(IsInside)、SRID (8307)、許容差(0.5メートル)、およびジオメトリが測地(true)であるかどうかです。
Categorization.configure()メソッドは、内部でマッパーとリデューサをそれぞれSpatialHierarchicalCountMapperとSpatialHierarchicalCountReducerに設定します。SpatialHierarchicalCountMapperの出力キーは、hierarchy_level + hierarchy_entry_idという形式の階層エントリ識別子です。マッパー出力値は出力キーごとに1件です。リデューサは各キーの件数をすべて合計します。
注意:
階層データ全体がメモリーに読み込まれるため、すべてのカタログの合計サイズはユーザー・データよりも大幅に小さくなると予想されます。階層データ・サイズは数GBを超えないようにします。
たとえば、階層エントリに応じたユーザー・レコードのリストなど、件数ではなく別の出力タイプが必要な場合があります。その場合は、SpatialHierarchicalJoinMapperを使用できます。SpatialHierarchicalJoinMapper出力値はRecordInfoインスタンスであり、ユーザー定義リデューサでまとめられ、別の出力を作成します。次のユーザー定義リデューサでは、MultipleOutputsクラスを使用して各階層レベルにMapFileを生成します。各MapFileには、キーとしての階層エントリID、および値として各階層エントリの一致レコードを含むArrayWritableインスタンスがあります。階層エントリごとのレコード・リストを返すユーザー定義リデューサを次に示します。
public class HierarchyJoinReducer extends MapReduceBase implements Reducer<Text, RecordInfo, Text, ArrayWritable> {
private MultipleOutputs mos = null;
private Text outKey = new Text();
private ArrayWritable outValue = new ArrayWritable( RecordInfo.class );
@Override
public void configure(JobConf conf)
{
super.configure(conf);
//use MultipleOutputs to generate different outputs for each hierarchy level
mos = new MultipleOutputs(conf);
}
@Override
public void reduce(Text key, Iterator<RecordInfo> values,
OutputCollector<Text, RecordInfoArrayWritable> output, Reporter reporter)
throws IOException
{
//Get the hierarchy level name and the hierarchy entry id from the key
String[] keyComponents = HierarchyHelper.getMapRedOutputKeyComponents(key.toString());
String hierarchyLevelName = keyComponents[0];
String entryId = keyComponents[1];
List<Writable> records = new LinkedList<Writable>();
//load the values to memory to fill output ArrayWritable
while(values.hasNext())
{
RecordInfo recordInfo = new RecordInfo( values.next() );
records.add( recordInfo );
}
if(!records.isEmpty())
{
//set the hierarchy entry id as key
outKey.set(entryId);
//list of records matching the hierarchy entry id
outValue.set( records.toArray(new Writable[]{} ) );
//get the named output for the given hierarchy level
hierarchyLevelName = FileUtils.toValidMONamedOutput(hierarchyLevelName);
OutputCollector<Text, ArrayWritable> mout = mos.getCollector(hierarchyLevelName, reporter);
//Emit key and value
mout.collect(outKey, outValue);
}
}
@Override
public void close() throws IOException
{
mos.close();
}
}
次の構成では、1つのジョブで同じリデューサが使用され、階層レベルに応じたレコードのリストが生成されます。
JobConf conf = new JobConf(getConf());
//input path
FileInputFormat.setInputPaths(conf, new Path("/user/data_spatial_index/") );
//output path
FileOutputFormat.setOutputPath(conf, new Path("/user/records_per_hier_level/") );
//input format used to read the spatial index
conf.setInputFormat( SequenceFileInputFormat.class);
//output format: the real output format will be configured for each multiple output later
conf.setOutputFormat(NullOutputFormat.class);
//mapper
conf.setMapperClass( SpatialHierarchicalJoinMapper.class );
conf.setMapOutputKeyClass(Text.class);
conf.setMapOutputValueClass(RecordInfo.class);
//reducer
conf.setReducerClass( HierarchyJoinReducer.class );
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(ArrayWritable.class);
////////////////////////////////////////////////////////////////////
//hierarchy data setup
//set HierarchyInfo class implementation
conf.setClass(ConfigParams.HIERARCHY_INFO_CLASS, WorldAdminHierarchyInfo.class, HierarchyInfo.class);
//paths to hierarchical catalogs
Path[] hierarchyDataPaths = {
new Path("file:///home/user/catalogs/world_continents.json"),
new Path("file:///home/user/catalogs/world_countries.json"),
new Path("file:///home/user/catalogs/world_states_provinces.json")};
//path to hierarchy index
Path hierarchyDataIndexPath = new Path("/user/hierarchy_data_index/");
//instantiate the HierarchyInfo class to index the data if needed.
HierarchyInfo hierarchyInfo = new WorldAdminHierarchyInfo();
hierarchyInfo.initialize(conf);
//Create the hierarchy index if needed. If it already exists, it will only load the hierarchy index to the distributed cache
HierarchyHelper.setupHierarchyDataIndex(hierarchyDataPaths, hierarchyDataIndexPath, hierarchyInfo, conf);
///////////////////////////////////////////////////////////////////
//setup the multiple named outputs:
int levels = hierarchyInfo.getNumberOfLevels();
for(int i=1; i<=levels; i++)
{
String levelName = hierarchyInfo.getLevelName(i);
//the hierarchy level name is used as the named output
String namedOutput = FileUtils.toValidMONamedOutput(levelName);
MultipleOutputs.addNamedOutput(conf, namedOutput, MapFileOutputFormat.class, Text.class, ArrayWritable.class);
}
//finally, setup the spatial operation
SpatialOperationConfig spatialOpConf = new SpatialOperationConfig();
spatialOpConf.setOperation(SpatialOperation.IsInside);
spatialOpConf.setSrid(8307);
spatialOpConf.setTolerance(0.5);
spatialOpConf.setGeodetic(true);
spatialOpConf.store(conf);
//run job
JobClient.runJob(conf);
出力値がRecordInfoインスタンスの配列ではなく、レコードIDの配列であるとすると、前に定義したリデューサで一部を変更するだけで済みます。
前の例でoutValueが宣言されている行は、次のように変更されます。
private ArrayWritable outValue = new ArrayWritable(Text.class);
前の例で入力値を取得するloopは、次のように変更されます。このため、レコード全体ではなくレコードIDを取得します。
while(values.hasNext())
{
records.add( new Text(values.next().getId()) );
}
レコードIDのみが必要なとき、マッパーがRecordInfoインスタンス全体を発行します。このため、これを改善するには、マッパーの出力値を変更します。マッパー出力値はAbstractSpatialJoinMapperを拡張して変更できます。次の例では、レコードが階層エントリの一部と一致するたびに、マッパーはRecorInfoインスタンス全体ではなく、レコードIDのみを発行します。
public class IdSpatialHierarchicalMapper extends AbstractSpatialHierarchicalMapper< Text >
{
Text outValue = new Text();
@Override
protected Text getOutValue(RecordInfo matchingRecordInfo)
{
//the out value is the record's id
outValue.set(matchingRecordInfo.getId());
return outValue;
}
}
デフォルトでは、階層検索を実行すると、HierarchyInfo実装に定義されている階層レベルがすべてロードされます。ロードされる階層レベルの範囲は、レベル1 (親レベル)からHierarchyInfo.getNumberOfLevels()メソッドが返すレベルまでに及びます。次の例では、レベル2と3のみをロードするジョブを設定する方法を示します。
conf.setInt( ConfigParams.HIERARCHY_LOAD_MIN_LEVEL, 2); conf.setInt( ConfigParams.HIERARCHY_LOAD_MAX_LEVEL, 3);
注意:
これらのパラメータは、階層レベルのサブセットのみが必要であり、HierarchyInfoの実装を変更しない場合に役立ちます。
検索は常に、(レベル番号が大きい)最下層の階層レベルで実行されます。ユーザー・レコードがこのレベルの階層エントリの一部と一致する場合、その一致は上位レベルの親エントリに伝播されます。たとえば、ユーザー・レコードがロサンゼルスと一致する場合、カリフォルニア、USA、および北米にも一致します。最下位レベルのユーザー・レコードと一致するものがない場合、上位レベルへの検索は続行されません。
この動作は構成パラメータConfigParams.HIERARCHY_SEARCH_MULTIPLE_LEVELSをtrueに設定して変更できます。このため、最下位の下層レベルの検索で、一致しないユーザー・レコードが見つかった場合、最上位レベルに達するまで、あるいは結合するユーザー・レコードがなくなるまで、上位レベルへの検索が続行されます。この動作は、親レベルのジオメトリがその子エントリのジオメトリを完全に囲んでいない場合に使用できます
データを分類するには、空間索引ではなくMVSuggestを使用できます。その場合、LocalizableRecordInfoProviderの実装を特定し、MVSuggestを送信して検索を実行する必要があります。LocalizableRecordInfoProviderに関する情報を参照してください。
次の例では、プログラム・オプションが空間からMVSに変更されています。入力は空間索引ではなくユーザー・データへのパスです。ユーザー・レコードの読取りに使用するInputFormatとLocalizableRecordInfoProviderの実装が指定されます。MVSuggestサービス構成が設定されます。この場合、空間操作の構成は必要ありません。
Categorization<LongWritable, Text> hierCount = new Categorization<LongWritable, Text>();
// the input path is the user's data
hierCount.setInput("/user/data/");
// set the job's output
hierCount.setOutput("/user/mvs_hierarchy_count");
// set HierarchyInfo implementation which describes the world
// administrative boundaries hierarchy
hierCount.setHierarchyInfoClass(WorldDynaAdminHierarchyInfo.class);
// specify the paths of the hierarchy data
Path[] hierarchyDataPaths = { new Path("file:///home/user/catalogs/world_continents.json"),
new Path("file:///home/user/catalogs/world_countries.json"),
new Path("file:///home/user/catalogs/world_states_provinces.json") };
hierCount.setHierarchyDataPaths(hierarchyDataPaths);
// set the path where the index for the previous hierarchy data will be
// generated
hierCount.setHierarchyIndexPath(new Path("/user/hierarchy_data_index/"));
// No spatial operation configuration is needed, Instead, specify the
// InputFormat used to read the user's data and the
// LocalizableRecordInfoProvider class.
hierCount.setInputFormatClass(TextInputFormat.class);
hierCount.setRecordInfoProviderClass(MyLocalizableRecordInfoProvider.class);
// finally, set the MVSuggest configuration
LocalMVSConfig lmvsConf = new LocalMVSConfig();
lmvsConf.setServiceLocation("file:///home/user/mvs_dir/oraclemaps_pub");
lmvsConf.setRepositoryLocation(true);
hierCount.setMvsConfig(lmvsConf);
// add the previous setup to the job configuration
hierCount.configure(conf);
// run the job
JobClient.runJob(conf);
注意:
MVSuggestを使用する場合、階層データ・ファイルはMVSuggestで使用するレイヤー・テンプレート・ファイルと同じである必要があります。HierarchyInfo.getLevelNames()メソッドによって返される階層レベル名が、MVSuggestで一致するレイヤーとして使用されます。
APIには、各レコードのジオメトリを囲んでバッファを生成するマッパーがあります。次のサンプル・コードでは、BufferMapperクラスを使用して各レコード・ジオメトリのバッファ生成ジョブを実行する方法を示します。
//configure input
conf.setInputFormat(FileSplitInputFormat.class);
FileSplitInputFormat.setInputPaths(conf, "/user/waterlines/");
FileSplitInputFormat.setRecordInfoProviderClass(conf, GeoJsonRecordInfoProvider.class);
//configure output
conf.setOutputFormat(SequenceFileOutputFormat.class);
SequenceFileOutputFormat.setOutputPath(conf, new Path("/user/data_buffer/"));
//set the BufferMapper as the job mapper
conf.setMapperClass(BufferMapper.class);
conf.setMapOutputKeyClass(Text.class);
conf.setMapOutputValueClass(RecordInfo.class);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(RecordInfo.class);
//set the width of the buffers to be generated
conf.setDouble(ConfigParams.BUFFER_WIDTH, 0.2);
//run the job
JobClient.runJob(conf);
BufferMapperは、ジオメトリを含むそれぞれの入力レコードのバッファを生成します。出力キーおよび値は、レコードIDおよび生成したバッファを含むRecordInfoインスタンスです。結果ファイルはマッパー出力キーおよび値を含むHadoop MapFileです。必要であれば、マッパーの出力キーと値、および別のタイプの出力キーと値をとるリデューサを実装すると、出力形式を変更できます。
BufferMapperは次のパラメータを受け入れます。
| パラメータ | ConfigParam定数 | 型 | 説明 |
|---|---|---|---|
oracle.spatial.buffer.width |
BUFFER_WIDTH |
double |
バッファの幅 |
oracle.spatial.buffer.sma |
BUFFER_SMA |
double |
入力の座標系で使用される基準の長半径 |
oracle.spatial.buffer.iFlat |
BUFFER_IFLAT |
double |
フラット化データ |
oracle.spatial.buffer.arcT |
BUFFER_ARCT |
double |
測地高密度化に使用する円弧許容差 |
ベクトルAPIには、空間データ・セットに空間ビニングを実行するクラスoracle.spatial.hadoop.vector.mapred.job.Binningがあります。Binningクラスは(空間索引付けした、または索引付けしない)入力データ・セットをとるMapReduceジョブ・ドライバであり、各レコードをビンに割り当て、(1つ以上のレコードおよび任意の集計値を含む)すべてのビンを含めたファイルを生成します。
ビニング・ジョブは次のように構成できます。
ビニングするデータ・セットと、それが読み込まれ、解釈される方法(InputFormatおよびRecordInfoProvider)、を指定するか、既存の空間索引の名前を指定します。
出力パスを設定します。
ビニングする矩形領域であるグリッドMBRを設定します。
ビンRECTANGLEまたはHEXAGONの形状を設定します。
ビン(セル)のサイズを指定します。矩形については、幅と高さをしてします。六角形のセルについては、六角形の幅を指定します。それぞれの六角形は、常にその頂点のいずれかが底として描かれます。
ビンごとに集計する数値フィールド名のリストを渡すこともできます。
結果の出力はテキスト・ファイルであり、そこで各レコードはJSON形式のビン(セル)であり、次の情報が含まれています。
id: ビンのID
geom: ビンのジオメトリ。常に六角形または八角形のポリゴン
count: ビンに含まれるポイント数
aggregated fields: ゼロ以上の集計フィールド
次の例では、ビニング・ジョブを構成し、実行します。
//create job driver
Binning<LongWritable, Text> binJob = new Binning<LongWritable, Text>();
//setup input
binJob.setInput("/user/hdfs/input/part*");
binJob.setInputFormatClass(GeoJsonInputFormat.class);
binJob.setRecordInfoProviderClass(GeoJsonRecordInfoProvider.class);
//set binning output
binJob.setOutput("/user/hdfs/output/binning");
//create a binning configuration to produce rectangular cells
BinningConfig binConf = new BinningConfig();
binConf.setShape(BinShape.RECTANGLE);
//set the bin size
binConf.setCellHeight(0.2);
binConf.setCellWidth(0.2);
//specify the area to be binned
binConf.setGridMbr(new double[]{-50,10,50,40});
binJob.setBinConf(binConf);
//save configuration
binJob.configure(conf);
//run job
JobClient.runJob(conf);
ジョブ・ドライバ・クラスoracle.spatial.hadoop.mapred.KMeansClusteringはデータ・セットの空間クラスタの検索に使用できます。このクラスでは、k-meansアルゴリズムの分散バージョンを使用します。
必須パラメータ:
InputFormatクラスが入力データ・セットの読取りに使用され、RecordInfoProviderがレコードからの空間情報の抽出に使用される、入力データ・セットへのパス。
結果が格納されるパス。
検出されるクラスタの数。
オプションのパラメータ:
アルゴリズムが終了するまでの最大反復数。
クラスタがいつ収束するかを判断するための基準関数。これはoracle.spatial.hadoop.vector.cluster.kmeans.CriterionFunctionの実装として提供されます。Vector APIには、SquaredErrorCriterionFunctionおよびEuclideanDistanceCriterionFunctionという基準関数の実装が含まれています。
各クラスタのジオメトリを生成するためのoracle.spatial.hadoop.vector.cluster.kmeans.ClusterShapeGeneratorの実装。デフォルトの実装はConvexHullClusterShapeGeneratorであり、各クラスタの凸包を生成します。クラスタ・ジオメトリが必要でない場合は、DummyClusterShapeGeneratorクラスを使用できます。
連続するx、yの縦座標としての初期Kクラスタ・ポイント。例: x1,y1,x2,y2,…xk,yk
この結果はclusters.jsonというファイルになり、クラスタを呼び出した機能の配列が含まれます。各クラスタには、次の情報が含まれます。
id: クラスタID
memberCount: クラスタ内の要素の数
geom: クラスタ・ジオメトリ
次の例では、KMeansClusteringアルゴリズムを実行して5クラスタを検出します。デフォルトでSquredErrorCriterionFunctionおよびConvexHullClusterShapeGeneratorが使用されるため、これらのクラスを明示的に設定する必要はありません。また、runIterations()がアルゴリズム実行のために内部的に呼び出されると、反復ごとにMapReduceが1回起動されます。この例では、数値20が許容されている反復の最大数としてrunIterations()に渡されます。
//create the cluster job driver
KMeansClustering<LongWritable, Text> clusterJob = new KMeansClustering<LongWritable, Text>();
//set input properties:
//input dataset path
clusterJob.setInput("/user/hdfs/input/part*");
//InputFormat class
clusterJob.setInputFormatClass(GeoJsonInputFormat.class);
//RecordInfoProvider implementation
clusterJob.setRecordInfoProviderClass(GeoJsonRecordInfoProvider.class);
//specify where the results will be saved
clusterJob.setOutput("/user/hdfs/output/clusters");
//5 cluster will be found
clusterJob.setK(5);
//run the algorithm
success = clusterJob.runIterations(20, conf);
空間の結合機能を使用すると、2つの異なる大きいデータ・セットのレコード間の空間的相互作用を検出できます。
ドライバ・クラスoracle.spatial.hadoop.vector.mapred.job.SpatialJoinを使用して、2つのデータ・セット間の空間結合を実行するためのジョブを実行または構成できます。このジョブ・ドライバは、次の入力を受け入れます。
入力データ・セット: 2つの入力データ・セットが予想されます。各入力データ・セットは、データ・セットからのレコードを解釈するために使用されるパス、空間索引、入力形式およびレコード情報プロバイダなどのデータ・セットを見つける場所および読み取る方法に関する情報が格納されたクラスoracle.spatial.hadoop.vector.InputDataSetを使用して表現されます。これはまた、データ・セットの空間構成も受け入れます。
空間操作構成: 空間操作構成は、2つのレコードが相互に関連しているかどうかを確認するために使用される空間的相互作用を定義します。これはまた、網羅する領域(MBR)も定義します。つまり、MBR内のレコードまたはMBRと交差するレコードのみが検索時に考慮されます。
パーティション化結果ファイル・パス: 両方のデータ・セットについて前に生成されたパーティション化結果を指し示すオプションのパラメータです。操作を分散するには、データをパーティション化する必要があります。このパラメータが指定されていない場合、パーティション化プロセスは入力データ・セット全体に対して実行されます。(詳細は、「空間のパーティション化」を参照してください。)
出力パス: 結果ファイルが書き込まれるパス。
空間の結合結果はテキスト・ファイルであり、その各行は、空間操作構成に定義されている空間的相互作用に応じたレコードのペアです。
次の表は、空間の結合に対して現在サポートされている空間的相互作用を示しています。
| 空間操作 | 追加パラメータ | 型 |
|---|---|---|
AnyInteract |
なし |
(該当なし) |
IsInside |
なし |
(該当なし) |
WithinDistance |
oracle.spatial.hadoop.vector.util.SpatialOperationConfig.PARAM_WD_DISTANCE |
double |
WithinDistance操作の場合、次の例に示すように、SpatialOperationConfigに距離パラメータを指定できます。
spatialOpConf.setOperation(SpatialOperation.WithinDistance); spatialOpConf.addParam(SpatialOperationConfig.PARAM_WD_DISTANCE, 5.0);
次の例では、2つの入力データ・セットに対して空間の結合ジョブを実行します。最初のデータ・セットである郵便番号の境界は、空間索引の名前を提供して指定されています。2番目のデータ・セットであるツイートの場合、ファイルへのパス、入力形式およびレコード情報プロバイダが指定されています。検出対象の空間的相互作用はIsInsideであるため、郵便番号の境界(ポリゴン)内にあるツイート(ポイント)のみが、それが含まれる郵便番号の境界とともに結果に表示されます。
SpatialJoin spatialJoin = new SpatialJoin();
List<InputDataSet> inputDataSets = new ArrayList<InputDataSet>(2);
// set the spatial index of the 3-digit postal boundaries of the USA as the first input data set
InputDataSet pbInputDataSet = new InputDataSet();
pbInputDataSet.setIndexName("usa_pcb3_index");
//no input format or record info provider are required here as a spatial index is provided
inputDataSets.add(pbInputDataSet);
// set the tweets data set in GeoJSON format as the second data set
InputDataSet tweetsDataSet = new InputDataSet();
tweetsDataSet.setPaths(new Path[]{new Path("/user/example/tweets.json")});
tweetsDataSet.setInputFormatClass(GeoJsonInputFormat.class);
tweetsDataSet.setRecordInfoProviderClass(GeoJsonRecordInfoProvider.class);
inputDataSets.add(tweetsDataSet);
//set input data sets
spatialJoin.setInputDataSets(inputDataSets);
//spatial operation configuration
SpatialOperationConfig spatialOpConf = new SpatialOperationConfig();
spatialOpConf.setOperation(SpatialOperation.IsInside);
spatialOpConf.setBoundaries(new double[]{47.70, -124.28, 35.45, -95.12});
spatialOpConf.setSrid(8307);
spatialOpConf.setTolerance(0.5);
spatialOpConf.setGeodetic(true);
spatialJoin.setSpatialOperationConfig(spatialOpConf);
//set output path
spatialJoin.setOutput("/user/example/spatialjoin");
// prepare job
JobConf jobConf = new JobConf(getConf());
//preprocess will partition both data sets as no partitioning result file was specified
spatialJoin.preprocess(jobConf);
spatialJoin.configure(jobConf);
JobClient.runJob(jobConf);
パーティション化機能を使用して、1つ以上のデータ・セットを空間的にパーティション化します。
空間のパーティション化は、複数の矩形への空間の分割で構成されています。この場合、各矩形は、ほぼ同じ数のポイントが含まれるよう意図されます。最終的に、これらのパーティションを使用して、空間の結合などの他のジョブ内のリデューサ間の操作を分散できます。
空間のパーティション化プロセスは、次の入力パラメータを受け入れるoracle.spatial.hadoop.mapred.job.Partitioningドライバ・クラスを使用して実行または構成されます。
入力データ・セット: 1つ以上の入力データ・セットを指定できます。各入力データ・セットは、データ・セットからのレコードを解釈するために使用されるパス、空間索引、入力形式およびレコード情報プロバイダなどのデータ・セットを見つける場所および読み取る方法に関する情報が格納されたクラスoracle.spatial.hadoop.vector.InputDataSetを使用して表現されます。これはまた、データ・セットの空間構成も受け入れます。
サンプリング比率: 1つ以上のデータ・セット全体の一部のみを使用してパーティション化を実行します。サンプリング比率は、入力データ・セットのサイズ全体に対するサンプルのサイズの比率です。指定されていない場合、入力データ・セットのサイズの10パーセント(0.1)が使用されます。
空間構成: SRIDなどの入力データ・セットの空間プロパティを定義します。少なくとも次元境界を指定する必要があります。
出力パス: 結果ファイルが書き込まれるパス。
生成されたパーティション化結果ファイルは、GeoJSON形式であり、生成された各パーティションに関する情報(パーティションのジオメトリおよび(サンプルから)含まれるポイントの数を含む)が格納されています。
次の例では、ツイート・データ・セットをパーティション化します。サンプリング比率は指定されていないため、デフォルトでは0.1が使用されています。
Partitioning partitioning = new Partitioning();
List<InputDataSet> inputDataSets = new ArrayList<InputDataSet>(1);
//define the input data set
InputDataSet dataSet = new InputDataSet();
dataSet.setPaths(new Path[]{new Path("/user/example/tweets.json")});
dataSet.setInputFormatClass(GeoJsonInputFormat.class);
dataSet.setRecordInfoProviderClass(GeoJsonRecordInfoProvider.class);
inputDataSets.add(dataSet);
partitioning.setInputDataSets(inputDataSets);
//spatial configuration
SpatialConfig spatialConf = new SpatialConfig();
spatialConf.setSrid(8307);
spatialConf.setBoundaries(new double[]{-180,-90,180,90});
partitioning.setSpatialConfig(spatialConf);
//set output
partitioning.setOutput("/user/example/tweets_partitions.json");
//run the partitioning process
partitioning.runFullPartitioningProcess(new JobConf());
HDFSからMapReduceジョブによって読み取られたレコードは、LongWritable、Text、ArrayWritableなどのJavaタイプ(通常)の書込み可能サブクラス、または一部のユーザー定義タイプを使用してキー/値ペアとしてメモリーに表示されます。たとえば、TextInputFormatを使用して読み取られたレコードは、メモリー内でLongWritable、Textキー/値ペアとして表示されます。
RecordInfoProviderはこのようなメモリー・レコード表現を解釈し、Vector Analysis APIで必要なデータを返すコンポーネントです。このため、APIは特定の形式やメモリー表現に関連付けられていません。
RecordInfoProviderインタフェースには、次のメソッドがあります。
void setCurrentRecord(K key, V value)
String getId()
JGeometry getGeometry()
boolean getExtraFields(Map<String, String> extraFields)
InputFormatごとに常にRecordInfoProviderインスタンスがあります。メソッドsetCurrentRecord()は、RecordReaderから取得した現在のキー/値ペアを渡して呼び出されます。次に、RecordInfoProviderによって現在のレコードID、ジオメトリ、および追加フィールドを取得します。これらのフィールドのいずれも必須フィールドではありません。ジオメトリのあるレコードのみが空間操作に関与します。IDは、カテゴリ化などの操作で、レコードの区別に使用されます。追加フィールドは、テキストとして表現され、元のレコードを読み取らない簡易アクセスに必要なレコード情報の格納、またはMVSuggestを使用する操作のために使用されます。
通常、RecordInfoProviderから返される情報は、RecordInfoインスタンスの移入に使用されます。RecordInfoはレコードの簡易バージョンとみなされ、RecordInfoProviderから返された情報、およびファイル内で元のレコードを特定する情報が含まれています。
このサンプル実装はJsonRecordInfoProviderと呼ばれ、TextInputFormatを使用して読み取られるJSON形式のテキスト・レコードをとります。レコード・サンプルを次に示します。
{ "_id":"ABCD1234", "location":" 119.31669, -31.21615", "locationText":"Boston, Ma", "date":"03-18-2015", "time":"18:05", "device-type":"cellphone", "device-name":"iPhone"}
JsonRecordInfoProviderがインスタンス化されると、JSON ObjectMapperが作成されます。ObjectMapperは、後でsetCurrentRecord()が呼び出されたときのレコード値の解析に使用されます。レコード・キーは無視されます。レコードID、ジオメトリ、および1つの追加フィールドが_id、locationおよびlocationText JSONプロパティから取得されます。ジオメトリは緯度/経度ペアとして表現され、JGeometry.createPoint()メソッドによる点ジオメトリの作成に使用されます。追加フィールド(locationText)は、出力パラメータとして機能するextraFieldsマップに追加され、追加フィールドが追加されたことを示すtrueを返します。
public class JsonRecordInfoProvider implements RecordInfoProvider<LongWritable, Text> {
private Text value = null;
private ObjectMapper jsonMapper = null;
private JsonNode recordNode = null;
public JsonRecordInfoProvider(){
//json mapper used to parse all the records
jsonMapper = new ObjectMapper();
}
@Override
public void setCurrentRecord(LongWritable key, Text value) throws Exception {
try{
//parse the current value
recordNode = jsonMapper.readTree(value.toString());
}catch(Exception ex){
recordNode = null;
throw ex;
}
}
@Override
public String getId() {
String id = null;
if(recordNode != null ){
id = recordNode.get("_id").getTextValue();
}
return id;
}
@Override
public JGeometry getGeometry() {
JGeometry geom = null;
if(recordNode!= null){
//location is represented as a lat,lon pair
String location = recordNode.get("location").getTextValue();
String[] locTokens = location.split(",");
double lat = Double.parseDouble(locTokens[0]);
double lon = Double.parseDouble(locTokens[1]);
geom = JGeometry.createPoint( new double[]{lon, lat}, 2, 8307);
}
return geom;
}
@Override
public boolean getExtraFields(Map<String, String> extraFields) {
boolean extraFieldsExist = false;
if(recordNode != null) {
extraFields.put("locationText", recordNode.get("locationText").getTextValue() );
extraFieldsExist = true;
}
return extraFieldsExist;
}
}
このインタフェースはRecordInfoProviderを拡張し、MVSuggestが使用されているときに検索テキストとして使用できる追加フィールドの特定に使用されます。
このインタフェースで追加されるメソッドはgetLocationServiceField()のみであり、MVSuggestに送信される追加フィールドの名前を返します。
また、「サンプルRecordInfoProvider実装」に基づく実装を次に示します。この例で返される名前はlocationTextであり、親クラスに含まれている追加フィールドの名前です。
public class LocalizableJsonRecordInfoProvider extends JsonRecordInfoProvider implements LocalizableRecordInfoProvider<LongWritable, Text> {
@Override
public String getLocationServiceField() {
return "locationText";
}
}
LocalizableRecordInfoProviderのかわりに、構成プロパティoracle.spatial.recordInfo.locationFieldを検索フィールドの名前で設定すると、その値がMVSuggestに送信されます。例: configuration.set(LocatizableRecordInfoProvider.CONF_RECORD_INFO_LOCATION_FIELD, “locationField”)
HierarchyInfoインタフェースは階層データ・セットの説明に使用されます。このHierarchyInfoの実装では、説明する階層の階層レベルの数、名前、およびエントリを示すものとされます。
ルート階層レベルは常に階層レベル1です。このレベルのエントリに親エントリはなく、このレベルが最上位の階層レベルとみなされます。子階層レベルには、上位のレベル値があります。たとえば、大陸部、国、および州に応じた階層のレベルは、それぞれ1、2、および3になります。大陸部レイヤーのエントリには親はありませんが、国レイヤーの子エントリがあります。下部レベルである州レイヤーのエントリには、子はありません。
HierarchyInfo実装は、Vector Analysis APIですぐに使用できるように用意されています。DynaAdminHierarchyInfo実装は、GeoJSON形式で認識されている階層レイヤーの読取りと説明に使用できます。DynaAdminHierarchyInfoはインスタンス化および構成、あるいはサブクラス化が可能です。これに含まれる階層レイヤーは、次のパラメータをとるaddLevel()メソッドを呼び出して指定します。
階層レベル番号
データを含むGeoJSONファイルのファイル名(拡張子なし)と一致する階層レベル名。たとえば、ファイルworld_continents.jsonの階層レベル名はworld_continentsであり、world_countries.jsonの階層レベル名はworld_countriesのようになります。
「Children join」フィールド: 現在レベルのエントリを、下位レベルの子エントリと結合するためのJSONプロパティです。nullが渡された場合、エントリIDが使用されます。
「Parent join」フィールド: 現在レベルのエントリを、上位レベルの親エントリと結合するためのJSONプロパティです。この値は、結合する上位レベルのない最上位レベルでは使用されません。1より大きい数のその他のレベルで値がnullに設定された場合、IsInside空間操作が実行され、親と子のエントリが結合されます。このシナリオでは、上位レベルのジオメトリには、下位レベルのエントリが含まれることを示しています。
たとえば、1つの階層は、1- world_continents、2 - world_countries、および3 - world_states_provincesのように、指定したレイヤーのレベルを含むとします。各レイヤーのサンプル・エントリは次のようになります。
world_continents:
{"type":"Feature","_id":"NA","geometry": {"type":"MultiPolygon", "coordinates":[ x,y,x,y,x,y] }"properties":{"NAME":"NORTH AMERICA", "CONTINENT_LONG_LABEL":"North America"},"label_box":[-118.07998,32.21006,-86.58515,44.71352]}
world_countries: {"type":"Feature","_id":"iso_CAN","geometry":{"type":"MultiPolygon","coordinates":[x,y,x,y,x,y]},"properties":{"NAME":"CANADA","CONTINENT":"NA","ALT_REGION":"NA","COUNTRY CODE":"CAN"},"label_box":[-124.28092,49.90408,-94.44878,66.89287]}
world_states_provinces:
{"type":"Feature","_id":"6093943","geometry": {"type":"Polygon", "coordinates":[ x,y,x,y,x,y]},"properties":{"COUNTRY":"Canada", "ISO":"CAN", "STATE_NAME":"Ontario"},"label_box":[-91.84903,49.39557,-82.32462,54.98426]}
DynaAdminHierarchyInfoは、次の方法で前述のレイヤーを含む階層を作成するために構成されます。
DynaAdminHierarchyInfo dahi = new DynaAdminHierarchyInfo(); dahi.addLevel(1, "world_continents", null /*_id is used by default to join with child entries*/, null /*not needed as there are not upper hierarchy levels*/); dahi.addLevel(2, "world_countries", "properties.COUNTRY CODE"/*field used to join with child entries*/, "properties.CONTINENT" /*the value "NA" will be used to find Canada's parent which is North America and which _id field value is also "NA" */); dahi.addLevel(3, "world_states_provinces", null /*not needed as not child entries are expected*/, "properties.ISO"/*field used to join with parent entries. For Ontario, it is the same value than the field properties.COUNTRY CODE specified for Canada*/); //save the previous configuration to the job configuration dahi.initialize(conf);
同様の構成を使用して、国、州、郡などの複数のレイヤー、または同様のJSON形式の他のレイヤーから階層を作成できます。
他にも、ジョブ実行ごとの階層の構成を避けるため、次の例に示すように、階層構成をDynaAdminHierarchyInfoサブクラスで囲むこともできます。
public class WorldDynaAdminHierarchyInfo extends DynaAdminHierarchyInfo \
{
public WorldDynaAdminHierarchyInfo()
{
super();
addLevel(1, "world_continents", null, null);
addLevel(2, "world_countries", "properties.COUNTRY CODE", "properties.CONTINENT");
addLevel(3, "world_states_provinces", null, "properties.ISO");
}
}
HierarchyInfoインタフェースには、階層の説明を実装するために次のメソッドが含まれています。メソッドは次の3つのカテゴリに分けられます。
階層を説明するメソッド
データをロードするメソッド
データを供給するメソッド
また、ジョブ構成の初期化を実行、およびジョブ構成へデータを保存、またはジョブ構成から読み取るためのinitialize() メソッドがあります
void initialize(JobConf conf); //methods to describe the hierarchy String getLevelName(int level); int getLevelNumber(String levelName); int getNumberOfLevels(); //methods to load data void load(Path[] hierDataPaths, int fromLevel, JobConf conf) throws Exception; void loadFromIndex(HierarchyDataIndexReader[] readers, int fromLevel, JobConf conf) throws Exception; //methods to supply data Collection<String> getEntriesIds(int level); JGeometry getEntryGeometry(int level, String entryId); String getParentId(int childLevel, String childId);
前述の階層レベルとしての地域レイヤーをとるHierarchyInfo実装のサンプルを次に示します。最初のセクションには、初期化メソッドと階層を記述するメソッドがあります。この場合、初期化メソッドは何もしません。次の例に示すメソッドは、hierarchyLevelNames配列を使用して階層を記述します。インスタンス変数entriesGeomsおよびentriesParentは、それぞれエントリのジオメトリとエントリの親を含むjava.util.Mapの配列です。どちらの場合も、エントリIDはキーとして使用されます。配列索引は0から始まり、階層レベルは1から始まるため、配列索引は、配列索引 + 1 = 階層レベルとして階層レベルに対応します。
public class WorldHierarchyInfo implements HierarchyInfo
{
private String[] hierarchyLevelNames = {"world_continents", "world_countries", "world_states_provinces"};
private Map<String, JGeometry>[] entriesGeoms = new Map[3];
private Map<String, String>[] entriesParents = new Map[3];
@Override
public void initialize(JobConf conf)
{
//do nothing for this implementation
}
@Override
public int getNumberOfLevels()
{
return hierarchyLevelNames.length;
}
@Override
public String getLevelName(int level)
{
String levelName = null;
if(level >=1 && level <= hierarchyLevelNames.length)
{
levelName = hierarchyLevelNames[ level - 1];
}
return levelName;
}
@Override
public int getLevelNumber(String levelName)
{
for(int i=0; i< hierarchyLevelNames.length; i++ )
{
if(hierarchyLevelNames.equals( levelName) ) return i+1;
}
return -1;
}
次の例には、複数の階層レベル・データをロードするメソッドが含まれています。load()メソッドはソース・ファイルworld_continents.json、world_countries.json、およびworld_states_provinces.jsonからデータを読み取ります。簡略化のため、内部的に呼び出されたloadLevel()メソッドは指定されませんが、JSONファイルの解析と読取りが行われます。
loadFromIndex()メソッドは、パラメータとして渡されたHierarchyIndexReaderインスタンスから提供された情報のみを受け取ります。load()メソッドは、階層索引がジョブで作成されない場合にかぎり、1回のみ実行されます。データはロード後に自動的に索引付けられ、階層データがメモリーにロードされるたびにloadFromIndex()メソッドが呼び出されます。
@Override
public void load(Path[] hierDataPaths, int fromLevel, JobConf conf) throws Exception {
int toLevel = fromLevel + hierDataPaths.length - 1;
int levels = getNumberOfLevels();
for(int i=0, level=fromLevel; i<hierDataPaths.length && level<=levels; i++, level++)
{
//load current level from the current path
loadLevel(level, hierDataPaths[i]);
}
}
@Override
public void loadFromIndex(HierarchyDataIndexReader[] readers, int fromLevel, JobConf conf)
throws Exception
{
Text parentId = new Text();
RecordInfoArrayWritable records = new RecordInfoArrayWritable();
int levels = getNumberOfLevels();
//iterate through each reader to load each level's entries
for(int i=0, level=fromLevel; i<readers.length && level<=levels; i++, level++)
{
entriesGeoms[ level - 1 ] = new Hashtable<String, JGeometry>();
entriesParents[ level - 1 ] = new Hashtable<String, String>();
//each entry is a parent record id (key) and a list of entries as RecordInfo (value)
while(readers[i].nextParentRecords(parentId, records))
{
String pId = null;
//entries with no parent will have the parent id UNDEFINED_PARENT_ID. Such is the case of the first level entries
if( ! UNDEFINED_PARENT_ID.equals( parentId.toString() ) )
{
pId = parentId.toString();
}
//add the current level's entries
for(Object obj : records.get())
{
RecordInfo entry = (RecordInfo) obj;
entriesGeoms[ level - 1 ].put(entry.getId(), entry.getGeometry());
if(pId != null)
{
entriesParents[ level -1 ].put(entry.getId(), pId);
}
}//finishin loading current parent entries
}//finish reading single hierarchy level index
}//finish iterating index readers
}
最後に、次に示すコードには、各階層レベルのそれぞれのエントリの情報を提供するメソッドが含まれます。提供される情報は、階層レベルに含まれるすべてのエントリのID、各エントリのジオメトリ、および各エントリの親です。
@Override
public Collection<String> getEntriesIds(int level)
{
Collection<String> ids = null;
if(level >= 1 && level <= getNumberOfLevels() && entriesGeoms[ level - 1 ] != null)
{
//returns the ids of all the entries from the given level
ids = entriesGeoms[ level - 1 ].keySet();
}
return ids;
}
@Override
public JGeometry getEntryGeometry(int level, String entryId)
{
JGeometry geom = null;
if(level >= 1 && level <= getNumberOfLevels() && entriesGeoms[ level - 1 ] != null)
{
//returns the geometry of the entry with the given id and level
geom = entriesGeoms[ level - 1 ].get(entryId);
}
return geom;
}
@Override
public String getParentId(int childLevel, String childId)
{
String parentId = null;
if(childLevel >= 1 && childLevel <= getNumberOfLevels() && entriesGeoms[ childLevel - 1 ] != null)
{
//returns the parent id of the entry with the given id and level
parentId = entriesParents[ childLevel - 1 ].get(childId);
}
return parentId;
}
}//end of class
Spatial Hadoop Vector Analysisには、Spatial Java APIで提供される機能の小さいサブセットのみが含まれており、MapReduceジョブでも使用できます。このセクションでは、空間処理のためにHadoopでJGeometryをどのように使用するかの簡単な例をいくつか示します。次の例では、JGeometryクラスを使用したデータセットと問合せジオメトリの間のIsInsideテストを実行する簡単なマッパーを示します。
この例では、空間操作で使用される問合せジオメトリの座標系、SRID、測地の値および許容差が構成メソッドのジョブ構成から取得されます。ポリゴンの問合せジオメトリは、IsInside操作を迅速に実行するため事前処理されます。
MAPメソッドは空間操作を実行する場所です。それぞれの入力レコード値が問合せジオメトリに対してテストされ、テストが完了するとIDが返されます。
public class IsInsideMapper extends MapReduceBase implements Mapper<LongWritable, Text, NullWritable, Text>
{
private JGeometry queryGeom = null;
private int srid = 0;
private double tolerance = 0.0;
private boolean geodetic = false;
private Text outputValue = new Text();
private double[] locationPoint = new double[2];
@Override
public void configure(JobConf conf)
{
super.configure(conf);
srid = conf.getInt("srid", 8307);
tolerance = conf.getDouble("tolerance", 0.0);
geodetic = conf.getBoolean("geodetic", true);
//The ordinates are represented as a string of comma separated double values
String[] ordsStr = conf.get("ordinates").split(",");
double[] ordinates = new double[ordsStr.length];
for(int i=0; i<ordsStr.length; i++)
{
ordinates[i] = Double.parseDouble(ordsStr[i]);
}
//create the query geometry as two-dimensional polygon and the given srid
queryGeom = JGeometry.createLinearPolygon(ordinates, 2, srid);
//preprocess the query geometry to make the IsInside operation run faster
try
{
queryGeom.preprocess(tolerance, geodetic, EnumSet.of(FastOp.ISINSIDE));
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void map(LongWritable key, Text value,
OutputCollector<NullWritable, Text> output, Reporter reporter)
throws IOException
{
//the input value is a comma separated values text with the following columns: id, x-ordinate, y-ordinate
String[] tokens = value.toString().split(",");
//create a geometry representation of the record's location
locationPoint[0] = Double.parseDouble(tokens[1]);//x ordinate
locationPoint[1] = Double.parseDouble(tokens[2]);//y ordinate
JGeometry location = JGeometry.createPoint(locationPoint, 2, srid);
//perform spatial test
try
{
if( location.isInside(queryGeom, tolerance, geodetic)){
//emit the record's id
outputValue.set( tokens[0] );
output.collect(NullWritable.get(), outputValue);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
同じような方法で、ジオメトリ自体の空間操作も実行できます。たとえば、バッファを作成します。次の例では、同じテキスト値の形式を使用して、各レコードの場所の周辺にバッファを作成します。マッパー出力キーおよび値はレコードIDおよび生成済のバッファであり、JGeometryWritableとして表現されます。JGeometryWritableはVector Analysis APIに含まれる書込み可能な実装であり、JGeometryインスタンスを保持します。
public class BufferMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, JGeometryWritable>
{
private int srid = 0;
private double bufferWidth = 0.0;
private Text outputKey = new Text();
private JGeometryWritable outputValue = new JGeometryWritable();
private double[] locationPoint = new double[2];
@Override
public void configure(JobConf conf)
{
super.configure(conf);
srid = conf.getInt("srid", 8307);
//get the buffer width
bufferWidth = conf.getDouble("bufferWidth", 0.0);
}
@Override
public void map(LongWritable key, Text value,
OutputCollector<Text, JGeometryWritable> output, Reporter reporter)
throws IOException
{
//the input value is a comma separated record with the following columns: id, longitude, latitude
String[] tokens = value.toString().split(",");
//create a geometry representation of the record's location
locationPoint[0] = Double.parseDouble(tokens[1]);
locationPoint[1] = Double.parseDouble(tokens[2]);
JGeometry location = JGeometry.createPoint(locationPoint, 2, srid);
try
{
//create the location's buffer
JGeometry buffer = location.buffer(bufferWidth);
//emit the record's id and the generated buffer
outputKey.set( tokens[0] );
outputValue.setGeometry( buffer );
output.collect(outputKey, outputValue);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
ファイルベースのデータ・ソース(つまり、ローカル・ファイル・システムまたは分散ファイル・システムからのファイルまたはファイル・セット)以外にも、他のタイプのデータ・ソースをVector APIジョブの入力データとして使用できます。
データ・ソースは、Vector API内の入力データ・ソースとして参照されます。すべての入力データ・セットにより、インタフェースoracle.spatial.hadoop.vector.data.AbstractInputDataSetが実装されます。入力データ・セットのプロパティは、メソッドsetInputFormatClass()、setRecordInfoProviderClass()およびsetSpatialConfig()を使用してVectorジョブに対して直接設定できます。入力データ・セットのタイプに応じて、より多くの情報を設定できます。たとえば、setInput()を使用してファイル・データ・ソースを指定したり、setIndexName()を空間索引に使用したりできます。このジョブにより、設定されているプロパティに基づいて入力データ型ソースが決まります。
入力データ・セット情報は、ジョブのメソッドsetInputDataSet()を使用してVector APIジョブに直接設定することもできます。このメソッドを使用すると、入力データ・ソース情報がカプセル化され、より詳細な制御が可能になり、使用されているデータ・ソースのタイプを識別しやすくなります。
Vector APIには、AsbtractInputDataSetの次の実装が用意されています。
SimpleInputDataSet: 入力データ・セット用としてVector APIに必要な最小限の情報が含まれます。通常、Apache Hbase、Oracleデータベースまたは他の任意のファイルベース以外のデータ・ソースなど、ファイルベース以外の入力データ・セットには、このタイプの入力データ・セットを使用する必要があります。
FileInputDataSet: ローカル・ファイル・システムまたは分散ファイル・システムからのファイルベースの入力データ・セットをカプセル化します。これには、入力パスをパス・インスタンスの配列として、またはパス選択用の正規表現として使用可能な文字列として設定するためのプロパティが用意されています。
SpatialIndexInputDataSet: Vector APIによって生成された空間索引を操作するために最適化されたFileInputDataSetのサブクラス。このタイプの入力データ・セットの場合、索引名を指定するだけで十分です。
NoSQLInputDataSet: Oracle NoSQLデータ・ソースを指定します。Vector NoSQL APIと連携して使用する必要があります。NoSQL KVInputFormatまたはTableInputFormatクラスを使用する必要がある場合は、SimpleInputFormatを代わりに使用してください。
MultiInputDataSet: 複数の入力データ・セットをカプセル化する入力データ・セット。
複数の入力データ・セット
Vector APIジョブに用意されているHadoopジョブのほとんど(カテゴリ化を除く)では、クラスoracle.spatial.hadoop.vector.data.MultiInputDataSetを使用することにより、複数の入力データ・セットを管理できます。
1つのジョブに複数の入力データ・セットを追加するには、次の手順を実行します。
AbstractInputDataSetサブクラスの複数のインスタンスを作成および構成します。
oracle.spatial.hadoop.vector.data.MultiInputDataSetのインスタンスを作成します。
ステップ1で作成した入力データ・セットをMultiInputDataSetインスタンスに追加します。
ジョブの入力データ・セットとしてMultiInputDataSetインスタンスを設定します。
次のコード・スニペットは、1つのVector APIに複数の入力データ・セットを設定する方法を示しています。
//file input data set
FileInputDataSet fileDataSet = new FileInputDataSet();
fileDataSet.setInputFormatClass(GeoJsonInputFormat.class);
fileDataSet.setRecordInfoProviderClass(GeoJsonRecordInfoProvider.class);
fileDataSet.setInputString("/user/myUser/geojson/*.json");
//spatial index input data set
SpatialIndexInputDataSet indexDataSet = new SpatialIndexInputDataSet();
indexDataSet.setIndexName("myIndex");
//create multi input data set
MultiInputDataSet multiDataSet = new MultiInputDataSet();
//add the previously defined input data sets
multiDataSet.addInputDataSet(fileDataSet);
multiDataSet.addInputDataSet(indexDataSet);
Binning binningJob = new Binning();
//set multiple input data sets to the job
binningJob.setInputDataSet(multiDataSet);
NoSQL入力データ・セット
Vector APIには、Oracle NoSQL Databaseからデータを読み取るクラスが用意されています。Vector NoSQLコンポーネントを使用すると、複数のキー/値ペアを単一のレコードにグループ化できます。これらのレコードは、HadoopマッパーにRecordInfoインスタンスとして渡されます。また、これらを使用して、NoSQLエントリ(キーおよび値)をHadoopレコード・フィールド(RecordInfoのid、geometryおよび追加フィールド)にマップすることもできます。
NoSQLパラメータは、NoSQLInputDataSetクラスを使用してVectorジョブに渡されます。必要なのは、NoSQLデータ・ソースのKVストア、ホスト、親キーおよび追加情報が含まれるNoSQLConfigurationインスタンスを入力および設定することのみです。デフォルトのクラスが使用されるため、InputFormatおよびRecordInfoProviderクラスを設定する必要はありません。
次の例は、Vector NoSQLクラスを使用して、NoSQLをデータ・ソースとして使用するジョブを構成する方法を示します。
//create NoSQL configuration
NoSQLConfiguration nsqlConf = new NoSQLConfiguration();
// set connection data
nsqlConf.setKvStoreName("mystore");
nsqlConf.setKvStoreHosts(new String[] { "myserver:5000" });
nsqlConf.setParentKey(Key.createKey("tweets"));
// set NoSQL entries to be included in the Hadoop records
// the entries with the following minor keys will be set as the
// RecordInfo's extra fields
nsqlConf.addTargetEntries(new String[] { "friendsCount", "followersCount" });
// add an entry processor to map the spatial entry to a RecordInfo's
// geometry
nsqlConf.addTargetEntry("geometry", NoSQLJGeometryEntryProcessor.class);
//create and set the NoSQL input data set
NoSQLInputDataSet nsqlDataSet = new NoSQLInputDataSet();
//set noSQL configuration
nsqlDataSet.setNoSQLConfig(nsqlConf);
//set spatial configuration
SpatialConfig spatialConf = new SpatialConfig();
spatialConf.setSrid(8307);
nsqlDataSet.setSpatialConfig(spatialConf);
ターゲット・エントリは、Hadoopレコードの一部となるNoSQLエントリを参照しており、NoSQLマイナー・キーによって指定されます。前の例では、マイナー・キーfriendsCountおよびfollowersCountを持つエントリがHadoopレコードの一部となります。これらのNoSQLエントリは、テキスト値として解析され、friendsCountおよびfollowersCountと呼ばれる追加フィールドとしてHadoop RecordInfoに割り当てられます。デフォルトでは、メジャー・キーがレコードIDとして使用されます。マイナー・キーとして“ジオメトリ”が含まれるエントリは、RecordInfoのgeometryフィールドを設定するために使用されます。
前の例では、ジオメトリNoSQLエントリの値タイプはJGeometryであるため、この値を解析するためのクラスを指定し、RecordInfoのgeometryフィールドに割り当てる必要があります。これには、NoSQLEntryProcessorインタフェースの実装を設定する必要があります。この場合、NoSQLJGeometryEntryProcessorクラスが使用され、このクラスが、NoSQLエントリから値を読み取り、この値を現在のRecordInfoのgeometryフィールドに設定します。特定のエントリ形式を解析するためにNoSQLEntryProcessorの独自の実装を用意できます。
デフォルトでは、同じメジャー・キーを共有するNoSQLエントリが同じHadoopレコードにグループ化されます。この動作を変更するには、oracle.spatial.hadoop.nosql.NoSQLGrouperを実装し、NoSQLConfigurationプロパティentryGrouperClassを新しいgrouperクラスを使用して設定します。
NoSQLを入力データ・ソースとして使用するVector APIジョブを実行する場合、Oracle NoSQLライブラリkvstore.jarが必要です。
他のファイルベース以外のデータ・ソース
NoSQL (Oracle NoSQLクラスを使用)およびApache HBaseなど、他のファイルベース以外のデータ・ソースをVector APIとともに使用できます。Vector APIには、データ・ソースのすべてのタイプを管理するための特定のクラスは用意されていませんが、特定のデータ・ソースをジョブ構成と関連付け、Vectorジョブに次の情報を指定できます。
InputFormat: データ・ソースからデータを読み取るために使用されるInputFormat実装。
RecordInfoProvider: 現在のInputFormatから返されたキー/値ペアからid、空間情報および追加フィールドなどの必要な情報を抽出するためのRecordInfoProviderの実装。
空間構成: SRIDや次元境界などの入力データの空間プロパティを説明します。
次の例は、Vectorジョブ内のApache HBaseデータを使用する方法を示します。
//create job
Job job = Job.getInstance(getConf());
job.setJobName(getClass().getName());
job.setJarByClass(getClass());
//Setup hbase parameters
Scan scan = new Scan();
scan.setCaching(500);
scan.setCacheBlocks(false);
scan.addColumn(Bytes.toBytes("location_data"), Bytes.toBytes("geometry"));
scan.addColumn(Bytes.toBytes("other_data"), Bytes.toBytes("followers_count"));
scan.addColumn(Bytes.toBytes("other_data"), Bytes.toBytes("user_id"));
//initialize job configuration with hbase parameters
TableMapReduceUtil.initTableMapperJob(
"tweets_table",
scan,
null,
null,
null,
job);
//create binning job
Binning<ImmutableBytesWritable, Result> binningJob = new Binning<ImmutableBytesWritable, Result>();
//setup the input data set
SimpleInputDataSet inputDataSet = new SimpleInputDataSet();
//use HBase's TableInputFormat
inputDataSet.setInputFormatClass(TableInputFormat.class);
//Set a RecordInfoProvider which can extract information from HBase TableInputFormat's returned key and values
inputDataSet.setRecordInfoProviderClass(HBaseRecordInfoProvider.class);
//set spatial configuration
SpatialConfig spatialConf = new SpatialConfig();
spatialConf.setSrid(8307);
inputDataSet.setSpatialConfig(spatialConf);
binningJob.setInputDataSet(inputDataSet);
//job output
binningJob.setOutput("hbase_example_output");
//binning configuration
BinningConfig binConf = new BinningConfig();
binConf.setGridMbr(new double[]{-180, -90, 180, 90});
binConf.setCellHeight(5);
binConf.setCellWidth(5);
binningJob.setBinConf(binConf);
//configure the job
binningJob.configure(job);
//run
boolean success = job.waitForCompletion(true);
前の例で設定されたRecordInfoProviderクラスは、HBaseRecordInfoProviderと呼ばれるカスタム実装であり、その定義は次のとおりです。
public class HBaseRecordInfoProvider implements RecordInfoProvider<ImmutableBytesWritable, Result>, Configurable{
private Result value = null;
private Configuration conf = null;
private int srid = 0;
@Override
public void setCurrentRecord(ImmutableBytesWritable key, Result value) throws Exception {
this.value = value;
}
@Override
public String getId() {
byte[] idb = value.getValue(Bytes.toBytes("other_data"), Bytes.toBytes("user_id"));
String id = idb != null ? Bytes.toString(idb) : null;
return id;
}
@Override
public JGeometry getGeometry() {
byte[] geomb = value.getValue(Bytes.toBytes("location_data"), Bytes.toBytes("geometry"));
String geomStr = geomb!=null ? Bytes.toString(geomb) : null;
JGeometry geom = null;
if(geomStr != null){
String[] pointsStr = geomStr.split(",");
geom = JGeometry.createPoint(new double[]{Double.valueOf(pointsStr[0]), Double.valueOf(pointsStr[1])}, 2, srid);
}
return geom;
}
@Override
public boolean getExtraFields(Map<String, String> extraFields) {
byte[] fcb = value.getValue(Bytes.toBytes("other_data"), Bytes.toBytes("followers_count"));
if(fcb!=null){
extraFields.put("followers_count", Bytes.toString(fcb));
}
return fcb!=null;
}
@Override
public Configuration getConf() {
return conf;
}
@Override
public void setConf(Configuration conf) {
srid = conf.getInt(ConfigParams.SRID, 0);
}
}
コマンド・ライン・インタフェースまたはWebコンソールを使用してVector APIジョブが起動されるたびに、そのジョブ用のレジストリ・ファイルが作成されます。ジョブ・レジストリ・ファイルには、ジョブに関する次の情報が含まれます。
ジョブ名
ジョブID
ジョブを実行したユーザー
開始時間および終了時間
ジョブの実行に使用されたパラメータ
最初のジョブによって起動されたジョブ(child jobsと呼ばれます)。子ジョブには、親ジョブと同じフィールドが含まれます。
ジョブ・レジストリ・ファイルには、ジョブの実行に使用されるパラメータが保持されています。このパラメータは、同一のジョブがコマンド・ライン・インタフェースを使用して最初に実行されていなかった場合でも、このジョブを実行するためのサポート用として使用できます。
デフォルトでは、ジョブ・レジストリ・ファイルは、ユーザー・フォルダoracle_spatial/job_registry (hdfsユーザー用の/user/hdfs/oracle_spatial/job_registryなど)の相対HDFSパスの下に作成されます。
ジョブ・レジストリ・ファイルは、HDFSコマンドを使用して直接、またはクラスoracle.spatial.hadoop.commons.logging.registry.RegistryManagerの次のユーティリティ・メソッドを使用して削除できます。
public static int removeJobRegistry(long beforeDate, Configuration conf): デフォルトのジョブ・レジストリ・フォルダから指定されたタイム・スタンプの前に作成されたジョブ・レジストリ・ファイルをすべて削除します。
public static int removeJobRegistry(Path jobRegDirPath, long beforeDate, Configuration conf): 指定されたジョブ・レジストリ・フォルダから指定されたタイム・スタンプの前に作成されたジョブ・レジストリ・ファイルをすべて削除します。
この表は、Vector Analysis APIを使用したジョブ作成の実行時間を示します。ジョブは4ノードのクラスタを使用して実行されています。時間はクラスタの特性によって異なります。テスト・データセットには、10億以上のレコードがあり、サイズは1TBを超えています。
表2-4 Vector Analysis APIを使用したジョブ実行のパフォーマンス時間
| ジョブ・タイプ | 経過時間(推定値) |
|---|---|
空間の索引付け |
2時間 |
空間索引による空間のフィルタ処理 |
1時間 |
空間索引を使用しない空間のフィルタ処理 |
3時間 |
空間索引による階層のカウント |
5分 |
空間索引を使用しない階層のカウント |
3時間 |
ジョブにかかる時間は、次の構成パラメータのいずれかを使用して最大分割サイズを増やすと短縮できます。
mapred.max.split.size mapreduce.input.fileinputformat.split.maxsize
この結果、各マッパーでさらに多くの分割が処理され、実行時間が短縮されます。これはSpatialFilterInputFormat (空間索引付け)またはFileSplitInputFormat (空間階層結合、バッファ)を使用して実行します。また、内部InputFormatとしてCombineFileInputFormatの実装を使用しても、同様の結果が得られます。
Oracle Big Data Spatial Vector Analysis for Apache Sparkは、空間の変換およびアクション、空間のパーティショニングおよび索引付けをサポートしている空間対応のRDD (Resilient Distributed Datasets)が用意されたSpatial Vector Analysis API for Java and Scalaです。
これらのコンポーネントでは、Spatial Java APIを利用して空間分析タスクを実行します。サポートされている機能には、次が含まれています。
空間RDD (Resilient Distributed Dataset)は、空間の変換およびアクションを実行できるSpark RDDです。
現在の空間RDD実装は、Java用のクラスoracle.spatial.spark.vector.rdd.SpatialJavaRDDおよびScala用のoracle.spatial.spark.vector.scala.rdd.SpatialRDDです。空間RDD実装は、次の例に示すように、RDDまたはJavaRDDの既存のインスタンスから作成できます。
Java:
//create a regular RDD
JavaRDD<String> rdd = sc.textFile("someFile.txt");
//create a SparkRecordInfoProvider to extract spatial information from the source RDD’s records
SparkRecordInfoProvider<String> recordInfoProvider = new MySparkRecordInfoProvider();
//create a spatial RDD
SpatialJavaRDD<String> spatialRDD = SpatialJavaRDD.fromJavaRDD(rdd, recordInfoProvider, String.class));
Scala:
//create a regular RDD
val rdd: RDD[String] = sc.textFile("someFile.txt")
//create a SparkRecordInfoProvider to extract spatial information from the source RDD’s records
val recordInfoProvider: SparkRecordInfoProvider[String] = new MySparkRecordInfoProvider()
//create a spatial RDD
val spatialRDD: SpatialRDD[String] = SpatialRDD(rdd, recordInfoProvider)
空間RDDでは、各RDD要素から空間情報を抽出するために使用されるインタフェースoracle.spatial.spark.vector.SparkRecordInfoProviderの実装が使用されます。
通常のRDDは、同じ汎用型の空間RDDに変換できます(つまり、ソースRDDに文字列型のレコードが含まれる場合)。空間RDDには文字列レコードも含まれます。
タイプoracle.spatial.spark.vector.SparkRecordInfoのレコードを使用して空間RDDを作成することもできます。SparkRecordInfoは、ソースRDDからのレコードの抽象です。これには、ソース・レコードの空間情報が保持され、ソース・レコードのサブセットのデータが含まれる場合があります。
次の例は、SparkRecordInfoレコードのRDDを作成する方法を示します。
Java:
//create a regular RDD
JavaRDD<String> rdd = sc.textFile("someFile.txt");
//create a SparkRecordInfoProvider to extract spatial information from the source RDD’s records
SparkRecordInfoProvider<String> recordInfoProvider = new MySparkRecordInfoProvider();
//create a spatial RDD
SpatialJavaRDD<SparkRecordInfo> spatialRDD = SpatialJavaRDD.fromJavaRDD(rdd, recordInfoProvider));
Scala:
//create a regular RDD
val rdd: RDD[String] = sc.textFile("someFile.txt")
//create a SparkRecordInfoProvider to extract spatial information from the source RDD’s records
val recordInfoProvider: SparkRecordInfoProvider[String] = new MySparkRecordInfoProvider()
//create a spatial RDD
val spatialRDD: SpatialRDD[SparkRecordInfo] = SpatialRDD.fromRDD(rdd, recordInfoProvider))
SparkRecordInfoレコードの空間RDDには、空間操作に必要なときに毎回、空間情報を各レコードから抽出する必要がないというメリットがあります。
空間RDDに空間的に索引付けすることにより、空間検索を加速できます。空間索引付けについては、「1.4 空間の索引付け」で説明されています。
空間RDDには、「1.2 空間の変換」および「1.3 空間アクション」の各項で説明されている次の空間の変換およびアクションが用意されています。
空間の変換:
filter
flatMap
join (空間索引の作成時に使用可能)
空間アクション:
MBR
nearestNeighbors
空間ペアRDD
JavaクラスSpatialJavaRDDのペア・バージョンが用意されており、クラスoracle.spatial.spark.vector.rdd.SpatialJavaPairRDDとして実装されます。空間ペアRDDは、既存のペアRDDから作成され、単一の空間RDDと同じ空間の変換およびアクションを含みます。空間ペアRDDに使用されるSparkRecordInfoProviderは、タイプscala.Tuple2<K,V>のレコードを受け取る必要があります。この場合、KおよびVは、ペアRDDのキーおよび値のタイプにそれぞれ対応しています。
例2-1 CSVファイルから情報を読み取るためのSparkRecordInfoProvider
次の例は、CSVファイルから情報を読み取るための単純なSparkRecordInfoProviderを実装する方法を示します。
public class CSVRecordInfoProvider implements SparkRecordInfoProvider<String>{
private int srid = 8307;
//receives an RDD record and fills the given recordInfo
public boolean getRecordInfo(String record, SparkRecordInfo recordInfo) {
try {
String[] tokens = record.split(",");
//expected records have the format: id,name,last_name,x,y where x and y are optional
//output recordInfo will contain the fields id, last name and geometry
recordInfo.addField("id", tokens[0]);
recordInfo.addField("last_name", tokens[2]);
if (tokens.length == 5) {
recordInfo.setGeometry(JGeometry.createPoint(tokens[3], tokens[4], 2, srid));
}
} catch (Exception ex) {
//return false when there is an error extracting data from the input value
return false;
}
return true;
}
public void setSrid(int srid) {this.srid = srid;}
public int getSrid() {return srid;}
}
この例では、出力パラメータとして使用されるSparkRecordInfoインスタンスに送信される空間情報とともに、レコードのIDおよび姓フィールドが抽出されます。追加情報の抽出が必要なのは、SparkRecordInfo要素が含まれる空間RDDを作成することが目標である場合のみです。この抽出処理は、元のレコード情報のサブセットを保持するために必要です。それ以外の場合に必要なのは、空間情報を抽出することのみです。
レコードを変換に含めるか検索時に考慮することが必要な場合は常に、SparkRecordInfoProvider.getRecordInfo()への呼出しによってtrueが返される必要があります。SparkRecordInfoProvider.getRecordInfo()によってfalseが返される場合、レコードは無視されます。
次のサブトピックで説明する変換は、別途記述がない限り(たとえば、結合変換は分散空間索引に対してのみ使用可能であるなど)、空間RDD、空間ペアRDDおよび分散空間索引に対して使用可能です。
フィルタ変換は、通常のRDDのfilter()変換の空間バージョンです。ユーザー指定のフィルタ機能に加えて、これには、空間レコードのフィルタに使用される空間操作を記述するために使用されるoracle.spatial.hadoop.vector.util.SpatialOperationConfigのインスタンスが使用されます。SpatialOperationConfigには、参照および空間操作として使用されるジオメトリである問合せウィンドウが含まれます。空間操作は、(RDDレコードのジオメトリ) (空間操作) (問合せウィンドウ)という形式で実行されます。たとえば、(RDD record) IsInside (queryWindow)などです
使用可能な空間操作は、AnyInteract、IsInside、ContainsおよびWithinDistanceです。
次の例は、特定の問合せウィンドウ内にありnull以外のIDを持つレコードのみが含まれるRDDを返します。
Java:
SpatialOperationConfig soc = new SpatialOperationConfig();
soc.setOperation(SpatialOperation.IsInside);
soc.setQueryWindow(JGeometry.createLinearPolygon(new double[] { 2.0, 1.0, 2.0, 3.0, 6.0, 3.0, 6.0, 1.0, 2.0, 1.0 }, 2, srid));
SpatialJavaRDD<SparkRecordInfo> filteredSpatialRDD = spatialRDD.filter(
(record) -> {
return record.getField(“id”) != null;
}, soc);
Scala:
val soc = new SpatialOperationConfig()
soc.setOperation(SpatialOperation.IsInside)
soc.setQueryWindow(JGeometry.createLinearPolygon(Array(2.0, 1.0, 2.0, 3.0, 6.0, 3.0, 6.0, 1.0, 2.0, 1.0 ), 2, srid))
val filteredSpatialRDD: SpatialRDD[SparkRecordInfo] = spatialRDD.filter(
record => { record.getField(“id”) != null }, soc)
FlatMap変換は、通常のRDDのflatMap()変換の空間バージョンです。ユーザー指定の機能以外にも、空間フィルタを実行するためにSpatialOperationConfigが使用されます。これは、空間的にフィルタされた結果がマップ機能に渡されてフラット化される点を除いて、Filter Transformationと同じように機能します。
次の例では、バッファされた特定の問合せウィンドウおよびジオメトリと相互作用する要素のみが含まれるRDDを作成します。
Java:
SpatialOperationConfig soc = new SpatialOperationConfig();
soc.setOperation(SpatialOperation.AnyInteract);
soc.setQueryWindow(JGeometry.createLinearPolygon(new double[] { 2.0, 1.0, 2.0, 3.0, 6.0, 3.0, 6.0, 1.0, 2.0, 1.0 }, 2, srid));
JavaRDD<SparkRecordInfo> mappedRDD = spatialRDD.flatMap(
(record) -> {
JGeometry buffer = record.getGeometry().buffer(2.5);
record.setGeometry(buffer);
return Collections.singletonList(record);
}, soc);
Scala:
val soc = new SpatialOperationConfig()
soc.setOperation(SpatialOperation.AnyInteract)
soc.setQueryWindow(JGeometry.createLinearPolygon(Array( 2.0, 1.0, 2.0, 3.0, 6.0, 3.0, 6.0, 1.0, 2.0, 1.0 ), 2, srid))
val mappedRDD: RDD[SparkRecordInfo] = spatialRDD.flatMap(
record => {
val buffer: JGeometry = record.getGeometry().buffer(2.5)
record.setGeometry(buffer)
record
}, soc)
結合変換では、2つの空間RDDをそれらのレコード間の空間関係に基づいて結合します。この変換を実行するには、2つのRDDの1つを空間的に索引付けする必要があります。(空間RDDの索引付けの詳細は、「空間の索引付け」を参照してください。)
次の例では、何らかの方法で相互作用するデータ・セットの両方のレコードをすべて結合します。
Java:
DistributedSpatialIndex index = DistributedSpatialIndex.createIndex(sparkContext, spatialRDD1, new QuadTreeConfiguration());
SpatialJavaRDD<SparkRecordInfo> spatialRDD2 = SpatialJavaRDD.fromJavaRDD(rdd2, new RegionsRecordInfoProvider(srid));
SatialOperationConfig soc = new SpatialOperationConfig();
soc.setOperation(SpatialOperation.AnyInteract);
JavaRDD<Tuple2<SparkRecordInfo, SparkRecordInfo> joinedRDD = index.join( spatialRDD2,
(recordRDD1, recordRDD2) -> {
return Collections.singletonList( new Tuple2<>(recordRDD1, recordRDD2));
}, soc);
Scala:
val index: DistributedSpatialIndex[SparkRecordInfo] = DistributedSpatialIndex.createIndex(spatialRDD1, new QuadTreeConfiguration())
val spatialRDD2: SpatialRDD[SparkRecordInfo] = SpatialRDD.fromRDD(rdd2, new RegionsRecordInfoProvider(srid))
val soc = new SpatialOperationConfig()
soc.setOperation(SpatialOperation.AnyInteract)
val joinedRDD: RDD[(SparkRecordInfo, SparkRecordInfo)] = index.join( spatialRDD2,
(recordRDD1, recordRDD2) => {(recordRDD1, recordRDD2)}, soc)
フィルタ処理変換または最近傍アクションを実行する場合、デフォルトでは、空間操作は、ユーザー定義のフィルタ処理機能を呼び出す前に実行されます。ただし、この動作は変更できます。空間操作の前にユーザー定義のフィルタ処理機能を実行すると、ユーザー定義のフィルタ処理機能に比べて空間操作のコストの方が大きい場合にパフォーマンスを向上させることができます。
空間操作の前に実行されるユーザー定義の機能を設定するには、フィルタ変換または最近傍アクションのいずれかに渡されるSpatialOperationConfigに次のパラメータを設定します。
SpatialOperationConfig spatialOpConf = new SpatialOperationConfig(SpatialOperation.AnyInteract, qryWindow, 0.05);
//set the spatial operation to be executed after the user-defined filtering function
spatialOpConf.addParam(SpatialOperationConfig.PARAM_SPATIAL_EVAL_STAGE, SpatialOperationConfig.VAL_SPATIAL_EVAL_STAGE_POST);
spatialRDD.filter((r)->{ return r.getFollowersCount()>1000;}, spatialOpConf);
前の例は、空間RDDと分散空間索引の両方に適用されます。
空間操作は、任意の変換を実行する前にSpatialTransformationContextを作成することにより、通常の変換で実行できます。
SpatialTransformationContextインスタンスが変換機能内に格納された後、次の例に示すように、このインスタンスを使用して、レコードのジオメトリを取得し、空間操作を適用できます。ここでは、StringレコードのRDDを、キーと値がソース・レコードのIDおよびバッファ済ジオメトリに対応しているペアRDDに変換しています。
Java:
SpatialJavaRDD<String> spatialRDD = SpatialJavaRDD.fromJavaRDD(rdd, new CSVRecordInfoProvider(srid), String.class);
SpatialTransformationContext stCtx = spatialRDD.createSpatialTransformationContext();
JavaPairRDD<String, JGeometry> bufferedRDD = spatialRDD.mapToPair(
(record) -> {
SparkRecordInfo recordInfo = stCtx.getRecordInfo(record);
String id = (String) recordInfo.getField(“id”)
JGeometry geom. = recordInfo.getGeometry(record);
JGeometry buffer = geom.buffer(0.5);
return new Tuple2(id, buffer);
}, soc);
Scala:
val spatialRDD: SpatialRDD[String]= SpatialRDD.fromRDD(rdd, new CSVRecordInfoProvider(srid))
val stCtx: SpatialTransformationContext[String] = spatialRDD.createSpatialTransformationContext()
val bufferedRDD: RDD[(String, JGeometry)] = spatialRDD.map(
record => {
val recordInfo: SparkRecordInfo = stCtx.getRecordInfo(record)
val id: String = recordInfo.getField(“id”).asInstanceOf[String]
val geom: JGeometry = recordInfo.getGeometry(record)
val buffer: JGeometry = geom.buffer(0.5)
(id, buffer)
}, soc)
空間RDD、空間ペアRDDおよび分散空間索引には、次の空間アクションが用意されています。
MBR: RDDの最小外接矩形(MBR)を計算します。MBRは1回のみ計算され、2回目に呼び出されたときに再計算されないようにキャッシュされます。次の例は、空間RDDからMBRを取得する方法を示します。(この変換は、DistributedSpatialIndexに対しては使用できません。)
Java:
doubl[] mbr = spatialRDD.getMBR();
Scala:
val mbr: Array[Double] = spatialRDD.getMBR()
NearestNeighbors: K最近要素が含まれるリストをRDDまたは分散空間索引から特定のジオメトリに返します。また、ユーザー定義のフィルタ・ラムダ機能を渡すことにより、フィルタを渡すレコードのみをK最近傍リストの一部となる候補にすることができます。次の例は、特定のポイントの最も地階5つのレコードを取得する方法を示します。
Java:
JGeometry qryWindow = JGeometry.createPoint(new double[] { 2.0, 1.0 }, 2, srid));
SpatialOperationConfig soc = new SpatialOperationConfig(SpatialOperation.None, qryWindow, 0.05);
List<SparkRecordInfo> nearestNeighbors = spatialRDD.nearestNeighbors(
(record)->{
return ((Integer)record.getField(“followers_count”))>1000;
}, 5, soc);
Scala:
val qryWindow: JGeometry = JGeometry.createPoint(Array(2.0, 1.0 ), 2, srid))
val soc: SpatialOperationConfig = new SpatialOperationConfig(SpatialOperation.None, qryWindow, 0.05)
val nearestNeighbors: Seq[SparkRecordInfo] = spatialRDD.nearestNeighbors(
record=>{ record.getField(“followers_count”).asInstanceOf[Int]>1000 }, 5, soc);
空間RDDを空間的に索引付けすることにより、空間変換の実行時に空間検索を加速できます。
空間索引によって空間RDDを再パーティション化することにより、各パーティションの特定の領域にのみレコードが含まれるようにすることができます。これにより、空間検索に結果が含まれないパーティションを簡単に破棄できるため、検索が高速になります。
空間索引はJava抽象クラスoracle.spatial.spark.vector.index.DistributedSpatialIndexまたはそのScalaの同等クラスoracle.spatial.spark.vector.scala.index.DistributedSpatialIndexを介して作成されます。これらでは両方とも、実際の空間索引を作成するために特定の実装が使用されます。次の例は、QuadTreeベースの空間索引実装を使用して空間索引を作成する方法を示します。
Java:
DistributedSpatialIndex<String> index = DistributedSpatialIndex.createIndex(sparkContext, spatialRDD1, new QuadTreeConfiguration());
Scala:
val index: DistributedSpatialIndex[String] = DistributedSpatialIndex.createIndex(spatialRDD1, new QuadTreeConfiguration())(sparkContext)
空間索引実装のタイプは、oracle.spatial.spark.vector.index.SpatialPartitioningConfigurationのサブセットである最後のパラメータによって決まります。索引実装によっては、構成パラメータがパーティション化および索引付けのために異なる設定を受け入れる場合があります。現在、空間索引の唯一の実装はクラスoracle.spatial.spark.vector.index.quadtree.QuadTreeDistIndexであり、このクラスは、タイプoracle.spatial.spark.vector.index.quadtree.QuadTreeConfigurationの構成を受け取ります。
DistributedSpatialIndexクラスは現在、「空間の変換」で説明されているfilter、flatMap、joinおよびnearestNeighbors変換をサポートしています。
空間索引は、既存のSparkContextおよび索引の格納先のパスを使用するメソッドDistributedSpatialIndex.save()を使用して永続化できます。このパスは、ローカル・ファイル・システムである場合や分散(HDFS)ファイル・システムである場合があります。同様に、永続化された空間索引は、こちらも既存のSparkContextおよび索引の格納先のパスを使用するメソッドDistributedSpatialIndex.load()を使用して呼び出すことにより、ロードできます。
空間RDDは、クラスoracle.spatial.spark.vector.index.SpatialPartitioningの実装を介してパーティション化できます。SpatialPartitioningクラスは、空間RDDを、キーが空間パーティションを指し示している空間的にパーティション化されたペアRDDに変換する空間のパーティション化アルゴリズムを表します。
SpatialPartitioningアルゴリズムは空間索引によって内部的に使用されるか、具象クラスを作成することによって直接使用することもできます。現在、oracle.spatial.spark.vector.index.quadtree.QuadTreePartitioningと呼ばれるQuadTreeベースの実装があります。次の例は、空間RDDを空間的にパーティション化する方法を示します。
QuadTreePartitioning<T> partitioning = new QuadTreePartitioning<>(sparkContext, spatialRDD, new QuadTreeConfiguration()); SpatialJavaPairRDD<PartitionKey, T> partRDD = partitioning.getPartitionedRDD();
ローカル空間索引は、空間RDDのパーティションごとに作成できます。各パターンのコンテンツをローカルにパーティション化すると、パーティションベースで作業するときに空間の検索効率が上がります。
ローカル索引をパーティションごとに作成するには、分散空間索引の作成時にパラメータuseLocalIndexをtrueに設定します。空間的にパーティション化されたRDDは、ユーティリティ・メソッドoracle.spatial.spark.vector.index.local.LocalIndex.createLocallyIndexedRDD(SpatialJavaPairRDD<PartitionKey, T> rdd)を呼び出すことによって各パーティションがローカルに索引付けされるよう変換することもできます。
Spark Vector APIには、GeoJSONおよびShapefile形式のデータ・セット用のSparkRecordInfoProviderの実装が用意されています。関連形式のデータ・セットは、Hadoop用のVector APIに用意されている既存のInputFormatクラスを使用して読み取ることができます。詳細は、「GeoJSONおよびShapefile形式のサポート」を参照してください。
JSONおよびShapefile形式のSparkRecordInfoProvider実装は、getRecordInfo()の呼出し時にジオメトリ・フィールドに加えてフィールドを含めるよう構成できます。次の例は、国および州フィールドが含まれるSparkRecordInfoインスタンスが返されるようShapeFileRecordInfoProviderを構成します。
//create an RDD from an existing shape file
JavaPairRDD<LongWritable, MapWritable> shapeFileRDD = sparkContext.hadoopRDD(jobConf, ShapeFileInputFormat.class, LongWritable.class, MapWritable.class);
//list of fields to be included in the SparkRecordInfo filled by the SparkRecordInfoProvider implementation
List<String> attributes = new ArrayList<String>();
attributes.add("country");
attributes.add("province");
//create a ShapeFileRecordInfoProvider
ShapeFileRecordInfoProvider recordInfoProvider = new ShapeFileRecordInfoProvider(attributes, 8307);
//create a spatial RDD
SpatialJavaRDD<SparkRecordInfo> spatialRDD = SpatialJavaRDD.fromJavaRDD(shapeFileRDD.values(), recordInfoProvider);
空間Spark SQL APIは、任意の形式の空間情報が含まれるSpark SQL DataFrameオブジェクトをサポートします。
Oracle Big Data Spatial Vector Hive Analysis (Oracle Big Data Spatial Vector Hive Analysis)は、Spark SQLとともに使用できます。
例2-2 ツイートを問い合せるための空間DataFrameの作成
次の例では、空間RDDを使用してデータがロードされる場合、関数SpatialJavaRDD.createSpatialDataFrameを使用してDataFrameを作成できます。
//create HiveContext
HiveContext sqlContext = new HiveContext(sparkContext.sc());
//get the spatial DataFrame from the SpatialRDD
//the geometries are in GeoJSON format
DataFrame spatialDataFrame = spatialRDD.createSpatialDataFrame(sqlContext, properties);
// Register the DataFrame as a table.
spatialDataFrame.registerTempTable("tweets");
//register UDFs
sqlContext.sql("create temporary function ST_Polygon as 'oracle.spatial.hadoop.vector.hive.ST_Polygon'");
sqlContext.sql("create temporary function ST_Point as 'oracle.spatial.hadoop.vector.hive.ST_Point'");
sqlContext.sql("create temporary function ST_Contains as 'oracle.spatial.hadoop.vector.hive.function.ST_Contains'");
// SQL can be run over RDDs that have been registered as tables.
StringBuffer query = new StringBuffer();
query.append("SELECT geometry, friends_count, location, followers_count FROM tweets ");
query.append("WHERE ST_Contains( ");
query.append(" ST_Polygon('{\"type\": \"Polygon\",\"coordinates\": [[[-106, 25], [-106, 30], [-104, 30], [-104, 25], [-106, 25]]]}', 8307) ");
query.append(" , ST_Point(geometry, 8307) ");
query.append(" , 0.05)");
query.append(" and followers_count > 50");
DataFrame results = sqlContext.sql(query.toString());
//Filter the tweets in a query window (somewhere in the north of Mexico)
//and with more than 50 followers.
//Note that since the geometries are in GeoJSON format it is possible to create the ST_Point like
//ST_Point(geometry, 8307)
//instead of
//ST_Point(geometry, 'oracle.spatial.hadoop.vector.hive.json.GeoJsonHiveRecordInfoProvider')
List<String> filteredTweets = results.javaRDD().map(new Function<Row, String>() {
public String call(Row row) {
StringBuffer sb = new StringBuffer();
sb.append("Geometry: ");
sb.append(row.getString(0));
sb.append("\nFriends count: ");
sb.append(row.getString(1));
sb.append("\nLocation: ");
sb.append(row.getString(2));
sb.append("\nFollowers count: ");
sb.append(row.getString(3));
return sb.toString();
}
}).collect();
//print the filtered tweets
filteredTweets.forEach(tweet -> System.out.println("Tweet: "+tweet));
Oracle Databaseデータは、Spark Vector Analysis APIを使用して空間RDDのデータ・ソースとして使用できます。
クラスoracle.spatial.spark.vector.util.JDBCUtils (またはScala用のoracle.spatial.spark.vector.scala.util.JDBCUtils)には、Oracleデータベース表またはOracleデータベースに対するSQL問合せから空間RDDを作成するための便利なメソッドが用意されています。表またはSQL問合せには、空間RDDを作成するためにタイプSDO_GEOMETRYの列が1つ含まれる必要があります。
表からのメソッド・バージョンおよび問合せからのメソッド・バージョンでは両方とも、Oracleデータベースへの接続が必要であり、この接続は、テンプレートoracle.spatial.spark.vector.util.ConnectionSupplier (またはScala用のoracle.spatial.spark.vector.scala.util.ConnectionSupler)によって定義されるラムダ機能によって提供されます。
この結果として生成される空間RDDタイプのパラメータは常にSparkRecordInfoになります。つまり、結果として生成されるRDDには、タイプSparkRecordInfoのレコードが含まれ、これには、SQL問合せのSELECTセクション内の表または列を問い合せるときに指定されるフィールドが含まれます。デフォルトでは、取得される列の名前およびタイプはResultSetメタデータを使用して推測されます。ただし、SparkRecordInfoProviderの実装を提供することにより、取得されるフィールドの名前付けおよびタイプを制御できます
次の例は、表とSQL問合せのそれぞれから空間RDDを作成する方法を示します。
例2-3 データベース表からの空間RDDの作成
SpatialJavaRDD<SparkRecordInfoProvider> jdbcSpatialRDD = JDBCUtils.createSpatialRDDFromTable(
sparkContext, //spark context
()->{
Class.forName("oracle.jdbc.driver.OracleDriver");
return new DriverManager.getConnection(connURL, usr, pwd);
}, //DB connection supplier lambda
“VEHICLES”, //DB table
Arrays.asList(new String[]{"ID","DESC","LOCATION"}), //list of fields to retrieve
null //SparkRecordInfoProvider<ResultSet, SparkRecordIngo> (optional)
);
例2-4 データベースに対するSQL問合せからの空間RDDの作成
SpatialJavaRDD<SparkRecordInfoProvider> jdbcSpatialRDD = JDBCUtils.createSpatialRDDFromQuery(
sparkContext, //spark context
()->{
Class.forName("oracle.jdbc.driver.OracleDriver");
return new DriverManager.getConnection(connURL, usr, pwd);
}, //DB connection supplier lambda
“SELECT * FROM VEHICLES WHERE category > 5”, //SQL query
null //SparkRecordInfoProvider<ResultSet, SparkRecordIngo> (optional)
);
前の例では、Oracleデータベースからのデータを問い合せてパーティション化することにより、Spark RDDを作成しています。パーティションの数およびサイズは、Spark Vector Analysis APIによって自動的に決定されます。
この数をパラメータとして使用するメソッド・オーバーロードを呼び出すことにより、Sparkパーティションに含めるデータベース行の目的の数を指定することもできます。パーティションごとの行数を手動で指定すると、空間RDDの作成のパフォーマンスを向上させることができます。
Oracle Big Data Spatial Vector Hive Analysisには、Hiveを使用してデータを分析するために空間関数が用意されています。
空間データは、サポートされている任意のHive形式にすることができます。また、高速処理を目的としてJava分析API (「空間の索引付け」を参照)を使用して作成された空間索引を使用することもできます。
サポートされている機能は次のとおりです。
これらの機能の実装の詳細は、HiveRecordInfoProviderも参照してください。
Hive空間関数には、使用可能な機能に関する参照情報が用意されています。
前提条件ライブラリ
Spatial Vector Hive Analysis APIには、次のライブラリが必要です。
sdohadoop-vector-hive.jar
sdohadoop-vector.jar
sdoutil.jar
sdoapi.jar
ojdbc.jar
Hive表内のレコードには、JSON、WKTまたはユーザー指定形式などの任意の形式のジオメトリ・フィールドが含まれる場合があります。ST_Geometryなどのジオメトリ・コンストラクタにより、ジオメトリのGeoJSON、WKTまたはWKB表現を受け取るジオメトリ作成できます。ジオメトリが別の形式で格納されている場合、HiveRecordInfoProviderを使用できます。
HiveRecordInfoProviderは、ジオメトリ・フィールド表現を解釈し、ジオメトリをGeoJSON形式で返すコンポーネントです。
返されたジオメトリには、次の形式例のように、ジオメトリSRIDが含まれる必要があります。
{"type":<geometry-type", "crs": {"type": "name", "properties": {"name": "EPSG:4326"}}"coordinates":[c1,c2,....cn]}
HiveRecordInfoProviderインタフェースには、次のメソッドがあります。
void setCurrentRecord(Object record)
String getGeometry()
メソッドsetCurrentRecord()は、Hiveでのジオメトリの作成時に提供された現在のジオメトリ・フィールドを渡すことによって呼び出されます。この際、レコードに空間情報がない場合にジオメトリを取得するかnullを返すためにHiveRecordInfoProviderが使用されます。
HiveRecordInfoProviderによって返される情報は、ジオメトリを作成するためにHive空間関数によって使用されます(「Hive空間関数」を参照)。
サンプルHiveRecordInfoProvider実装
SimpleHiveRecordInfoProviderという名前のこのサンプル実装は、JSON形式のテキスト・レコードを使用します。サンプル入力レコードは、次のとおりです。{"longitude":-71.46, "latitude":42.35}
SimpeHiveRecordInfoProviderがインスタンス化されると、JSON ObjectMapperが作成されます。ObjectMapperは、後でsetCurrentRecord()が呼び出されるときのレコード値の解析に使用されます。ジオメトリは緯度/経度ペアとして表現され、JsonUtils.readGeometry()メソッドによる点ジオメトリの作成に使用されます。この場合、返されるGeoJSON形式がGeoJsonGen.asGeometry()を使用して作成され、SRIDがJsonUtils.addSRIDToGeoJSON()を使用してGeoJSONに追加されます。
public class SimpleHiveRecordInfoProvider implements HiveRecordInfoProvider{
private static final Log LOG =
LogFactory.getLog(SimpleHiveRecordInfoProvider.class.getName());
private JsonNode recordNode = null;
private ObjectMapper jsonMapper = null;
public SimpleHiveRecordInfoProvider(){
jsonMapper = new ObjectMapper();
}
@Override
public void setCurrentRecord(Object record) throws Exception {
try{
if(record != null){
//parse the current value
recordNode = jsonMapper.readTree(record.toString());
}
}catch(Exception ex){
recordNode = null;
LOG.warn("Problem reading JSON record
value:"+record.toString(), ex);
}
}
@Override
public String getGeometry() {
if(recordNode == null){
return null;
}
JGeometry geom = null;
try{
geom = JsonUtils.readGeometry(recordNode,
2, //dimensions
8307 //SRID
);
}catch(Exception ex){
recordNode = null;
LOG.warn("Problem reading JSON record
geometry:"+recordNode.toString(), ex);
}
if(geom != null){
StringBuilder res = new StringBuilder();
//Get a GeoJSON representation of the JGeometry
GeoJsonGen.asGeometry(geom, res);
String result = res.toString();
//add SRID to GeoJSON and return the result
return JsonUtils.addSRIDToGeoJSON(result, 8307);
}
return null;
}
}
Hive Spatial APIは、1つ以上のジオメトリを使用してジオメトリを作成したり操作を実行したりするために使用できるOracle提供のHiveユーザー定義関数で構成されています。
これらの関数は、タイプ、単一のジオメトリ、2つのジオメトリという論理カテゴリにグループ化できます。(Hive空間関数は、各カテゴリ内の関数をリストし、各関数に関する参照情報を提供します。)
例2-5 Hiveスクリプト
次のスクリプトの例は、指定した地勢ポリゴン内におり、50人を超えるフォロワがいるデータ・セット内のTwitterユーザーに関する情報を返します。次の内容を実行します。
必要なjarファイルを追加します。
add jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/ojdbc8.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoutl.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoapi.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector-hive.jar;
使用対象のHiveユーザー定義機能を作成します。
create temporary function ST_Point as 'oracle.spatial.hadoop.vector.hive.ST_Point'; create temporary function ST_Polygon as 'oracle.spatial.hadoop.vector.hive.ST_Polygon'; create temporary function ST_Contains as 'oracle.spatial.hadoop.vector.hive.function.ST_Contains';
HDFSディレクトリ/user/oracle/twitterの下にあるファイルに基づいてHive表を作成します。この場合に使用されるInputFormatはoracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormatであり、Hive SerDeはユーザー定義のSerDe oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDeです。
CREATE EXTERNAL TABLE IF NOT EXISTS sample_tweets (id STRING, geometry STRING, followers_count STRING, friends_count STRING, location STRING) ROW FORMAT SERDE 'oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDe' STORED AS INPUTFORMAT 'oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION '/user/oracle/twitter';
ST_Polygon問合せ領域およびST_Pointツイート・ジオメトリを受け取り、空間操作の許容差値として0.5を使用する空間問合せを実行します。出力は、50人を超えるフォロワがいる問合せ領域内のTwitterユーザーに関する情報になります。
SELECT id, followers_count, friends_count, location FROM sample_tweets
WHERE ST_Contains(
ST_Polygon(
'{"type": "Polygon",
"coordinates":
[[[-106, 25],[-106, 30], [-104, 30], [-104, 25], [-106, 25]]]}',
8307
),
ST_Point(geometry, 8307),
0.5
)
and followers_count > 50;
完全なスクリプトは、次のとおりです。
add jar
/opt/oracle/oracle-spatial-graph/spatial/vector/jlib/ojdbc8.jar
/opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoutl.jar
/opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoapi.jar
/opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector.jar
/opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector-hive.jar;
create temporary function ST_Point as 'oracle.spatial.hadoop.vector.hive.ST_Point';
create temporary function ST_Polygon as 'oracle.spatial.hadoop.vector.hive.ST_Polygon';
create temporary function ST_Contains as 'oracle.spatial.hadoop.vector.hive.function.ST_Contains';
CREATE EXTERNAL TABLE IF NOT EXISTS sample_tweets (id STRING, geometry STRING, followers_count STRING, friends_count STRING, location STRING)
ROW FORMAT SERDE 'oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDe'
STORED AS INPUTFORMAT 'oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION '/user/oracle/twitter';
SELECT id, followers_count, friends_count, location FROM sample_tweets
WHERE
ST_Contains(
ST_Polygon(
'{"type": "Polygon",
"coordinates":
[[[-106, 25],[-106, 30], [-104, 30], [-104, 25], [-106, 25]]]}',
8307
),
ST_Point(geometry, 8307),
0.5
)
and followers_count > 50;
Hive空間問合せでは、前に作成した空間索引を使用できますが、これは、Java API (「空間の索引付け」を参照)を使用して作成できます。
元のデータにアクセスするAPI関数内の索引を使用する必要がない場合、oracle.spatial.hadoop.vector.mapred.job.SpatialIndexingを呼び出すときにisMapFileIndex=falseを指定するか、関数setMapFileIndex(false)を使用できます。これらの場合、索引の構造は次のようになります。
HDFSIndexDirectory/part-xxxxx
これらの場合、Hive表を作成するときに、索引を作成したフォルダを提供してください。
元のデータに関係する必要がある場合に、パラメータisMapFileIndex=falseを設定していない場合、索引構造は次のようになります。
part-xxxxx data index
このような場合、Hive表を作成するには、索引のデータ・ファイルが必要です。dataファイルを新しいHDFSフォルダにコピーしますが、この場合、各データ・ファイルがdata1やdata2などの異なる名前を持つようにします。この新しいフォルダがHive表の作成に使用されます。
索引には、ジオメトリ・レコードおよび追加フィールドが含まれます。このデータは、Hive表の作成時に使用できます。
(「空間の索引付けクラスの構造」では、索引構造が説明されており、「RecordInfoProvider」には、追加フィールドを追加するRecordInfoProviderの例が用意されています。)
索引の読み取りには、InputFormat oracle.spatial.hadoop.vector.mapred.input.SpatialIndexTextInputFormatが使用されます。このInputFormatの出力はGeoJSONです。
任意の問合せを実行する前に、SpatialIndexTextInputFormatを使用して最初のデータ・フィルタ処理を実行する最小外接矩形(MBR)を指定できます。
例2-6 空間索引を使用したHiveスクリプト
次のスクリプトの例は、指定した地勢ポリゴン内におり、50人を超えるフォロワがいるデータ・セット内のTwitterユーザーに関する情報を返します。次の内容を実行します。
必要なjarファイルを追加します。
add jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/ojdbc8.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoutl.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoapi.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector-hive.jar;
使用対象のHiveユーザー定義機能を作成します。
create temporary function ST_Point as 'oracle.spatial.hadoop.vector.hive.ST_Point'; create temporary function ST_Polygon as 'oracle.spatial.hadoop.vector.hive.ST_Polygon'; create temporary function ST_Contains as 'oracle.spatial.hadoop.vector.hive.function.ST_Contains';
データの最大および最小の境界(dim1Min,dim2Min,dim1Max,dim2Max)を設定します。
set oracle.spatial.boundaries=-180,-90,180,90;
set oracle.spatial.index.includedExtraFields=followers_count,friends_count,location;
HDFSディレクトリ/user/oracle/twitterの下にあるファイルに基づいてHive表を作成します。この場合に使用されるInputFormatはoracle.spatial.hadoop.vector.mapred.input.SpatialIndexTextInputFormatであり、Hive SerDeはユーザー定義のSerDe oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDeです。(oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDeのコードは、Hiveの例に含まれています。)ツイートのジオメトリは、形式{"longitude":n, "latitude":n}のジオメトリ列に保存されます。
CREATE EXTERNAL TABLE IF NOT EXISTS sample_tweets_index (id STRING, geometry STRING, followers_count STRING, friends_count STRING, location STRING) ROW FORMAT SERDE 'oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDe' STORED AS INPUTFORMAT 'oracle.spatial.hadoop.vector.mapred.input.SpatialIndexTextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION '/user/oracle/twitter/index';
SpatialIndexTextInputFormatでフィルタ処理する最小外接矩形(MBR)を定義します。すべての空間索引がこのMBR内のデータのみにアクセスできます。MBRが指定されていない場合、データ境界が使用されます。パフォーマンスを向上させるにはこの設定をお薦めします。
set oracle.spatial.spatialQueryWindow={"type": "Polygon","coordinates": [[[-107, 24], [-107, 31], [-103, 31], [-103, 24], [-107, 24]]]};
ST_Polygon問合せ領域およびST_Pointツイート・ジオメトリを受け取り、空間操作の許容差値として0.5を使用する空間問合せを実行します。ツイート・ジオメトリはGeoJSON形式であり、ST_Point関数はSRIDを8307として指定して使用されます。出力は、50人を超えるフォロワがいる問合せ領域内のTwitterユーザーに関する情報になります。
SELECT id, followers_count, friends_count, location FROM sample_tweets
WHERE ST_Contains(
ST_Polygon('{"type": "Polygon","coordinates": [[[-106, 25], [-106, 30], [-104, 30], [-104, 25], [-106, 25]]]}', 8307)
, ST_Point(geometry, 8307)
, 0.5)
and followers_count > 50;
完全なスクリプトは、次のとおりです。(このスクリプトと「Hive Spatial APIの使用」内のスクリプトの差異は太字でマークされていますが、すべての手順は前のリストで説明されています。)
add jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/ojdbc8.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoutl.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdoapi.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector.jar /opt/oracle/oracle-spatial-graph/spatial/vector/jlib/sdohadoop-vector-hive.jar; create temporary function ST_Polygon as 'oracle.spatial.hadoop.vector.hive.ST_Polygon'; create temporary function ST_Point as 'oracle.spatial.hadoop.vector.hive.ST_Point'; create temporary function ST_Contains as 'oracle.spatial.hadoop.vector.hive.function.ST_Contains'; set oracle.spatial.boundaries=-180,-90,180,90; set oracle.spatial.index.includedExtraFields=followers_count,friends_count,location; CREATE EXTERNAL TABLE IF NOT EXISTS sample_tweets_index (id STRING, geometry STRING, followers_count STRING, friends_count STRING, location STRING) ROW FORMAT SERDE 'oracle.spatial.hadoop.vector.hive.json.GeoJsonSerDe' STORED AS INPUTFORMAT 'oracle.spatial.hadoop.vector.mapred.input.SpatialIndexTextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION '/user/oracle/twitter/index'; set oracle.spatial.spatialQueryWindow={"type": "Polygon","coordinates": [[[-107, 24], [-107, 31], [-103, 31], [-103, 24], [-107, 24]]]}; SELECT id, followers_count, friends_count, location FROM sample_tweets WHERE ST_Contains( ST_Polygon('{"type": "Polygon","coordinates": [[[-106, 25], [-106, 30], [-104, 30], [-104, 25], [-106, 25]]]}', 8307) , ST_Point(geometry, 8307) , 0.5) and followers_count > 50;
Oracle Big Data SpatialViewer Webアプリケーション(SpatialViewer)を使用すると、空間索引付けおよびテーマ・マップの作成と表示に関連するタスクを実行できます。
SpatialViewerを使用してHadoop空間索引を作成するには、次の手順に従います。
コンソールhttp://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます
「Spatial Index」をクリックします。
必要な詳細をすべて指定します。
索引名。
HDFSの索引へのファイルのパス。例: /user/oracle/bdsg/tweets.json。
新しい索引パス: これはジョブ出力パスです。例: /user/oracle/bdsg/index。
索引付けするジオメトリのSRID。例: 8307
索引付けするジオメトリの許容差。例: 0.05
入力形式クラス: 入力形式のクラス。例: oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。例: oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider。
注意:
InputFormatクラスまたはRecordInfoProviderクラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このjarを使用するには、/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/WEB-INF/libディレクトリに追加し、サーバーを再起動する必要があります。
エンリッチメント・サービス(MVSuggest)を使用する必要があるかどうか。ジオメトリを場所の文字列から検出する場合は、MVSuggestサービスを使用します。この場合、指定されたRecordInfoProviderがインタフェースoracle.spatial.hadoop.vector.LocalizableRecordInfoProviderを実装する必要があります。
MVSuggestテンプレート(オプション): MVSuggestサービスを使用する場合、索引の作成に使用するテンプレートを定義できます。
「Create」をクリックします。
ジョブを追跡するためにURLが表示されます。
Hadoop索引付き空間データを検索するには、次の手順を実行します。
コンソールhttp://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます
「Explore Data」をクリックします。
たとえば、次のことが可能です。
目的の索引付きデータを選択し、矩形ツールを使用して目的の領域内のデータを表示します。
背景地図のスタイルを変更します。
ヒート・マップを使用してデータを表示します。
SpatialViewerを使用してSpark空間索引を作成するには、次の手順に従います。
コンソールhttp://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorsparkを開きます
「Spatial Index」をクリックします。
必要な詳細をすべて指定します。
索引名。
HDFSの索引へのファイルのパス。例: /user/oracle/bdsg/tweets.json。
新しい索引パス: これはジョブ出力パスです。例: /user/oracle/bdsg/index。
索引付けするジオメトリのSRID。例: 8307
索引付けするジオメトリの許容差。例: 0.05
入力形式クラス(オプション): 入力形式のクラス。例: oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat
キー・クラス(入力形式クラスが定義されている場合は必須): 入力形式キーのクラス。例: org.apache.hadoop.io.LongWritable
値クラス(入力形式クラスが定義されている場合は必須): 入力形式値のクラス。例: org.apache.hadoop.io.Text
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。例: oracle.spatial.spark.vector.recordinfoprovider.GeoJsonRecordInfoProvider
注意:
InputFormatクラスまたはRecordInfoProviderクラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このjarを使用するには、/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/WEB-INF/lib directoryに追加し、サーバーを再起動する必要があります。
「Create」をクリックします。
ジョブを追跡するためにURLが表示されます。
Spark索引付き空間データを検索するには、次の手順を実行します。
コンソールhttp://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorsparkを開きます
「Explore Data」をクリックします。
たとえば、次のことが可能です。
目的の索引付きデータを選択し、矩形ツールを使用して目的の領域内のデータを表示します。
背景地図のスタイルを変更します。
カテゴリ化ジョブは空間索引の有無に関係なく実行できます。次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます。
「Categorization」、「Categorization Job」の順にクリックします。
「With Index」または「Without Index」のいずれかを選択し、必要に応じて次の詳細を入力します。
With Index
索引名
Without Index
データのパス: HDFSデータ・パスを入力します。例: /user/oracle/bdsg/tweets.json。
ユーザー・クラスのあるJAR (オプション): InputFormatクラスまたはRecordInfoProviderクラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このjarを使用するには、/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/WEB-INF/libディレクトリに追加し、サーバーを再起動する必要があります。
入力形式クラス: 入力形式のクラス。例: oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。例: oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider。
エンリッチメント・サービスMVSuggestを使用する必要があるかどうか。ジオメトリを場所の文字列から検出する場合は、MVSuggestサービスを使用します。この場合、指定されたRecordInfoProviderがインタフェース oracle.spatial.hadoop.vector.LocalizableRecordInfoProviderを実装する必要があります。
テンプレート: テーマ・マップを作成するテンプレート。
注意:
テンプレートが点ジオメトリ(都市など)を参照する場合、MVSuggestが使用されていないと、そのテンプレートに空白の結果が返されます。これは、空間操作がポリゴンの結果のみを返すためです。
ヒント:
MVSuggestサービスを使用したとき、結果と一致するすべてのテンプレートが提供されていれば、結果はさらに正確になります。たとえば、データが世界の都市、州、国、大陸部を参照する場合、結果を得るために最適なテンプレートは、「World Continents」、「World Countries」、「World State Provinces」、および「World Cities」になります。また、データがUSAの州および郡の場合、適切なテンプレートは「USA States」および「USA Counties」になります。MVSuggestサービスを使用して作成した索引を選択した場合、最適な結果を得るには最上位の階層を選択します。たとえば、「World Countries」、「World State Provinces」、「World Cities」を使用して作成した場合は、「World Countries」をテンプレートとして使用します。
出力パス: Hadoopジョブ出力パス。例: /user/oracle/bdsg/catoutput
結果名: 結果の名前。同じ名前の結果がテンプレートにある場合は上書きされます。例: Tweets test。
「Create」をクリックします。ジョブを追跡するためにURLが表示されます。
カテゴリ化結果は、将来可能性があるアップロードや使用に備えてローカル・システム上のファイル(コマンド・ラインから実行されたジョブを使用して作成された結果ファイルなど)に保存できます。テンプレートは、フォルダ/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/templates内にあります。テンプレートは各種機能を備えたGeoJSONファイルであり、機能にはすべてIDがあります。たとえば、テンプレート「USA States」の最初の機能は{"type":"Feature","_id":"WYOMING",...から始まります。
結果は{"id":"JSONFeatureId","result":result}の形式のJSONファイルになります。
たとえば、テンプレート「USA States」が選択されると、有効な結果は、{"id":"WYOMING","result":3232} {"id":"SOUTH DAKOTA","result":74968}を含むファイルになります
新しいテンプレートを作成するには、次の手順を実行します。
/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/templates/に追加します。/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/templates/_config_に追加します。テンプレートを削除するには、ステップ1と2で追加したJSONファイルおよび構成ファイルを削除します。
各テンプレートには構成ファイルがあります。テンプレート構成ファイルは、フォルダ/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/templates/_config_内にあります。構成ファイルの名前は、テンプレート・ファイルと同じ名前に.jsonではなくconfig.jsonを付けたものです。たとえば、テンプレート・ファイルusa_states.jsonの構成ファイル名は usa_states.config.jsonになります。構成パラメータは次のとおりです。
name: コンソールに表示されるテンプレートの名前。たとえば、name: USA Statesです。
display_attribute: カテゴリ化結果を表示するとき、カーソルがこのプロパティと機能の結果を表示する機能の上に移動します。たとえば、display_attribute: STATE NAMEです。
point_geometry: テンプレートに点ジオメトリがある場合はtrue、ポリゴンの場合はfalseです。たとえば、point_geometry: falseです。
child_templates (オプション): 使用できる複数の子テンプレートをカンマで区切ってリストできるテンプレートです。たとえば、child_templates: ["world_states_provinces, usa_states(properties.COUNTRY CODE:properties.PARENT_REGION)"]です。
子テンプレートがリンク・フィールドを指定しない場合、親の機能にあるすべての機能は子の機能とみなされます。この場合、world_states_provincesはフィールドを指定しません。親と子の間のリンクが指定されている場合、空間関係は適用されず、機能プロパティのリンクがチェックされます。前述の例では、usa_statesとの関係が現在のテンプレートのプロパティCOUNTRY CODEおよびテンプレート・ファイルusa_states.jsonのプロパティPARENT_REGIONで検出されます。
srid: テンプレートのジオメトリのSRIDです。たとえば、srid: 8307です。
back_polygon_template_file_name (オプション): 定義済テンプレートを表示するときに、背景として設定されるポリゴン・ジオメトリのあるテンプレートです。たとえば、back_polygon_template_file_name: usa_statesです。
vectorLayers: MVSuggestサービスに固有の構成です。次に例を示します。
{
"vectorLayers": [
{
"gnidColumns":["_GNID"],
"boostValues":[2.0,1.0,1.0,2.0]
}
]
}
説明:
gnidColumnsはジオメトリ名IDを示すJsonファイル内の列名です。この値はMVSuggestで複数の言語をサポートする場合に使用されます。(ファイルtemplates/_geonames_/alternateNames.jsonの値の参照を確認してください。)このプロパティのデフォルト値はありません。
boostValuesは浮動小数点の数値の配列であり、列が指定の行の「プロパティ」値の中にあることの重要性を示します。数値が大きいほど、そのフィールドの重要性も大きくなります。ゼロの値はフィールドが無視されることを意味します。boostValuesがない場合は、すべてのフィールドがデフォルト値の1.0をとり、重要性が同じプロパティであることを示します。MVSuggestサービスは、その値に応じて異なる結果を返します。次のプロパティのあるJsonファイルの場合、boost値は次のようになります。
"properties":{"Name":"New York City","State":"NY","Country":"United States","Country Code":"US","Population":8491079,"Time Zone":"UTC-5"}
"boostValues":[3.0,2.0,1.0,1.0,0.0,0.0]
SpatialViewerを使用してクラスタ化ジョブを作成するには、次の手順に従います。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます
「Clustering」、「Clustering Job」の順にクリックします。
必要に応じて、次の詳細を指定します。
データのパス: HDFSデータ・パスを入力します。例: /user/oracle/bdsg/tweets.json。
ジオメトリのSRID。例: 8307
ジオメトリの許容差。例: 0.05
ユーザー・クラスのあるJAR (オプション): InputFormatクラスまたはRecordInfoProviderクラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このjarを使用するには、/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/WEB-INF/libディレクトリに追加し、サーバーを再起動する必要があります。
入力形式クラス: 入力形式のクラス。例: oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。例: oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider。
クラスタの数: 検出されるクラスタの数。
出力パス: Hadoopジョブ出力パス。例: /user/oracle/bdsg/catoutput
結果名: 結果の名前。同じ名前の結果がテンプレートにある場合は上書きされます。たとえば、「Tweets test」などです。
「Create」をクリックします。
ジョブを追跡するためにURLが表示されます。
クラスタ化結果を表示するには、次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます。クラスタ化結果は、後でアップロードおよび使用するためにローカル・システム上のファイルに保存できます。クラスタ化結果をファイルに保存するには、次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます。ビニング・ジョブは空間索引の有無に関係なく実行できます。次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます。
「Binning」、「Binning Job」の順にクリックします。
「With Index」または「Without Index」のいずれかを選択し、必要に応じて次の詳細を入力します。
With Index
索引名
Without Index
データのパス: HDFSデータ・パスを入力します。例: /user/oracle/bdsg/tweets.json
ジオメトリのSRID。例: 8307
ジオメトリの許容差。例: 0.05
ユーザー・クラスのあるJAR (オプション): InputFormatクラスまたはRecordInfoProviderクラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このjarを使用するには、/opt/oracle/oracle-spatial-graph/spatial/web-server/spatialviewer/WEB-INF/libディレクトリに追加し、サーバーを再起動する必要があります。
入力形式クラス: 入力形式のクラス。例: oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。例: oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider。
ビニングおよび最小外接矩形(MBR)。地図上のMBR表示するためのアイコンをクリックできます。
ビニング形状: 六角形(六角形の幅を指定します)または矩形(幅と高さを指定します)。
テーマ属性: ジョブに索引が使用される場合、ダブルクリックして使用可能な値を表示します。これらは、索引の作成時に使用されたRecordInfoProviderの関数getExtraFieldsによって返されたものです。ジョブに索引が使用されない場合、フィールドは、指定したRecordInfoProviderクラスの関数getExtraFieldsによって返されるフィールドの1つである場合があります。いずれの場合も、count属性は常に使用可能であり、この属性により、ビン内のレコードの数を指定します。
出力パス: Hadoopジョブ出力パス。例: /user/oracle/bdsg/binningOutput
結果名: 結果の名前。同じ名前の結果がテンプレートにある場合は上書きされます。たとえば、「Tweets test」などです。
「Create」をクリックします。ジョブを追跡するためにURLが表示されます。
ビニング結果を表示するには、次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます。ビニング結果は、後でアップロードおよび使用するためにローカル・システム上のファイルに保存できます。ビニング結果をファイルに保存するには、次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8045/spatialviewer/?root=vectorを開きます。空間索引を作成するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH>/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SpatialIndexing [generic options] input=<path|comma_separated_paths|path_pattern> output=<path> inputFormat=<InputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass> [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<minX,minY,maxX,maxY>] [indexName=<index_name>] [indexMetadataDir=<path>] [overwriteIndexMetadata=<true|false>] [ mvsLocation=<path|URL> [mvsMatchLayers=<comma_separated_layers>][mvsMatchCountry=<country_name>][mvsSpatialResponse=<[NONE, FEATURE_GEOMETRY, FEATURE_CENTROID]>][mvsInterfaceType=<LOCAL, WEB>][mvsIsRepository=<true|false>][rebuildMVSIndex=<true|false>][mvsPersistentLocation=<hdfs_path>][mvsOverwritePersistentLocation=<true|false>] ]
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.SpatialIndexingをoracle.spatial.hadoop.vector.mapreduce.job.SpatialIndexingに置き換えます。
入力/出力引数:
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。
output: 空間索引の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
boundaries (オプション、デフォルト=unbounded): minX,minY,maxX,maxYの形式でカンマ区切りの値として表される各次元の最小値および最大値
空間索引メタデータの引数:
indexName (オプション、デフォルト=出力フォルダ名): 生成対象の索引の名前。
indexMetadataDir (オプション、デフォルト=hdfs://server:port/user/<current_user>/またはoracle_spatial/index_metadata/): 空間索引メタデータの格納先のディレクトリ。
overwriteIndexMetadata (オプション、デフォルト=false)同じ名前の索引がすでに存在する場合に索引メタデータを上書きできるかどうかを示すブール引数。
MVSuggest引数:
mvsLocation: リモート・インスタンスの操作時のサービスURLまたはMVSuggestのローカル・スタンドアロン・インスタンスのMVSuggestディレクトリまたはリポジトリへのパス。この引数は、MVSuggestを操作するときに必要です。
mvsMatchLayers (オプション、デフォルト=all): カンマ区切りのレイヤーのリスト。指定されている場合、MVSuggestでは、検索の実行時にこれらのレイヤーのみが使用されます。
mvsMatchCountry (オプション、デフォルト=none): MVSuggestでの照合の実行時により高い優先度が与えられる国名。
mvsSpatialResponse (オプション、デフォルト=CENTROID): 返された各照合結果に含まれる空間結果のタイプ。使用可能な値は、NONE、FEATURE_GEOMETRY、FEATURE_CENTROIDです。
mvsInterfaceType (オプション、デフォルト=LOCAL): 使用されるMVSuggestサービスのタイプで、LOCALまたはWEBがあります。
mvsIsRepository (オプション、デフォルト=false) (LOCALのみ): mvsLocationがMVSディレクトリ全体(false)を指し示すかリポジトリのみ(true)を指し示すかを示すブール値。MVSリポジトリにはJSONテンプレートのみを含めることができます。_config_や_geonames_フォルダが含まれる場合や含まれない場合があります。
mvsRebuildIndex (オプション、デフォルト=false) (LOCALのみ): リポジトリ索引を再構築する必要があるかどうかを示すブール値。
mvsPersistentLocation (オプション、デフォルト=none) (LOCALのみ): MVSuggestディレクトリの保存先のHDFSパス。
mvsIsOverwritePersistentLocation (オプション、デフォルト=false): 既存のmvsPersistentLocationが存在する場合に上書きする必要があるかどうかを示すブール引数。
例: indexExampleと呼ばれる空間索引を作成します。索引メタデータは、HDFSディレクトリspatialMetadataに格納されます。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SpatialIndexing input="/user/hdfs/demo_vector/tweets/part*" output=/user/hdfs/demo_vector/tweets/spatial_index inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider srid=8307 geodetic=true tolerance=0.5 indexName=indexExample indexMetadataDir=indexMetadataDir overwriteIndexMetadata=true
例: MVSuggestを使用して空間索引を作成し、ジオメトリが含まれないレコードに空間の場所を割り当てます。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SpatialIndexing input="/user/hdfs/demo_vector/tweets/part*" output=/user/hdfs/demo_vector/tweets/spatial_index inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=mypackage.Simple LocationRecordInfoProvider srid=8307 geodetic=true tolerance=0.5 indexName=indexExample indexMetadataDir=indexMetadataDir overwriteIndexMetadata=true mvsLocation=file:///local_folder/mvs_dir/oraclemaps_pub/ mvsRepository=true
カテゴリ化結果を作成するには、次の形式の1つのコマンドを使用します。
空間索引がある場合
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Categorization [generic options] ( indexName=<indexName> [indexMetadataDir=<path>] ) | ( input=<path|comma_separated_paths|path_pattern> isInputIndex=true [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>] ) output=<path> hierarchyIndex=<hdfs_hierarchy_index_path> hierarchyInfo=<HierarchyInfo_subclass> [hierarchyDataPaths=<level1_path,level2_path,,levelN_path>] spatialOperation=<[None, IsInside, AnyInteract]>
空間索引がない場合
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Categorization [generic options] input=<path|comma_separated_paths|path_pattern> inputFormat=<InputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass> [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>] output=<path> hierarchyIndex=<hdfs_hierarchy_index_path> hierarchyInfo=<HierarchyInfo_subclass> hierarchyDataPaths=<level1_path,level2_path,,levelN_path>] spatialOperation=<[None, IsInside, AnyInteract]>
MVSuggestの使用
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Categorization [generic options] (indexName=<indexName> [indexMetadataDir=<path>]) | ( (input=<path|comma_separated_paths|path_pattern> isInputIndex=true) | (input=<path|comma_separated_paths|path_pattern> inputFormat=<InputFormat_subclass> recordInfoProvider=<LocalizableRecordInfoProvider_subclass>) [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>] ) output=<path> mvsLocation=<path|URL> [mvsMatchLayers=<comma_separated_layers>] [mvsMatchCountry=<country_name>] [mvsSpatialResponse=<[NONE, FEATURE_GEOMETRY, FEATURE_CENTROID]>] [mvsInterfaceType=<[UNDEFINED, LOCAL, WEB]>] [mvsIsRepository=<true|false>] [mvsRebuildIndex=<true|false>] [mvsPersistentLocation=<hdfs_path>] [mvsOverwritePersistentLocation=<true|false>] [mvsMaxRequestRecords=<integer_number>] hierarchyIndex=<hdfs_hierarchy_index_path> hierarchyInfo=<HierarchyInfo_subclass>
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.Categorizationをoracle.spatial.hadoop.vector.mapreduce.job.Categorizationに置き換えます。
入力/出力引数:
indexName: 既存の空間索引の名前。索引情報は、indexMetadataDirによって示されるパスで参照します。使用されている場合、引数inputは無視されます。
indexMetadataDir (オプション、デフォルト=hdfs://server:port/user/<current_user>/oracle_spatial/index_metadata/): 空間索引メタデータの格納先のディレクトリ
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。(indexNameが指定されている場合は無視されます。)
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。(indexNameが指定されている場合は無視されます。)
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。(indexNameが指定されている場合は無視されます。)
output: 空間索引の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
boundaries (オプション、デフォルト=unbounded): minX,minY,maxX,maxYの形式でカンマ区切りの値として表される各次元の最小値および最大値
spatialOperation: 入力データ・セットと階層データ・セットの間で実行する空間操作。使用可能な値は、IsInsideおよびAnyInteractです。
階層データ・セットの引数:
hierarchyIndex: 既存の階層索引のHDFSパス、または階層索引を生成する必要がある場合に階層索引を格納できるHDFSパス。
hierarchyInfo: 階層データを記述するために使用されるHierarchyInfoサブクラスの完全修飾名。
hierarchyDataPaths (オプション、デフォルト=none): 階層データのパスのカンマ区切りのリスト。これらのパスは、階層レベル別に昇順でソートする必要があります。特定の階層データの階層索引パスが存在しない場合、この引数が必要です。
MVSuggest引数:
mvsLocation: リモート・インスタンスの操作時のサービスURLまたはMVSuggestのローカル・スタンドアロン・インスタンスのMVSuggestディレクトリまたはリポジトリへのパス。この引数は、MVSuggestを操作するときに必要です。
mvsMatchLayers (オプション、デフォルト=all): カンマ区切りのレイヤーのリスト。指定されている場合、MVSuggestでは、検索の実行時にこれらのレイヤーのみが使用されます。
mvsMatchCountry (オプション、デフォルト=none): MVSuggestでの照合の実行時により高い優先度が与えられる国名。
mvsSpatialResponse (オプション、デフォルト=CENTROID): 返された各照合結果に含まれる空間結果のタイプ。使用可能な値は、NONE、FEATURE_GEOMETRY、FEATURE_CENTROIDです。
mvsInterfaceType (オプション、デフォルト=LOCAL): 使用されるMVSuggestサービスのタイプで、LOCALまたはWEBがあります。
mvsIsRepository (オプション、デフォルト=false) (LOCALのみ): mvsLocationがMVSディレクトリ全体(false)を指し示すかリポジトリのみ(true)を指し示すかを示すブール値。MVSリポジトリにはJSONテンプレートのみを含めることができます。_config_や_geonames_フォルダが含まれる場合や含まれない場合があります。
mvsRebuildIndex (オプション、デフォルト=false) (LOCALのみ): リポジトリ索引を再構築する必要があるかどうかを示すブール値。
mvsPersistentLocation (オプション、デフォルト=none) (LOCALのみ): MVSuggestディレクトリの保存先のHDFSパス。
mvsIsOverwritePersistentLocation (オプション、デフォルト=false): 既存のmvsPersistentLocationが存在する場合に上書きする必要があるかどうかを示すブール引数。
例: 大陸部、国、および州別にレコード数が含まれるサマリーを作成するためのカテゴリ化ジョブを実行します。この入力は、indexExampleと呼ばれる既存の空間索引です。階層データは、索引が付けられ、パスhierarchyIndexでHDFSに格納されます。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Categorization indexName= indexExample output=/user/hdfs/demo_vector/tweets/hier_count_spatial hierarchyInfo=vectoranalysis.categorization.WorldAdminHierarchyInfo hierarchyIndex=hierarchyIndex hierarchyDataPaths=file:///templates/world_continents.json,file:///templates/world_countries.json,file:///templates/world_states_provinces.json spatialOperation=IsInside
例: MVSuggestを使用して大陸部、国、州、および都市当たりのツイート数のサマリーを作成するためのカテゴリ化ジョブを実行します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Categorization input="/user/hdfs/demo_vector/tweets/part*" inputFormat=<InputFormat_subclass> recordInfoProvider=<LocalizableRecordInfoProvider_subclass> output=/user/hdfs/demo_vector/tweets/hier_count_mvs hierarchyInfo=vectoranalysis.categorization.WorldAdminHierarchyInfo hierarchyIndex=hierarchyIndex mvsLocation=file:///mvs_dir mvsMatchLayers=world_continents,world_countries,world_states_provinces spatialOperation=IsInside
クラスタ化結果を作成するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.KMeansClustering [generic options] input=<path|comma_separated_paths|path_pattern> inputFormat=<InputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass> output=<path> [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>] k=<number_of_clusters> [clustersPoints=<comma_separated_points_ordinates>] [deleteClusterFiles=<true|false>] [maxIterations=<integer_value>] [critFunClass=<CriterionFunction_subclass>] [shapeGenClass=<ClusterShapeGenerator_subclass>] [maxMemberDistance=<double_value>]
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.KMeansClusteringをoracle.spatial.hadoop.vector.mapreduce.job.KMeansClusteringに置き換えます。
入力/出力引数:
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。
output: 空間索引の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
boundaries (オプション、デフォルト=unbounded): minX,minY,maxX,maxYの形式でカンマ区切りの値として表される各次元の最小値および最大値
spatialOperation: 入力データ・セットと階層データ・セットの間で実行する空間操作。使用可能な値は、IsInsideおよびAnyInteractです。
クラスタ化の引数:
k: 検出されるクラスタの数。
clusterPoints (オプション、デフォルト=none): p1_x,p1_y,p2_x,p2_y,…,pk_x,pk_y形式の点座標のカンマ区切りのリストである初期のクラスタの中心
deleteClusterFiles (オプション、デフォルト=true): 各反復の間に生成される中間クラスタ・ファイルを削除する必要があるかどうかを示すブール引数
maxIterations (オプション、デフォルト=数値kに基づいて計算されます): ジョブが完了するまでに許可される反復の最大回数。
critFunClass (オプション、デフォルト=oracle.spatial.hadoop.vector.cluster.kmeans.SquaredErrorCriterionFunction): CriterionFunctionサブクラスの完全修飾名。
shapeGenClass (オプション、デフォルト=oracle.spatial.hadoop.vector.cluster.kmeans.ConvexHullClusterShapeGenerator) クラスタのジオメトリを生成するために使用されるClusterShapeGeneratorサブクラスの完全修飾名。
maxMemberDistance (オプション、デフォルト=undefined): クラスタの中心とクラスタ・メンバーの間の最大距離を示すdouble値。
例: 5つのクラスタを生成するクラスタ化ジョブを実行します。シェルされたクラスタ・ジオメトリはすべての凸包になります。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.KMeansClustering input="/user/hdfs/demo_vector/tweets/part*" output=/user/hdfs/demo_vector/tweets/result inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider srid=8307 geodetic=true tolerance=0.5 k=5 shapeGenClass=oracle.spatial.hadoop.vector.cluster.kmeans.ConvexHullClusterShapeGenerator
ビニング結果を作成するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Binning [generic options] (indexName=<INDEX_NAME> [indexMetadataDir=<INDEX_METADATA_DIRECTORY>]) | (input=<DATA_PATH> inputFormat=<INPUT_FORMAT_CLASS> recordInfoProvider=<RECORD_INFO_PROVIDER_CLASS> [srid=<SRID>] [geodetic=<GEODETIC>] [tolerance=<TOLERANCE>]) output=<RESULT_PATH> cellSize=<CELL_SIZE> gridMbr=<GRID_MBR> [cellShape=<CELL_SHAPE>] [aggrFields=<EXTRA_FIELDS>]
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.Binningをoracle.spatial.hadoop.vector.mapreduce.job.Binningに置き換えます。
入力/出力引数:
indexName: 既存の空間索引の名前。索引情報は、indexMetadataDirによって示されるパスで参照します。使用されている場合、引数inputは無視されます。
indexMetadataDir (オプション、デフォルト=hdfs://server:port/user/<current_user>/oracle_spatial/index_metadata/): 空間索引メタデータの格納先のディレクトリ
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。
output: 空間索引の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
ビニングの引数:
cellSize: width,heightの形式のセルのサイズ
gridMbr : minX,minY,maxX,maxYの形式のグリッドの最小および最大次元値
cellShape (オプション、デフォルト=RECTANGLE): セルの形状。使用可能な値は、RECTANGLEまたはHEXAGONです
aggrFields (オプション、デフォルト=none): 集計されるフィールド名のカンマ区切りのリスト。
例: 六角形のセルのグリッドを生成し、フィールドSALESの値を集計する空間ビニング・ジョブを実行します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Binning indexName=indexExample indexMetadataDir=indexMetadataDir output=/user/hdfs/demo_vector/result cellShape=HEXAGON cellSize=5 gridMbr=-175,-85,175,85 aggrFields=SALES
空間フィルタ処理を実行するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SpatialFilter [generic options] ( indexName=<indexName> [indexMetadataDir=<path>] ) | ( (input=<path|comma_separated_paths|path_pattern> isInputIndex=true) | (input=<path|comma_separated_paths|path_pattern> inputFormat=<InputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass>) [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>] ) output=<path> spatialOperation=<[IsInside, AnyInteract]> queryWindow=<json-geometry>
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.SpatialFilterをoracle.spatial.hadoop.vector.mapreduce.job.SpatialFilterに置き換えます。
入力/出力引数:
indexName: 既存の空間索引の名前。索引情報は、indexMetadataDirによって示されるパスで参照します。使用されている場合、引数inputは無視されます。
indexMetadataDir (オプション、デフォルト=hdfs://server:port/user/<current_user>/oracle_spatial/index_metadata/): 空間索引メタデータの格納先のディレクトリ
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。
output: 空間索引の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
ビニングの引数:
cellSize: width,heightの形式のセルのサイズ
gridMbr : minX,minY,maxX,maxYの形式のグリッドの最小および最大次元値
cellShape (オプション、デフォルト=RECTANGLE): セルの形状。使用可能な値は、RECTANGLEまたはHEXAGONです
aggrFields (オプション、デフォルト=none): 集計されるフィールド名のカンマ区切りのリスト。
boundaries (オプション、デフォルト=unbounded): minX,minY,maxX,maxYの形式でカンマ区切りの値として表される各次元の最小値および最大値
spatialOperation: 入力データ・セットからのジオメトリとqueryWindowの間で適用する操作
queryWindow: 入力データ・セットをフィルタ処理するために使用されるジオメトリ。
例: 空間フィルタ処理操作を実行します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SpatialFilter indexName=indexExample indexMetadataDir=indexMetadataDir output=/user/hdfs/demo_vector/result spatialOperation=IsInside queryWindow='{"type":"Polygon", "coordinates":[[-106, 25, -106, 30, -104, 30, -104, 25, -106, 25]]}'
場所の提案を取得するジョブを作成するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SuggestService [generic options] input=<path|comma_separated_paths|path_pattern> inputFormat=<InputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass> output=<path> mvsLocation=<path|URL> [mvsMatchLayers=<comma_separated_layers>] [mvsMatchCountry=<country_name>] [mvsSpatialResponse=<[NONE, FEATURE_GEOMETRY, FEATURE_CENTROID]>] [mvsInterfaceType=<[UNDEFINED, LOCAL, WEB]>] [mvsIsRepository=<true|false>] [mvsRebuildIndex=<true|false>] [mvsPersistentLocation=<hdfs_path>] [mvsOverwritePersistentLocation=<true|false>] [mvsMaxRequestRecords=<integer_number>]
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.SuggestServiceをoracle.spatial.hadoop.vector.mapreduce.job.SuggestServiceに置き換えます。
入力/出力引数:
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。(indexNameが指定されている場合は無視されます。)
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。(indexNameが指定されている場合は無視されます。)
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。(indexNameが指定されている場合は無視されます。)
output: 空間索引の格納先のパス
MVSuggest引数:
mvsLocation: リモート・インスタンスの操作時のサービスURLまたはMVSuggestのローカル・スタンドアロン・インスタンスのMVSuggestディレクトリまたはリポジトリへのパス。この引数は、MVSuggestを操作するときに必要です。
mvsMatchLayers (オプション、デフォルト=all): カンマ区切りのレイヤーのリスト。指定されている場合、MVSuggestでは、検索の実行時にこれらのレイヤーのみが使用されます。
mvsMatchCountry (オプション、デフォルト=none): MVSuggestでの照合の実行時により高い優先度が与えられる国名。
mvsSpatialResponse (オプション、デフォルト=CENTROID): 返された各照合結果に含まれる空間結果のタイプ。使用可能な値は、NONE、FEATURE_GEOMETRY、FEATURE_CENTROIDです。
mvsInterfaceType (オプション、デフォルト=LOCAL): 使用されるMVSuggestサービスのタイプで、LOCALまたはWEBがあります。
mvsIsRepository (オプション、デフォルト=false) (LOCALのみ): mvsLocationがMVSディレクトリ全体(false)を指し示すかリポジトリのみ(true)を指し示すかを示すブール値。MVSリポジトリにはJSONテンプレートのみを含めることができます。_config_や_geonames_フォルダが含まれる場合や含まれない場合があります。
mvsRebuildIndex (オプション、デフォルト=false) (LOCALのみ): リポジトリ索引を再構築する必要があるかどうかを示すブール値。
mvsPersistentLocation (オプション、デフォルト=none) (LOCALのみ): MVSuggestディレクトリの保存先のHDFSパス。
mvsIsOverwritePersistentLocation (オプション、デフォルト=false): 既存のmvsPersistentLocationが存在する場合に上書きする必要があるかどうかを示すブール引数。
例: 入力データ・セットからの場所テキストに基づいて提案を取得します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SuggestService input="/user/hdfs/demo_vector/tweets/part*" inputFormat=<InputFormat_subclass> recordInfoProvider=<LocalizableRecordInfoProvider_subclass> output=/user/hdfs/demo_vector/tweets/suggest_res mvsLocation=file:///mvs_dir mvsMatchLayers=world_continents,world_countries,world_states_provinces
2つのデータ・セットに対して空間結合ジョブを実行するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job. SpatialJoin [generic options]
inputList={
{
( indexName=<dataset1_spatial_index_name> indexMetadataDir=<dataset1_spatial_index_metadata_dir_path> )
|
( input=<dataset1_path|comma_separated_paths|path_pattern> inputFormat=<dataset1_InputFormat_subclass> recordInfoProvider=<dataset1_RecordInfoProvider_subclass> )
[boundaries=<min_x,min_y,max_x,max_y>]
}
{
(indexName=<dataset2_spatial_index_name> indexMetadataDir=<dataset2_spatial_index_metadata_dir_path>
)
|
( input=<dataset2_path|comma_separated_paths|path_pattern> inputFormat=<dataset2_InputFormat_subclass> recordInfoProvider=<dataset2_RecordInfoProvider_subclass>
)
[boundaries=<min_x,min_y,max_x,max_y>]
}
} output=<path>[srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] boundaries=<min_x,min_y,max_x,max_y> spatialOperation=<AnyInteract|IsInside|WithinDistance> [distance=<double_value>] [samplingRatio=<decimal_value_between_0_and_1> | partitioningResult=<path>]
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.SpatialJoinをoracle.spatial.hadoop.vector.mapreduce.job.SpatialJoinに置き換えます。
InputList: 2つの入力データ・セットのリスト。このリストは、中カッコ({})で囲まれます。各リスト要素は、中カッコで囲まれた入力データ・セットです。入力データ・セットには、データ・セットを空間索引として指定するかどうかに応じて、次の情報が含まれます。
空間索引として指定される場合:
indexName: 既存の空間索引の名前。
indexMetadataDir : 空間索引メタデータが配置されるディレクトリ
空間索引として指定されない場合:
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。(indexNameが指定されている場合は無視されます。)
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。(indexNameが指定されている場合は無視されます。)
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。(indexNameが指定されている場合は無視されます。)
output: 結果の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
boundaries (オプション、デフォルト=unbounded): minX,minY,maxX,maxYの形式でカンマ区切りの値として表される各次元の最小値および最大値
spatialOperation: 入力データ・セットと階層データ・セットの間で実行する空間操作。使用可能な値は、IsInsideおよびAnyInteractです。
distance: WithinDistance操作に使用される距離。
パーティション化の引数:
samplingRatio (オプション、デフォルト=0.1): パーティション化を実行する必要がある場合にデータ・セットをサンプリングするために使用される比率
partitioningResult (オプション、デフォルト=none): 前に生成されたパーティション化結果ファイルへのパス
例: 2つのデータ・セットに対して空間結合を実行します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.SpatialJoin inputList="{{input=/user/hdfs/demo_vector/world_countries.json inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider} {input=file="/user/hdfs/demo_vector/tweets/part*” inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider}}" output=/user/hdfs/demo_vector/spatial_join srid=8307 spatialOperation=AnyInteract boundaries=-180,-90,180,90
空間パーティション化を実行するには、次の形式のコマンドを使用します。
hadoop jar <HADOOP_LIB_PATH >/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job. SpatialJoin [generic options]
inputList={
{
( indexName=<dataset1_spatial_index_name> indexMetadataDir=<dataset1_spatial_index_metadata_dir_path> )
|
( input=<dataset1_path|comma_separated_paths|path_pattern> inputFormat=<dataset1_InputFormat_subclass> recordInfoProvider=<dataset1_RecordInfoProvider_subclass> )
[boundaries=<min_x,min_y,max_x,max_y>]
}
[
{
(indexName=<dataset2_spatial_index_name> indexMetadataDir=<dataset2_spatial_index_metadata_dir_path>
)
|
( input=<dataset2_path|comma_separated_paths|path_pattern> inputFormat=<dataset2_InputFormat_subclass> recordInfoProvider=<dataset2_RecordInfoProvider_subclass>
)
[boundaries=<min_x,min_y,max_x,max_y>]
}
……
{
(indexName=<datasetN_spatial_index_name> indexMetadataDir=<datasetN_spatial_index_metadata_dir_path>
)
|
( input=<datasetN_path|comma_separated_paths|path_pattern> inputFormat=<datasetN_InputFormat_subclass> recordInfoProvider=<datasetN_RecordInfoProvider_subclass>
)
[boundaries=<min_x,min_y,max_x,max_y>]
}
}
] output=<path>[srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] boundaries=<min_x,min_y,max_x,max_y> [samplingRatio=<decimal_value_between_0_and_1>]
新しいHadoop API形式を使用するには、oracle.spatial.hadoop.vector.mapred.job.Partitioningをoracle.spatial.hadoop.vector.mapreduce.job.Partitioningに置き換えます。
InputList: 2つの入力データ・セットのリスト。このリストは、中カッコ({})で囲まれます。各リスト要素は、中カッコで囲まれた入力データ・セットです。入力データ・セットには、データ・セットを空間索引として指定するかどうかに応じて、次の情報が含まれます。
空間索引として指定される場合:
indexName: 既存の空間索引の名前。
indexMetadataDir : 空間索引メタデータが配置されるディレクトリ
空間索引として指定されない場合:
input : 入力データの場所。これは、パス、カンマ区切りのパスのリスト、または正規表現として表すことができます。(indexNameが指定されている場合は無視されます。)
inputFormat: 入力データを読み取るために使用されるinputFormatクラス実装。(indexNameが指定されている場合は無視されます。)
recordInfoProvider: InputFormatクラスによって読み取られたレコードから情報を抽出するために使用されるrecordInfoProvider実装。(indexNameが指定されている場合は無視されます。)
output: 結果の格納先のパス
空間引数:
srid (オプション、デフォルト=0): 空間データの空間参照システム(座標系) ID。
geodetic (オプション、デフォルトはSRIDによって異なります): ジオメトリが測地であるかどうかを示すブール値。
tolerance (オプション、デフォルト=0.0): 空間操作の実行時に使用される許容差を表すdouble値。
boundaries (オプション、デフォルト=unbounded): minX,minY,maxX,maxYの形式でカンマ区切りの値として表される各次元の最小値および最大値
パーティション化の引数:
samplingRatio (オプション、デフォルト=0.1): パーティション化を実行する必要がある場合にデータ・セットをサンプリングするために使用される比率
例: 2つのデータ・セットをパーティション化します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector.jar oracle.spatial.hadoop.vector.mapred.job.Partitioning inputList="{{input=/user/hdfs/demo_vector/world_countries.json inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider} {input=file="/user/hdfs/demo_vector/tweets/part*” inputFormat=oracle.spatial.hadoop.vector.geojson.mapred.GeoJsonInputFormat recordInfoProvider=oracle.spatial.hadoop.vector.geojson.GeoJsonRecordInfoProvider}}" output=/user/hdfs/demo_vector/partitioning srid=8307 boundaries=-180,-90,180,90
inputListパラメータを使用してコマンド・ライン・インタフェースを介してVectorジョブに対して複数の入力データ・セットを指定できます。inputListパラメータ値は、入力データ・セットのグループです。inputListパラメータの形式は、次のとおりです。
inputList={ {input_data_set_1_params} {input_data_set_2_params} … {input_data_set_N_params} }
各入力データ・セットとして使用可能なのは、次の入力データ・セットのいずれかです。
非ファイル入力データ・セット: inputFormat=<InputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass> [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>]
ファイル入力データ・セット: input=<path|comma_separated_paths|path_pattern> inputFormat=<FileInputFormat_subclass> recordInfoProvider=<RecordInfoProvider_subclass> [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>]
空間索引入力データ・セット: ( ( indexName=<<indexName>> [indexMetadataDir=<<path>>]) | ( isInputIndex=<true> input=<path|comma_separated_paths|path_pattern> ) ) [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>]
NoSQL入力データ・セット: kvStore=<kv store name> kvStoreHosts=<comma separated list of hosts> kvParentKey=<parent key> [kvConsistency=<Absolute|NoneRequired|NoneRequiredNoMaster>] [kvBatchSize=<integer value>] [kvDepth=<CHILDREN_ONLY|DESCENDANTS_ONLY|PARENT_AND_CHILDREN|PARENT_AND_DESCENDANTS>] [kvFormatterClass=<fully qualified class name>] [kvSecurity=<properties file path>] [kvTimeOut=<long value>] [kvDefaultEntryProcessor=<fully qualified class name>] [kvEntryGrouper=<fully qualified class name>] [ kvResultEntries={ { minor key 1: a minor key name relative to the major key [fully qualified class name: a subclass of NoSQLEntryProcessor class used to process the entry with the given key] } * } ] [srid=<integer_value>] [geodetic=<true|false>] [tolerance=<double_value>] [boundaries=<min_x,min_y,max_x,max_y>]
注意:
カテゴリ化ジョブは、複数の入力データ・セットをサポートしていません。
SpatialJoinジョブは、2つの入力データ・セットのみをサポートしています。
SpatialIndexingジョブは、空間索引タイプの入力データ・セットを受け入れません。
NoSQL入力データ・セットを使用できるのは、クラスパス内にkvstore.jarが存在する場合のみです。