この章では、ビッグ・データ環境での空間データのロード、格納、アクセス、および使用に関する概念と使用状況の情報について説明します。
空間データは、実際の空間または地理情報システム(GIS)やその他の位置情報アプリケーション上の概念的な空間に関連する実際、または概念的なオブジェクトの位置特性を表します。
Oracle Big Data Spatial and Graphの機能では、位置情報に基づく意思決定のために、空間データを迅速かつ効率的に格納、アクセス、および分析できます。
この機能を使用して、特定の位置の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環境にロードします。ラスター空間データでは、次の基本操作を実行できます。
モザイク: 複数のラスター・イメージを組み合せて単一のモザイク・イメージを作成します。
サブセット: 個々のイメージに対してサブセット操作を実行します。
この機能は、ラスター分析操作のためのMapReduceフレームワークをサポートしています。ユーザーは、ラスター・データの代数関数などの独自のラスター操作をカスタムで構築できます。たとえば、地形など、数値標高モデルや空間的表面の3次元の表現の各基盤の傾斜を計算します。詳細は、「ラスター・データ処理のためのOracle Big Data Spatial Hadoop Image Processing Framework」を参照してください。
この機能は、空間ベクトル・データの処理をサポートしています。
Hadoop HDFS環境へのロードおよび格納
デカルトまたは測地データとして格納
格納された空間ベクトル・データは次の問合せ操作などの実行に使用されます。
ポイントインポリゴン
距離計算
ANYINTERACT
バッファ作成
空間ベクトル・データでは、2つの異なるデータ・サービス操作がサポートされています。
データ・エンリッチメント
データ・カテゴリ化
また、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ジョブで表されます。また、Image Server Webアプリケーションを使用してイメージをロードおよび処理し、Java APIを使用してフレームワークの機能を公開できます。
インストールと構成について詳しくは、次を参照してください。
Image Loaderは、特定のイメージまたはイメージ・グループをHDFSにロードするHadoopジョブの1つです。
イメージはインポート中、HDFSブロックとして四角形処理され、格納されます。
GDALはイメージの四角形処理に使用されます。
それぞれの四角形は個々のマッパーによってロードされるため、並列で読み取られ、高速になります。
それぞれの四角形は一定のバイト数(ユーザー入力)が重なっているため、隣接する四角形の領域にかかっています。
MapReduceジョブでは、それぞれの四角形の情報をロードするマッパーを使用します。マッパーの数は、四角形の数、イメージ解像度、およびブロック・サイズに応じて'n'個になります。
イメージごとのリデュース・フェーズでは、マッパーによってロードされた情報をすべてまとめ、そのイメージを解像度、帯域、オフセット、イメージ・データを含む特別な.ohif
形式で格納します。これにより、それぞれの四角形を含むファイル・オフセットとノード場所が明らかになります。
それぞれの四角形には、各帯域の情報が含まれます。これは、一部の四角形のみを処理し、それに対応するブロックのみをロードする場合に役立ちます。
次の図はImage Loaderの処理を示しています。
Image Processorは、ユーザー入力に基づいて処理対象の四角形をフィルタ処理し、並列処理によって新しい1つのイメージを作成するためのHadoopジョブです。
ユーザーが識別した特定のイメージの四角形を処理します。識別できる処理クラスは1つ、ゼロ、または複数です。処理クラスの実行後、モザイク操作を実行し、ピクセルを調整してユーザーが要求した最終的な出力形式にします。
マッパーは、データのローカル性を保ちながら、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>]
説明:
SOURCE_IMGS_PATH
はソース・イメージまたはフォルダのパスです。入力が複数の場合はカンマで区切ります。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。HDFS_OUTPUT_FOLDER
はロードしたイメージを格納するHDFS出力フォルダです。OVERLAPPING_PIXELS
はそれぞれの四角形の境界線上で重なるピクセルの任意の数であり、このパラメータが指定されていない場合、重なっている2つのピクセルのデフォルトが使用されます。GDAL_LIB_PATH
はGDALライブラリの場所を示すパスです。GDAL_DATA_PATH
はGDALデータ・フォルダの場所を示すパスです。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。THUMBNAIL_PATH
はロードしたイメージのサムネイルを格納する任意のパスです。NFSを介してクラスタ内のすべてにアクセスでき、Yarnユーザーの書込みアクセス権のあるパスを指定する必要があります。たとえば、次のコマンドでは、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
リデューサは、入力イメージごとに2つの出力ファイルを生成します。1つ目は、ソース・イメージのすべての四角形を集める.ohif
ファイルであり、それぞれの四角形は処理マッパーによって別のインスタンスとして処理されます。四角形は内部でHDFSブロックとして格納されます。ブロックは複数のノードに配置され、1つのノードには特定の.ohif
ファイルのブロックが1つ以上含まれます。.ohif
ファイルは/user/<USER_EXECUTING_JOB>/OUT_FOLDER/<PARENT_DIRECTORIES_OF_SOURCE_RASTER>
フォルダのユーザーが指定したフォルダで、-outフラグを付けて格納され、ファイルは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
の指定に基づいて情報が読み取られ、ユーザーが指定した帯域のみを選択するようフィルタ処理され、地図操作、および(要求に定義されていれば)処理クラスのリストが実行されます。
それぞれのマッパー処理は、データがあるノードで実行されます。地図代数演算および処理クラスが実行されると、最終プロセスによってモザイク操作が実行されます。モザイク操作では、すべての四角形から出力に適合するピクセルのみを選択し、必要に応じて解像度を変更してモザイク出力に追加します。その結果のバイト数は、ImageBandWritable
型に含まれるコンテキストに設定されます。
1つのリデューサで複数の四角形を選択し、それをまとめます。ユーザーがHDFS出力を選択すると、ImageLoaderが呼び出され、結果がHDFSに格納されます。それ以外の場合、イメージはデフォルトでGDALによって用意され、ファイル・システム(NFS)に格納されます。
次の入力パラメータをHadoopコマンドに指定します。
hadoop jar /opt/oracle/oracle-spatial-graph/spatial/raster/jlib/hadoop-imageprocessor.jar -catalog <IMAGE_CATALOG_PATH> -config <MOSAIC_CONFIG_PATH> [-usrlib <USER_PROCESS_JAR_PATH>] [-thumbnail <THUMBNAIL_PATH>] -gdal <GDAL_LIBRARIES_PATH> -gdalData <GDAL_DATA_PATH>
説明:
IMAGE_CATALOG_PATH
は、処理対象のHDFSイメージをリストするカタログxmlへのパスです。MOSAIC_CONFIG_PATH
は、出力モザイクの機能を定義するモザイク構成xmlへのパスです。USER_PROCESS_JAR_PATH
は任意のユーザー定義jarファイルであり、ソース・イメージに適用される追加の処理クラスが含まれています。 THUMBNAIL_PATH
はロードしたイメージのサムネイル作成を有効化するための任意のフラグです。このパスは、クラスタ内のすべてのノードへのNFSを介してアクセスし、HDFS出力の場合のみ有効です。GDAL_LIBRARIES_PATH
はGDALライブラリの場所を示すパスです。GDAL_DATA_PATH
はGDALデータ・フォルダの場所を示すパスです。NFSを介してクラスタ内のすべてにアクセスできるパスを指定する必要があります。たとえば、次のコマンドは、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> -<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"/> <nodata>#000000</nodata> <pixelType>1</pixelType> </output> -<crop> -<transform> 356958.985610072,280.38843650364862,0,2458324.0825054757,0,-280.38843650364862 </transform> </crop> -<process> -<class>oracle.spatial.imageporcessor.hadoop.process.ImageSlope </class> </process> <operations> <localif operator="<" operand="3" newvalue="6"/> <localadd arg="5"/> <localsqrt/> <localround/> </operations> </mosaic>
<mosaic>
要素は処理出力の仕様を定義します。
<output>
要素は出力に使用される<SRID>などの機能を定義します。異なるSRIDのすべてのイメージは、モザイクSRIDに変換され、その四角形がモザイクに適合するかどうかが判断されます。
<directory>
要素は出力の場所を定義します。これは、タグの型で指定される、通常のファイルシステム(FS)またはHDFSのいずれかです。
<tempFsFolder>
要素はモザイク出力を一時的に格納するパスを設定します。
<filename>
および<format>
要素は出力ファイル名を指定します。
<width>
および<height>
要素はモザイク出力の解像度を設定します。
<algorithm>
要素はイメージの順序アルゴリズムを設定します。1はソースの最終変更日付順、2はイメージ・サイズ順を示します。順序タグは昇順モードまたは降順モードを表します。
<bands>
要素は出力モザイクの帯域数を指定します。この数より帯域の少ないイメージは破棄されます。
<nodata>
要素は、値のないモザイク出力のすべてのピクセルのうち、最初の3帯域の色を指定します。
<pixelType>
要素はモザイク出力のピクセル・タイプを設定します。同じピクセル・サイズのないソース・イメージは処理段階で破棄されます。
<crop>
要素は、モザイク出力に含まれる座標を、startcoordinateX
、pixelXWidth
、RotationX
、startcoordinateY
、RotationY
、pixelheightY
の順に定義します。
<process>
要素はモザイク操作の前に実行するクラスをすべてリストします。この例では、傾斜の計算が適用されており、数値標高モデル(DEM)ファイルの32ビット・イメージにのみ有効です。
<operations>
要素は、この要求で処理される地図代数演算をすべてリストします。
その他のユーザー作成処理クラスを指定できます。処理クラスが定義されていない場合は、モザイク操作のみ実行されます。
ジョブの最初のステップは、モザイクに適合する四角形をフィルタ処理することです。最初に、四角形のメタデータを保持している位置ファイルがInputFormat
に送信されます。
pixelType
を抽出すると、フィルタにより、関連するソース・イメージが処理に有効かどうかが判別されます。カタログxmlで作成したユーザー定義に基づき、次のいずれかが実行されます。
イメージが処理に有効な場合、次にSRIDが評価されます
ユーザー定義と異なる場合、すべての四角形のMBR座標がユーザーSRIDに変換され、評価されます。
この方法では、すべての四角形がモザイク定義と交差するかどうかが評価されます。交差している四角形のみが選択され、それぞれの分割が作成されます。
マッパーでは、格納先のノードでそれぞれの分割が処理されます。マッパーでは、ユーザーが定義した地図代数演算および処理クラスが順に実行され、次にモザイク処理が実行されます。1つのリデューサによってマッパーの結果がまとめられ、ユーザーの要求に応じてイメージがFSまたはHDFSに格納されます。ユーザーの要求がHDFSへの出力の格納の場合、ImageLoader
ジョブが起動され、イメージが.ohif
ファイルとして格納されます。
デフォルトでは、マッパーとリデューサは2GBのJVMを取得できるよう構成されていますが、この設定、またはその他の構成プロパティは、コマンドを実行する同じフォルダの場所で、imagejob.prop
プロパティ・ファイルを追加することによってオーバーライドできます。
カタログXMLで指定した処理クラスは、ジョブで正しく処理できるように、次の一連のルールを遵守している必要があります。すべての処理クラスにImageProcessorInterface
が実装されている必要があります。
処理クラスを実装するには、そのオブジェクト表現ImageBandWritable
を使用してラスターを操作する必要があります。処理クラスの例はフレームワークで提供され、DEMの傾斜を計算できます。関数によってピクセル値を別の値に変換する場合などは、マッピング操作を作成できます。ImageBandWritable
インスタンスは、解像度、サイズ、ピクセルなど、四角形のコンテンツを定義します。これらの値は、四角形の定義を作成するプロパティに反映する必要があります。モザイク出力の整合性は、これらのプロパティの操作が正しいかどうかによって決まります。
ImageBandWritable
インスタンスは、解像度、サイズ、ピクセルなど、四角形のコンテンツを定義します。これらの値は、四角形の定義を作成するプロパティに反映する必要があります。モザイク出力の整合性は、これらのプロパティの操作が正しいかどうかによって決まります。
表2-1 ImageBandWritableプロパティ
|
処理クラスおよびメソッド
四角形のピクセルを変更する場合は、次のメソッドを使用して、最初に帯域情報を配列に取り込みます。
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);
ここでは、帯域はピクセル情報を含むバイト数または浮動小数点の配列です。処理操作の結果、影響を受けるインスタンス・サイズ、データ型、bytesNumberおよびその他のプロパティを必ず更新してください。各プロパティには、セッターを使用できます。
ローカル地図代数演算は入力ラスター上で処理でき、そこではピクセル数が操作に応じて変更されます。構成XMLの操作の順序によって、処理される操作の順序が決まります。すべての地図代数演算が処理されると、処理クラスが実行され、最後にモザイク操作が実行されます。
次の地図代数演算はモザイク構成XMLの<operations>
要素に追加でき、演算名を要素名として使用できます。
localnot
: 各ピクセルの否定を取得し、ビット・パターンを反転します。結果が負の値でデータ型が符号なしの場合、NODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
|locallog
: ピクセルの自然対数(底e)を返します。結果がNaNの場合は元のピクセル値が設定され、結果が無限の場合はNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
locallog10
: ピクセルの底10の対数が返されます。結果がNaNの場合は元のピクセル値が設定され、結果が無限の場合はNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localadd
: 指定した値を引数としてピクセルに追加します。例: <localadd arg="5"/>
localdivide
: 各ピクセルの値を、引数として指定した値セットで除算します。例: <localdivide arg="5"/>
localif
: 各ピクセルの値を引数として指定した値および条件に基づいて変更します。有効な演算子: = 、<、>、>=、< !=。例: <localif operator="<" operand="3" newvalue="6"/>
、ここでは、値が3未満のピクセルがすべて変更され、新しい値が6に設定されます。
localmultiply
: 各ピクセルの値に、引数として指定した値を乗算します。例: <localmultiply arg="5"/>
localpow
: 各ピクセルの値を、指定した引数の値のべき乗に切り上げます。例: <localpow arg="5"/>
。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localsqrt
: 各ピクセルを正しく四捨五入した正の値の平方根を返します。結果が無限またはNaNの場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localsubstract
: すべてのピクセル値から引数として指定した値を減算します。例: <localsubstract arg="5"/>
localacos
: ピクセルの逆余弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localasin
: ピクセルの逆正弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localatan
: ピクセルの逆正接を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localcos
: ピクセルの余弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localcosh
: ピクセルの逆双曲線余弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localsin
: ピクセルの正弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localtan
: ピクセルの正接を計算します。ピクセルの余弦が0の場合、このピクセルは変更されません。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localsinh
: ピクセルの逆双曲線正弦を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localtanh
: ピクセルの双曲線正接を計算します。結果がNaNの場合、NODATA値がこのピクセルに設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localdefined
: セルの値がNODATAではない場合は整数型指定のピクセルが1にマップされ、それ以外の場合は0にマップされます。
localundefined
: セルの値がNODATAではない場合は整数型指定のラスターが0にマップされ、それ以外の場合は1にマップされます。
localabs
: 符号付きピクセルの絶対値を返します。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localnegate
: 各ピクセルの値から1を引いた数を乗算します。
localceil
: ピクセル値以上であり、ある数学的整数と等しい最小値を返します。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localfloor
: ピクセル値以下であり、ある数学的整数と等しい最小値を返します。結果が無限の場合、このピクセルにNODATA値が設定されます。ラスターにNODATA値が指定されていない場合、元のピクセルが設定されます。
localround
: 各ピクセルに最も近い整数値を返します。
このフレームワークでは、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 Big Data Spatial Vector AnalysisはSpatial Vector Analysis APIであり、Hadoopジョブとして実行され、HDFSに格納されているデータの空間処理のためのMapReduceコンポーネントを提供します。これらのコンポーネントでは、Spatial Java APIを利用して空間分析タスクを実行します。このAPIには、Webコンソールも用意されています。サポートされている機能は次のとおりです。
また、次の情報を参照し、実装について詳しく理解します。
空間の索引付けは、キー/値ペアの形式をとり、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
のサブクラスです。内部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);
InputFormat
は次のサポート対象の要件と一致している必要があります。
FileInputFormat
のサブクラスであること。
getSplits()
メソッドがFileSplit
またはCombineFileSplit
分割タイプを返すこと。
RecordReader
のgetPos()
メソッドが現在の位置を返し、空間索引のレコードをユーザー・ファイルの元のレコードにトラック・バックすること。現在の位置が返されない場合、空間索引では元のレコードが見つかりません。
ただし、空間索引は引き続き作成でき、元のレコードの読取りを必要としない操作に使用できます。たとえば、他のフィールドを追加フィールドとして追加すると、元のレコード全体を読み取る必要はありません。
注意:
それぞれの分割がgetSplits()
メソッドから返されたら、その分割に対して空間索引が作成されます。空間索引をフィルタ処理に使用する(空間のフィルタ処理)場合は、空間索引を作成したものと同じInputFormat
実装を使用して、分割索引があるかどうか確認することをお薦めします。
getPos()
メソッドはHadoopの新しいAPIから削除されていますが、org.apache.hadoop.mapreduce.lib.input.TextInputFormat
およびCombineTextInputFormat
はサポートされており、引き続きレコードの開始オフセットの取得に使用できます。
新しいAPIのその他の入力形式もサポートされていますが、レコード開始オフセットは空間索引に含まれません。このため、元のレコードは検索できません。新しいAPI入力形式の要件は、旧APIのものと同じです。ただし、新しいAPI FileInputFormat
、FileSplit
、およびCombineFileSplit
に変換する必要があります。次の例は、内部入力形式として使用される新しいHadoop APIの入力形式を示します。
CompositeInputFormat.setInternalInputFormatClass(conf, org.apache.hadoop.mapreduce.lib.input.TextInputFormat); spatialIndexing.setInputFormatClass(CompositeInputFormat.class);
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を参照してください。
MVSuggest
は、ジオメトリがなく、テキスト・フィールドのあるレコードの推定の位置を取得するための空間の索引付けに使用されます。このテキスト・フィールドはレコードの位置の特定に使用されます。MVSuggest
から返されたジオメトリが、空間索引内のレコードの包括に使用されます。
すべてのレコードについて検索テキストを含むフィールドを把握する必要があるため、RecordInfoProvider
実装では、LocalizableRecordInfoProvider
も実装する必要があります。または、検索テキストを含むフィールドの名前で、構成パラメータoracle.spatial.recordInfo.locationField
を設定できます。
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に委任されます。
次の空間フィルタ処理の相互作用の図にこれらの手順を示します。
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);
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 Analysis APIを使用したジョブ作成の実行時間を示します。ジョブは4ノードのクラスタを使用して実行されています。時間はクラスタの特性によって異なります。テスト・データセットには、10億以上のレコードがあり、サイズは1TBを超えています。
表2-2 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 and Graph Vectorコンソールを使用すると、空間索引付けおよびテーマ・マップの作成と表示に関連するタスクを実行できます。
Oracle Big Data Spatial and Graph Vectorコンソールを使用して空間索引を作成するには、次の手順を実行します。
コンソール: http://<oracle_big_data_spatial_vector_console>:8080/spatialviewer/
を開きます
「Create Index」をクリックします。
必要な詳細をすべて指定します。
索引名。
HDFSの索引へのファイルのパス。たとえば、hdfs://<server_name_to_store_index>:8020/user/myuser/twitter_logs/part-m-00000
です。
新しい索引パス: これはジョブ出力パスです。たとえば、hdfs://<oracle_big_data_spatial_vector_console>:8020/user/myuser/Twitter/index
です。
索引付けするジオメトリのSRID。例: 0.5
索引付けするジオメトリの許容差。例: 8307
索引付けするジオメトリが測地かどうか。
入力形式クラス: 入力形式のクラス。たとえば、org.apache.hadoop.mapred.TextInputFormat
です
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。たとえば、oracle.spatial.hadoop.vector.geojson. GeoJsonRecordInfoProvider
です。
注意:
InputFormat
クラスまたはRecordInfoProvider
クラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このJARを使用可能にするには、ユーザーはこれを$JETTY_HOME/webapps/spatialviewer/WEB-INF/lib
ディレクトリに追加し、サーバーを再起動する必要があります。
MVSuggestサービスを使用する必要があるかどうか。ジオメトリを場所の文字列から検出する場合は、MVSuggestサービスを使用します。この場合、指定されたRecordInfoProvider
がインタフェースoracle.spatial.hadoop.vector. LocalizableRecordInfoProvider
を実装します。
MVSuggestサービスURL (オプション): ジオメトリを場所の文字列から検出する場合は、MVSuggestサービスを使用します。サービスURLがローカルホストの場合、各データ・ノードでMVSuggestアプリケーションを起動し、実行している必要があります。この場合、新しい索引には、MVSuggestによって各レコードに提供された点ジオメトリとレイヤーが含まれます。ジオメトリがポリゴンの場合、そのジオメトリはポリゴンの重心です。例: http://localhost:8080
MVSuggestテンプレート(オプション): MVSuggestサービスを使用する場合、ユーザーは索引の作成に使用するテンプレートを定義できます。
結果通知の送信先電子メール(オプション): ジョブが完了したときに通知を受信する電子メールIDを指定します。電子メールIDが複数ある場合はセミコロンで区切ります。たとえば、mymail@example.com
です
「Create」をクリックします。
発行したジョブがリストされるので、ジョブ完了を示す電子メールを受信するまで待ちます。
索引付き空間データを検索するには、次の手順を実行します。
コンソール: http://<oracle_big_data_spatial_vector_console>:8080/spatialviewer/
を開きます
「Edplore Data」をクリックします。
たとえば、次のことが可能です。
必要な索引付きデータを選択し、「Refresh Map」をクリックして地図上にデータを表示します。
背景地図のスタイルを変更します。
実際のデータ・ズームのレベルを変更します。
ヒート・マップを使用してデータを表示します。
カテゴリ化ジョブは空間索引の有無に関係なく実行できます。次の手順を実行します。
http://<oracle_big_data_spatial_vector_console>:8080/spatialviewer/
を開きます。
「Categorization」をクリックし、次に「Run Job」をクリックします。
「With Index」または「Without Index」のいずれかを選択し、必要に応じて次の詳細を入力します。
With Index
索引名
Without Index
データのパス: HDFSデータ・パスを入力します。たとえば、hdfs://<oracle_big_data_spatial_vector_console>:8020/user/*/data
です。
ユーザー・クラスのあるJAR (オプション): InputFormat
クラスまたはRecordInfoProvider
クラスがAPI、またはHadoop APIクラスにない場合、ユーザー定義クラスのJARが提供されます。このJARを使用可能にするには、ユーザーはこれを$JETTY_HOME/webapps/spatialviewer/WEB-INF/lib
ディレクトリに追加し、サーバーを再起動する必要があります。
入力形式クラス: 入力形式のクラス。たとえば、org.apache.hadoop.mapred.TextInputFormat
です
レコード情報プロバイダ・クラス: 空間情報を提供するクラス。たとえば、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ジョブ出力パス。例: hdfs://<oracle_big_data_spatial_vector_console>:8020/user/myuser/Twitter/myoutput
結果名: 結果の名前。同じ名前の結果がテンプレートにある場合は上書きされます。たとえば、「Tweets test」などです。
結果通知の送信先電子メール(オプション): ジョブが完了したときに通知を受信する電子メールIDを指定します。電子メールIDが複数ある場合はセミコロンで区切ります。たとえば、mymail@abccorp.com
です。
結果ファイルを作成したり、ローカルに格納されている結果ファイルをアップロードしたりできます。たとえば、コマンドラインから実行したジョブによって作成された結果ファイルなどです。テンプレートはフォルダ$JETTY_HOME/webapps/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}
を含むファイルになります
新しいテンプレートを作成するには、次の手順を実行します。
$JETTY_HOME/webapps/spatialviewer/templates/
に追加します。$JETTY_HOME/webapps/spatialviewer/templates/_config_
に追加します。テンプレートを削除するには、ステップ1と2で追加したJSONファイルおよび構成ファイルを削除します。
各テンプレートには構成ファイルがあります。テンプレート構成ファイルはフォルダ$JETTY_HOME/webapps/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]
次のコマンドを実行して索引を作成します。
hadoop jar <HADOOP_LIB_PATH>/<jarfile> oracle.spatial.hadoop.vector.demo.job.SpatialIndexing <DATA_PATH> <SPATIAL_INDEX_PATH> <INPUT_FORMAT_CLASS> <RECORD_INFO_PROVIDER_CLASS>
説明
jarfile
は空間索引付けでユーザーが指定するjarファイルです。
DATA_PATH
は索引付けるデータの場所です。
SPATIAL_INDEX_PATH
は結果として生じる空間索引の場所です。
INPUT_FORMAT_CLASS
はデータの読取りに使用するInputFormat
実装です。
RECORD_INFO_PROVIDER_CLASS
はレコードからの情報の抽出に使用する実装です。
次の例では、コマンドラインを使用して索引を作成します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.SpatialIndexing "/user/hdfs/demo_vector/tweets/part*" /user/hdfs/demo_vector/tweets/spatial_index org.apache.hadoop.mapred.TextInputFormat oracle.spatial.hadoop.vector.demo.usr.TwitterLogRecordInfoProvider
注意:
前の例では、事前ロードされたデモ・ジョブを使用しています。
次のコマンドを実行して空間フィルタ処理を実行します。
hadoop jar HADOOP_LIB_PATH/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.TwitterLogSearch <DATA_PATH> <RESULT_PATH> <SEARCH_TEXT> <SPATIAL_INTERACTION> <GEOMETRY> <SRID> <TOLERANCE> <GEODETIC> <SPATIAL_INDEX_PATH>
説明
DATA_PATH
はフィルタ処理するデータです。
RESULT_PATH
は結果が生成される場所を示すパスです。
SEARCH_TEXT
は検索対象のテキストです。
SPATIAL_INTERACTION
は空間の相互作用のタイプです。これは1 (内部)または2 (任意の相互作用)のいずれかです。
GEOMETRY
は空間フィルタ処理の実行に使用するジオメトリです。これはJSON形式で表現されます。
SRID
は問合せジオメトリのSRS IDです。
TOLERANCE
は空間検索に使用する許容差です。
GEODETIC
はジオメトリが測地かどうかを指定します。
SPATIAL_INDEX_PATH
は事前に生成された空間索引へのパスです。
次の例では、一部のテキストを含み、指定のジオメトリと相互作用しているすべてのツイートのカウントを示します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.TwitterLogSearch "/user/hdfs/demo_vector/tweets/part*" /user/hdfs/demo_vector/tweets/text_search feel 2 '{"type":"Polygon", "coordinates":[[-106.64595, 25.83997, -106.64595, 36.50061, -93.51001, 36.50061, -93.51001, 25.83997, -106.64595, 25.83997]]}' 8307 0.0 true /user/hdfs/demo_vector/tweets/spatial_index
注意:
前の例では、事前ロードされたデモ・ジョブを使用しています。
次のコマンドを実行して階層結果を作成します。
hadoop jar HADOOP_LIB_PATH/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.HierarchicalCount spatial <SPATIAL_INDEX_PATH> <RESULT_PATH> <HIERARCHY_INFO_CLASS> <SPATIAL_INTERACTION> <SRID> <TOLERANCE> <GEODETIC> <HIERARCHY_DATA_INDEX_PATH> <HIERARCHY_DATA_PATHS>
説明
SPATIAL_INDEX_PATH
は事前に生成された空間索引へのパスです。このパスに空間索引パス・ファイル以外のファイル(たとえば、Hadoop生成の_SUCCESSファイルなど)がある場合、次のパターンSPATIAL_INDEX_PATH/part*/data
を追加します。
RESULT_PATH
は結果が生成される場所を示すパスです。各階層レベルには、XXXX_count.json
という名前のファイルが必要です。
HIERARCHY_INFO_CLASS
は結果として生じる空間索引の場所です。
INPUT_FORMAT_CLASS
はHierarchyInfo
実装です。現在の階層データの構造を定義します。
SPATIAL_INTERACTION,SRID,TOLERANCE,GEODETIC
はすべて、テキスト検索ジョブの事前定義と同じものを意味します。これらはデータと階層情報ジオメトリの間の空間操作の定義に使用します。
HIERARCHY_DATA_INDEX_PATH
は階層データ索引を配置する場所を示すパスです。この索引は、毎回、親子関係が要求されたときに、その検索を回避するジョブで使用されます。
HIERARCHY_DATA_PATHS
は階層データへのパスのカンマ区切りリストです。階層索引が同じ階層データに対して事前に作成されている場合は省略できます。
次の例では、コマンドラインを使用して索引を作成します。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.HierarchicalCount spatial "/user/hdfs/demo_vector/tweets/spatial_index/part*/data" /user/hdfs/demo_vector/tweets/hier_count_spatial oracle.spatial.hadoop.vector.demo.usr.WorldAdminHierarchyInfo 1 8307 0.5 true /user/hdfs/demo_vector/world_hier_index file:///net/den00btb/scratch/hsaucedo/spatial_bda/demo/vector/catalogs/world_continents.json,file:///net/den00btb/scratch/hsaucedo/spatial_bda/demo/vector/catalogs/world_countries.json,file:///net/den00btb/scratch/hsaucedo/spatial_bda/demo/vector/catalogs/world_states_provinces.json
注意:
前の例では、事前ロードされたデモ・ジョブを使用しています。
次のコマンドを実行してバッファを生成します。
hadoop jar HADOOP_LIB_PATH/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.Buffer <DATA_PATH> <RESULT_PATH> <INPUT_FORMAT_CLASS> <RECORD_INFO_PROVIDER_CLASS> <BUFFER_WIDTH> <BUFFER_SMA> <BUFFER_FLAT> <BUFFER_ARCTOL>
説明
DATA_PATH
はフィルタ処理するデータです。
RESULT_PATH
は結果が生成される場所を示すパスです。
INPUT_FORMAT_CLASS
はデータの読取りに使用するInputFormat
実装です。
RECORD_INFO_PROVIDER_CLASS
は各レコードからのデータの抽出に使用するRecordInfoProvider
実装です。
BUFFER_WIDTH
はバッファの幅を指定します。
BUFFER_SMA
は半長径です。
BUFFER_FLAT
はバッファの平坦化です。
BUFFER_ARCTOL
は測地高密度化の円弧許容差です。
次の例では、各レコードのジオメトリを囲むバッファの生成を示します。結果として生じるファイルはMapFileであり、その各エントリは入力データのレコードに対応します。入力キーはレコードIDであり、その値は生成されたバッファおよびレコードの場所(パス、開始オフセットおよび長さ)を保持するRecordInfo
インスタンスです。
hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop/lib/sdohadoop-vector-demo.jar oracle.spatial.hadoop.vector.demo.job.Buffer "/user/hdfs/demo_vector/waterlines/part*" /user/hdfs/demo_vector/waterlines/buffers org.apache.hadoop.mapred.TextInputFormat oracle.spatial.hadoop.vector.demo.usr.WorldSampleLineRecordInfoProvider 5.0
注意:
前の例では、事前ロードされたデモ・ジョブを使用しています。
Oracle Big Data Spatial and Graph Image Serverコンソールは、「モザイクを作成するためのHDFS Hadoopクラスタへのイメージのロード」などのタスクに使用できます。