この章では、ビッグ・データ環境でのプロパティ・グラフ・データの作成、格納および操作に関する概念と使用方法の情報を提供します。
プロパティ・グラフでは、プロパティ(キー値ペア)をグラフの頂点およびエッジに簡単に関連付けることができ、大量のデータ・セット間の関係に基づく分析操作が可能になります。
プロパティ・グラフは、オブジェクトまたは頂点のセットと、これらのオブジェクトをつなぐ矢印またはエッジのセットで構成されます。頂点とエッジには複数のプロパティを含めることができ、それらはキー値ペアとして表されます。
各頂点には一意の識別子があり、次のものを含めることができます。
出力エッジのセット
入力エッジのセット
プロパティの集まり
各エッジには一意の識別子があり、次のものを含めることができます。
出力頂点
入力頂点
2つの頂点間の関係を示すテキスト・ラベル
プロパティの集まり
図5-1は、2つの頂点と1つのエッジを持つ非常に単純なプロパティ・グラフを示しています。2つの頂点には、識別子1および2があります。両方の頂点には、プロパティname
およびage
があります。エッジは、出力頂点1から入力頂点2に向かっています。このエッジは、テキスト・ラベルknows
と、頂点1と2の関係のタイプを識別するプロパティtype
で表されます。
Big Data Spatial and Graphプロパティ・グラフ・データ・モデルには標準が用意されていませんが、これはW3C標準ベースのResource Description Framework (RDF)グラフ・データ・モデルに似ています。プロパティ・グラフ・データ・モデルはRDFよりも単純であり、精密ではありません。このような相違点により、これは次のようなユースケースでよい候補になります。
ソーシャル・ネットワークでの影響の特定
トレンドおよび顧客行動の予測
パターン一致に基づく関係の発見
キャンペーンをカスタマイズするためのクラスタの特定
注意:
データベース側でOracleがサポートしているプロパティ・グラフ・データ・モデルでは、頂点にラベルを使用することはできません。ただし、「頂点のラベルの指定」で説明されているように、指定した頂点プロパティの値を1つ以上のラベルとして扱うことができます。
プロパティ・グラフは、HadoopおよびOracle NoSQL Databaseのビッグ・データに対してサポートされます。このサポートは、データ・アクセス・レイヤーと分析レイヤーで構成されます。Hadoopでのデータベースの選択肢により、スケーラブルで一貫したストレージ管理が提供されます。
図5-2は、Oracleプロパティ・グラフのアーキテクチャを示しています。
インメモリー・アナリスト・レイヤーでは、パラレル・インメモリー実行を使用してプロパティ・グループを分析できます。これは、パス計算、ランキング、コミュニティ検出、推奨ムを含む、35を超える分析機能を提供します。
データ・アクセス・レイヤーは、プロパティ・グラフの作成および削除、頂点とエッジの追加および削除、キー値ペアを使用した頂点とエッジの検索、テキスト索引の作成、およびその他の操作の実行に使用できる、Java APIのセットを提供します。Java APIには、プロパティ・グラフ・データ・モデル用のTinkerPop Blueprintsグラフ・インタフェースの実装が含まれています。また、これらのAPIは、広く普及しているオープンソースのテキスト索引付けおよび検索エンジンであるApache LuceneおよびApache SolrCloudと統合されています。
プロパティ・グラフは、Oracle NoSQL DatabaseまたはApache HBaseのいずれかに格納できます。これらのデータベースは両方とも成熟しており、スケーラブルで、効率的なナビゲーション、問合せおよび分析をサポートします。両方とも、プロパティ・グラフの頂点およびエッジをモデル化するために表を使用します。
次のグラフ形式がサポートされます。
GraphMLファイル形式では、XMLを使用してグラフを記述します。例5-1は、図5-1に示されているプロパティ・グラフのGraphMLの記述を示しています。
例5-1 単純なプロパティ・グラフのGraphMLの記述
<?xml version="1.0" encoding="UTF-8"?> <graphml xmlns="http://graphml.graphdrawing.org/xmlns"> <key id="name" for="node" attr.name="name" attr.type="string"/> <key id="age" for="node" attr.name="age" attr.type="int"/> <key id="type" for="edge" attr.name="type" attr.type="string"/> <graph id="PG" edgedefault="directed"> <node id="1"> <data key="name">Alice</data> <data key="age">31</data> </node> <node id="2"> <data key="name">Bob</data> <data key="age">27</data> </node> <edge id="3" source="1" target="2" label="knows"> <data key="type">friends</data> </edge> </graph> </graphml>
GraphSONファイル形式では、JavaScript Object Notation (JSON)に基づいてグラフを記述します。例5-2は、図5-1に示されているプロパティ・グラフのGraphSONの記述を示しています。
関連項目:
『GraphSON Reader and Writer Library』
https://github.com/tinkerpop/blueprints/wiki/GraphSON-Reader-and-Writer-Library
例5-2 単純なプロパティ・グラフのGraphSONの記述
{ "graph": { "mode":"NORMAL", "vertices": [ { "name": "Alice", "age": 31, "_id": "1", "_type": "vertex" }, { "name": "Bob", "age": 27, "_id": "2", "_type": "vertex" } ], "edges": [ { "type": "friends", "_id": "3", "_type": "edge", "_outV": "1", "_inV": "2", "_label": "knows" } ] } }
Graph Modeling Language (GML)ファイル形式では、ASCIIを使用してグラフを記述します。例5-3は、図5-1に示されているプロパティ・グラフのGMLの記述を示しています。
関連項目:
『GML: A Portable Graph File Format』、Michael Himsolt著
例5-3 単純なプロパティ・グラフのGMLの記述
graph [ comment "Simple property graph" directed 1 IsPlanar 1 node [ id 1 label "1" name "Alice" age 31 ] node [ id 2 label "2" name "Bob" age 27 ] edge [ source 1 target 2 label "knows" type "friends" ] ]
Oracleフラット・ファイル形式はプロパティ・グラフのみを記述します。これは、その他のファイル形式よりも正確で、より優れたデータ型サポートを提供します。Oracleフラット・ファイル形式は、グラフを記述するために、頂点用とエッジ用にそれぞれ1つずつ、2つのファイルを使用します。レコードのフィールドはカンマで区切られます。
例5-4は、図5-1に示されているプロパティ・グラフを記述するOracleフラット・ファイルを示しています。
例5-4 単純なプロパティ・グラフのOracleフラット・ファイルの記述
頂点ファイル:
1,name,1,Alice,, 1,age,2,,31, 2,name,1,Bob,, 2,age,2,,27,
エッジ・ファイル:
1,1,2,knows,type,1,friends,,
プロパティ・グラフの作成には、Java APIを使用したプロパティ・グラフとそのオブジェクトの作成が含まれます。
プロパティ・グラフで使用できるJava APIには、次のものが含まれます。
Oracle Big Data Spatial and Graphのプロパティ・グラフ・サポートは、Apache HBaseおよびOracle NoSQL Database用のデータベース固有のAPIを提供します。データ・アクセス・レイヤーAPI (oracle.pg.*
)は、Oracle NoSQL DatabaseおよびApache HBaseに格納されているプロパティ・グラフ用のTinkerPop Blueprints API、テキスト検索および索引付けを実装します。
Oracle Big Data Spatial and Graph APIを使用するには、次のクラスをJavaプログラムにインポートします。
import oracle.pg.nosql.*; // or oracle.pg.hbase.*
import oracle.pgx.config.*;
import oracle.pgx.common.types.*;
TinkerPop Blueprints Java APIも含めます。
関連項目:
Oracle Big Data Spatial and Graph Java APIリファレンス
TinkerPop Blueprintsはプロパティ・グラフ・データ・モデルをサポートします。このAPIは、主にBig Data Spatial and Graphのデータ・アクセス・レイヤーJava APIを介して使用する、グラフ操作のためのユーティリティを提供します。
Blueprints APIを使用するには、次のクラスをJavaプログラムにインポートします。
import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.Edge;
関連項目:
『Blueprints: A Property Graph Model Interface API』
http://www.tinkerpop.com/docs/javadocs/blueprints/2.3.0/index.html
Apache Hadoop Java APIを使用すると、JavaコードをHadoop分散フレームワーク内で実行するMapReduceプログラムとして作成できます。
Hadoop Java APIを使用するには、次のクラスをJavaプログラムにインポートします。次に例を示します。
import org.apache.hadoop.conf.Configuration;
The Oracle NoSQL Database APIを使用すると、キー値(KV)ストアを作成および移入し、Hadoop、HiveおよびOracle NoSQL Databaseへのインタフェースを提供できます。
Oracle NoSQL Databaseをグラフ・データ・ストアとして使用するには、次のクラスをJavaプログラムにインポートします。次に例を示します。
import oracle.kv.*; import oracle.kv.table.TableOperation;
Apache HBase APIを使用すると、キー値ペアを作成および操作できます。
HBaseをグラフ・データ・ストアとして使用するには、次のクラスをJavaプログラムにインポートします。次に例を示します。
import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.filter.*; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.conf.Configuration;
関連項目:
『HBase 0.98.6-cdh5.3.2 API』
http://archive.cloudera.com/cdh5/cdh/5/hbase/apidocs/index.html?overview-summary.html
グラフ・データのパラレル・ロードを実行するために、Java APIが提供されています。
頂点ファイル(または入力ストリーム)のセットとエッジ・ファイル(または入力ストリーム)のセットがある場合、それらを複数のチャンクに分割し、並列でデータベースにロードできます。チャンクの数は、ユーザーが指定した並列度(DOP)によって決定されます。
並列性は、頂点およびエッジ・フラット・ファイルを複数のチャンクに分割するスプリッタ・スレッドと、別個のデータベース接続を使用して各チャンクをデータベースにロードするローダー・スレッドによって実現されます。スプリッタ・スレッドとローダー・スレッドを接続するために、Javaパイプが使用されます -- スプリッタ: PipedOutputStream
およびローダー: PipedInputStream
。
データ・ロードAPIの最も単純な使用方法は、1つのプロパティ・グラフ・インスタンス、1つの頂点ファイル、1つのエッジ・ファイルおよびDOPを指定することです。
次のロード・プロセスの例では、最適化されたOracleフラット・ファイル形式の頂点ファイルおよびエッジ・ファイルに格納されたグラフ・データをロードし、並列度48でロードを実行します。
opgdl = OraclePropertyGraphDataLoader.getInstance(); vfile = "../../data/connections.opv"; efile = "../../data/connections.ope"; opgdl.loadData(opg, vfile, efile, 48);
データ・ロードAPIを使用することにより、複数のパーティションを使用してデータをデータベースにロードできます。このAPIは、プロパティ・グラフ、頂点ファイル、エッジ・ファイル、DOP、パーティション合計数およびパーティション・オフセット(0からパーティション合計数 - 1まで)を必要とします。たとえば、2つのパーティションを使用してデータをロードするには、パーティション・オフセットは0および1である必要があります。つまり、グラフ全体をロードするために2つのデータ・ロードAPIコールがあり、これら2つのAPIコールの相違点は、パーティション・オフセット(0および1)のみになります。
次のコード・フラグメントは、4つのパーティションを使用してグラフ・データをロードします。データ・ローダーの各コールは、単一システム上または複数のシステム上の別々のJavaクライアントを使用して処理できます。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(
args, szGraphName);
int totalPartitions = 4;
int dop= 32; // degree of parallelism for each client.
String szOPVFile = "../../data/connections.opv";
String szOPEFile = "../../data/connections.ope";
SimpleLogBasedDataLoaderListenerImpl dll = SimpleLogBasedDataLoaderListenerImpl.getInstance(100 /* frequency */,
true /* Continue on error */);
// Run the data loading using 4 partitions (Each call can be run from a
// separate Java Client)
// Partition 1
OraclePropertyGraphDataLoader opgdlP1 = OraclePropertyGraphDataLoader.getInstance();
opgdlP1.loadData(opg, szOPVFile, szOPEFile, dop,
4 /* Total number of partitions, default 1 */,
0 /* Partition to load (from 0 to totalPartitions - 1, default 0 */,
dll);
// Partition 2
OraclePropertyGraphDataLoader opgdlP2 = OraclePropertyGraphDataLoader.getInstance();
opgdlP2.loadData(opg, szOPVFile, szOPEFile, dop, 4 /* Total number of partitions, default 1 */,
1 /* Partition to load (from 0 to totalPartitions - 1, default 0 */, dll);
// Partition 3
OraclePropertyGraphDataLoader opgdlP3 = OraclePropertyGraphDataLoader.getInstance();
opgdlP3.loadData(opg, szOPVFile, szOPEFile, dop, 4 /* Total number of partitions, default 1 */,
2 /* Partition to load (from 0 to totalPartitions - 1, default 0 */, dll);
// Partition 4
OraclePropertyGraphDataLoader opgdlP4 = OraclePropertyGraphDataLoader.getInstance();
opgdlP4.loadData(opg, szOPVFile, szOPEFile, dop, 4 /* Total number of partitions, default 1 */,
3 /* Partition to load (from 0 to totalPartitions - 1, default 0 */, dll);
データ・ロードAPIは、ロードされるソース頂点ファイルおよびエッジ・ファイル内のこれらの行のファインチューニングもサポートします。頂点(またはエッジ)オフセット行数と頂点(またはエッジ)最大行数を指定できます。オフセット行数から最大行数までのデータがロードされます。最大行数が-1である場合、ロード・プロセスはファイルの終わりに達するまでデータをスキャンします。
次のコード・フラグメントは、ファインチューニングを使用してグラフ・データをロードします。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(
args, szGraphName);
int totalPartitions = 4;
int dop= 32; // degree of parallelism for each client.
String szOPVFile = "../../data/connections.opv";
String szOPEFile = "../../data/connections.ope";
SimpleLogBasedDataLoaderListenerImpl dll = SimpleLogBasedDataLoaderListenerImpl.getInstance(100 /* frequency */,
true /* Continue on error */);
// Run the data loading using fine tuning
long lVertexOffsetlines = 0;
long lEdgeOffsetlines = 0;
long lVertexMaxlines = 100;
long lEdgeMaxlines = 100;
int totalPartitions = 1;
int idPartition = 0;
OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance();
opgdl.loadData(opg, szOPVFile, szOPEFile,
lVertexOffsetlines /* offset of lines to start loading
from partition, default 0*/,
lEdgeOffsetlines /* offset of lines to start loading
from partition, default 0*/,
lVertexMaxlines /* maximum number of lines to start loading
from partition, default -1 (all lines in partition)*/,
lEdgeMaxlines /* maximun number of lines to start loading
from partition, default -1 (all lines in partition)*/,
dop,
totalPartitions /* Total number of partitions, default 1 */,
idPartition /* Partition to load (from 0 to totalPartitions - 1,
default 0 */,
dll);
Oracle Big Data Spatial and Graphは、データベースへの複数の頂点ファイルおよび複数のエッジ・ファイルのロードもサポートします。指定された頂点ファイルがDOPチャンクに分割され、DOPスレッドを使用してデータベースに並列にロードされます。同様に、複数のエッジ・ファイルも分割されて、並列にロードされます。
次のコード・フラグメントは、パラレル・データ・ロードAPIを使用して、複数の頂点ファン・ファイルおよびエッジ・ファイルを並列にロードします。この例では、入力ファイルを保持するために2つの文字列配列szOPVFilesおよびszOPEFilesを使用しています。この例では1つの頂点ファイルと1つのエッジ・ファイルのみを使用していますが、これら2つの配列に複数の頂点ファイルと複数のエッジ・ファイルを指定できます。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(
args, szGraphName);
String[] szOPVFiles = new String[] {"../../data/connections.opv"};
String[] szOPEFiles = new String[] {"../../data/connections.ope"};
// Clear existing vertices/edges in the property graph
opg.clearRepository();
opg.setQueueSize(100); // 100 elements
// This object will handle parallel data loading over the property graph
OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance();
opgdl.loadData(opg, szOPVFiles, szOPEFiles, dop);
System.out.println("Total vertices: " + opg.countVertices());
System.out.println("Total edges: " + opg.countEdges());
プロパティ・グラフのパラレル問合せは、頂点(またはエッジ)のパラレル・スキャンを実行するための単純なJava APIを提供します。パラレル取得は、バックエンド・データベースとの分割間でのデータの配分を利用する最適化されたソリューションであり、各分割は別個のデータベース接続を使用して問い合せられます。
パラレル取得では、各要素が特定の分割からのすべての頂点(またはエッジ)を保持する配列が生成されます。問い合せられたシャードのサブセットは、特定の開始分割IDと指定された接続の配列のサイズによって分離されます。これにより、サブセットは[開始, 開始 - 1 + 接続の配列のサイズ]の範囲内の分割を考慮します。N分割を含む頂点表にあるすべての分割に、([0, N - 1]の範囲の)整数IDが割り当てられることに注意してください。
次のコードは、Apache HBaseを使用してプロパティ・グラフをロードし、接続の配列を開き、開いた接続を使用してパラレル問合せを実行してすべての頂点およびエッジを取得します。getVerticesPartitioned (getEdgesPartitioned)
メソッドの呼出し数は、分割の合計数と使用される接続の数によって制御されます。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create connections used in parallel query HConnection[] hConns= new HConnection[dop]; for (int i = 0; i < dop; i++) { Configuration conf_new = HBaseConfiguration.create(opg.getConfiguration()); hConns[i] = HConnectionManager.createConnection(conf_new); } long lCountV = 0; // Iterate over all the vertices’ splits to count all the vertices for (int split = 0; split < opg.getVertexTableSplits(); split += dop) { Iterable<Vertex>[] iterables = opg.getVerticesPartitioned(hConns /* Connection array */, true /* skip store to cache */, split /* starting split */); lCountV += consumeIterables(iterables); /* consume iterables using threads */ } // Count all vertices System.out.println("Vertices found using parallel query: " + lCountV); long lCountE = 0; // Iterate over all the edges’ splits to count all the edges for (int split = 0; split < opg.getEdgeTableSplits(); split += dop) { Iterable<Edge>[] iterables = opg.getEdgesPartitioned(hConns /* Connection array */, true /* skip store to cache */, split /* starting split */); lCountE += consumeIterables(iterables); /* consume iterables using threads */ } // Count all edges System.out.println("Edges found using parallel query: " + lCountE); // Close the connections to the database after completed for (int idx = 0; idx < hConns.length; idx++) { hConns[idx].close(); }
Apache HBaseのかわりにOracle NoSQL Database接続を使用してプロパティ・グラフをロードするには、次のコードを使用する必要があります。
// Create connections used in parallel query hConns = new KVStoreConfig[dop]; kvsc = opg.getKVStoreConfig(); for (i = 0; i < dop; i++) {hConns[i] = kvsc.clone(); } opg.setNumSplits(dop);
Oracle Big Data Spatial and Graphは、ユーザー定義の要素フィルタ・コールバックを使用した、容易なサブグラフ抽出のサポートを提供します。要素フィルタ・コールバックは、サブグラフに頂点(またはエッジ)を保持するために、頂点(またはエッジ)が満たす必要のある条件セットを定義します。ユーザーはVertexFilterCallback
およびEdgeFilterCallback
APIインタフェースを実装することによって、独自の要素フィルタを定義できます。
次のコード・フラグメントは、頂点が政治的役割を持たず、その出生地が米国であるかどうかを検証するVertexFilterCallback
を実装します。
/** * VertexFilterCallback to retrieve a vertex from the United States * that does not have a political role */ private static class NonPoliticianFilterCallback implements VertexFilterCallback { @Override public boolean keepVertex(OracleVertexBase vertex) { String country = vertex.getProperty("country"); String role = vertex.getProperty("role"); if (country != null && country.equals("United States")) { if (role == null || !role.toLowerCase().contains("political")) { return true; } } return false; } public static NonPoliticianFilterCallback getInstance() { return new NonPoliticianFilterCallback(); } }
次のコード・フラグメントは、VertexFilterCallback
を使用して特定の入力頂点に接続しているエッジのうち、その接続が政治家ではなく米国出身であるエッジのみを保持するEdgeFilterCallback
を実装します。
/** * EdgeFilterCallback to retrieve all edges connected to an input * vertex with "collaborates" label, and whose vertex is from the * United States with a role different than political */ private static class CollaboratorsFilterCallback implements EdgeFilterCallback { private VertexFilterCallback m_vfc; private Vertex m_startV; public CollaboratorsFilterCallback(VertexFilterCallback vfc, Vertex v) { m_vfc = vfc; m_startV = v; } @Override public boolean keepEdge(OracleEdgeBase edge) { if ("collaborates".equals(edge.getLabel())) { if (edge.getVertex(Direction.IN).equals(m_startV) && m_vfc.keepVertex((OracleVertex) edge.getVertex(Direction.OUT))) { return true; } else if (edge.getVertex(Direction.OUT).equals(m_startV) && m_vfc.keepVertex((OracleVertex) edge.getVertex(Direction.IN))) { return true; } } return false; } public static CollaboratorsFilterCallback getInstance(VertexFilterCallback vfc, Vertex v) { return new CollaboratorsFilterCallback(vfc, v); } }
前に定義したフィルタ・コールバックを使用して、次のコード・フラグメントは、プロパティ・グラフをロードし、フィルタ・コールバックのインスタンスを作成し、その後に政治家ではなく米国出身であるBarack Obamaのすべての協力者を取得します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // VertexFilterCallback to retrieve all people from the United States // who are not politicians NonPoliticianFilterCallback npvfc = NonPoliticianFilterCallback.getInstance(); // Initial vertex: Barack Obama Vertex v = opg.getVertices("name", "Barack Obama").iterator().next(); // EdgeFilterCallback to retrieve all collaborators of Barack Obama // from the United States who are not politicians CollaboratorsFilterCallback cefc = CollaboratorsFilterCallback.getInstance(npvfc, v); Iterable<<Edge> obamaCollabs = opg.getEdges((String[])null /* Match any of the properties */, cefc /* Match the EdgeFilterCallback */ ); Iterator<<Edge> iter = obamaCollabs.iterator(); System.out.println("\n\n--------Collaborators of Barack Obama from " + " the US and non-politician\n\n"); long countV = 0; while (iter.hasNext()) { Edge edge = iter.next(); // get the edge // check if obama is the IN vertex if (edge.getVertex(Direction.IN).equals(v)) { System.out.println(edge.getVertex(Direction.OUT) + "(Edge ID: " + edge.getId() + ")"); // get out vertex } else { System.out.println(edge.getVertex(Direction.IN)+ "(Edge ID: " + edge.getId() + ")"); // get in vertex } countV++; }
デフォルトでは、すべての頂点の取得、すべてのエッジの取得(および並列アプローチ)などのすべての読取り操作は、opg.setVertexFilterCallback(vfc)
およびopg.setEdgeFilterCallback(efc)
メソッドを使用してプロパティ・グラフに関連付けられたフィルタ・コールバックを使用します。フィルタ・コールバック・セットがない場合は、すべての頂点(またはエッジ)およびエッジが取得されます。
次のコード・フラグメントは、プロパティ・グラフでデフォルトのエッジ・フィルタ・コールバック・セットを使用して、エッジを取得します。
// VertexFilterCallback to retrieve all people from the United States // who are not politicians NonPoliticianFilterCallback npvfc = NonPoliticianFilterCallback.getInstance(); // Initial vertex: Barack Obama Vertex v = opg.getVertices("name", "Barack Obama").iterator().next(); // EdgeFilterCallback to retrieve all collaborators of Barack Obama // from the United States who are not politicians CollaboratorsFilterCallback cefc = CollaboratorsFilterCallback.getInstance(npvfc, v); opg.setEdgeFilterCallback(cefc); Iterable<Edge> obamaCollabs = opg.getEdges(); Iterator<Edge> iter = obamaCollabs.iterator(); System.out.println("\n\n--------Collaborators of Barack Obama from " + " the US and non-politician\n\n"); long countV = 0; while (iter.hasNext()) { Edge edge = iter.next(); // get the edge // check if obama is the IN vertex if (edge.getVertex(Direction.IN).equals(v)) { System.out.println(edge.getVertex(Direction.OUT) + "(Edge ID: " + edge.getId() + ")"); // get out vertex } else { System.out.println(edge.getVertex(Direction.IN)+ "(Edge ID: " + edge.getId() + ")"); // get in vertex } countV++; }
最適化フラグを使用すると、グラフ反復のパフォーマンスを向上させることができます。最適化フラグにより、情報がない、または最小限の情報(ID、ラベルおよび入力/出力頂点など)を持つオブジェクトとして、頂点(またはエッジ)を処理できます。これにより、反復中の各頂点またはエッジの処理にかかる時間が削減されます。
次の表に、プロパティ・グラフで頂点またはエッジを処理するときに使用できる最適化フラグを示します。
表5-1 プロパティ・グラフで頂点またはエッジを処理するための最適化フラグ
最適化フラグ | 説明 |
---|---|
DO_NOT_CREATE_OBJECT | 頂点またはエッジを処理するときに、事前定義済の定数オブジェクトを使用します。 |
JUST_EDGE_ID | エッジの処理時に、IDのみを持つエッジ・オブジェクトを作成します。 |
JUST_LABEL_EDGE_ID | エッジの処理時に、IDとラベルのみを持つエッジ・オブジェクトを作成します。 |
JUST_LABEL_VERTEX_EDGE_ID | エッジの処理時に、ID、ラベルおよび入力/出力頂点IDのみを持つエッジ・オブジェクトを作成します。 |
JUST_VERTEX_EDGE_ID | エッジの処理時に、IDおよび入力/出力頂点IDのみを持つエッジ・オブジェクトを作成します。 |
JUST_VERTEX_ID | 頂点の処理時に、IDのみを持つ頂点オブジェクトを作成します。 |
次のコード・フラグメントは、最適化フラグのセットを使用して、プロパティ・グラフの頂点およびエッジからすべてのIDのみを取得します。すべての頂点およびエッジの読取りによって取得されたオブジェクトには、IDのみが含まれ、キー/値プロパティや追加情報は含まれません。
import oracle.pg.common.OraclePropertyGraphBase.OptimizationFlag; OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Optimization flag to retrieve only vertices IDs OptimizationFlag optFlagVertex = OptimizationFlag.JUST_VERTEX_ID; // Optimization flag to retrieve only edges IDs OptimizationFlag optFlagEdge = OptimizationFlag.JUST_EDGE_ID; // Print all vertices Iterator<Vertex> vertices = opg.getVertices((String[])null /* Match any of the properties */, null /* Match the VertexFilterCallback */, optFlagVertex /* optimization flag */ ).iterator(); System.out.println("----- Vertices IDs----"); long vCount = 0; while (vertices.hasNext()) { OracleVertex v = vertices.next(); System.out.println((Long) v.getId()); vCount++; } System.out.println("Vertices found: " + vCount); // Print all edges Iterator<Edge> edges = opg.getEdges((String[])null /* Match any of the properties */, null /* Match the EdgeFilterCallback */, optFlagEdge /* optimization flag */ ).iterator(); System.out.println("----- Edges ----"); long eCount = 0; while (edges.hasNext()) { Edge e = edges.next(); System.out.println((Long) e.getId()); eCount++; } System.out.println("Edges found: " + eCount);
デフォルトでは、すべての頂点の取得、すべてのエッジの取得(および並列アプローチ)などのすべての読取り操作は、opg.setDefaultVertexOptFlag(optFlagVertex)
およびopg.setDefaultEdgeOptFlag(optFlagEdge)
メソッドを使用してプロパティ・グラフに関連付けられた最適化フラグを使用します。頂点またはエッジの処理に対する最適化フラグが定義されていない場合、頂点およびエッジに関するすべての情報が取得されます。
次のコード・フラグメントは、プロパティ・グラフでデフォルト最適化フラグのセットを使用して、その頂点およびエッジからすべてのIDのみを取得します。
import oracle.pg.common.OraclePropertyGraphBase.OptimizationFlag; // Optimization flag to retrieve only vertices IDs OptimizationFlag optFlagVertex = OptimizationFlag.JUST_VERTEX_ID; // Optimization flag to retrieve only edges IDs OptimizationFlag optFlagEdge = OptimizationFlag.JUST_EDGE_ID; opg.setDefaultVertexOptFlag(optFlagVertex); opg.setDefaultEdgeOptFlag(optFlagEdge); Iterator<Vertex> vertices = opg.getVertices().iterator(); System.out.println("----- Vertices IDs----"); long vCount = 0; while (vertices.hasNext()) { OracleVertex v = vertices.next(); System.out.println((Long) v.getId()); vCount++; } System.out.println("Vertices found: " + vCount); // Print all edges Iterator<Edge> edges = opg.getEdges().iterator(); System.out.println("----- Edges ----"); long eCount = 0; while (edges.hasNext()) { Edge e = edges.next(); System.out.println((Long) e.getId()); eCount++; } System.out.println("Edges found: " + eCount);
Oracle Big Data Spatial and Graphは、ユーザーがカスタマイズした操作コールバックを使用した、頂点またはエッジ(あるいはその両方)のサブグラフへの属性(キー/値ペア)の更新をサポートします。操作コールバックは、(特定の属性および値を追加または削除することによって)頂点(またはエッジ)を更新するために、頂点(またはエッジ)が満たす必要のある条件セットを定義します。
VertexOpCallback
およびEdgeOpCallback
APIインタフェースを実装することにより、独自の属性操作を定義できます。更新操作に含まれる頂点(またはエッジ)によって満たされる必要のある条件を定義するneedOp
メソッド、および要素の更新時に使用されるキー名とキー値をそれぞれ返すgetAttributeKeyName
メソッドとgetAttributeKeyValue
メソッドをオーバーライドする必要があります。
次のコード・フラグメントは、Barack Obamaの協力者のみに関連付けられたobamaCollaborator
属性を操作するVertexOpCallback
を実装します。このプロパティの値は、協力者の役職に基づいて指定されます。
private static class CollaboratorsVertexOpCallback implements VertexOpCallback { private OracleVertexBase m_obama; private List<Vertex> m_obamaCollaborators; public CollaboratorsVertexOpCallback(OraclePropertyGraph opg) { // Get a list of Barack Obama'sCollaborators m_obama = (OracleVertexBase) opg.getVertices("name", "Barack Obama") .iterator().next(); Iterable<Vertex> iter = m_obama.getVertices(Direction.BOTH, "collaborates"); m_obamaCollaborators = OraclePropertyGraphUtils.listify(iter); } public static CollaboratorsVertexOpCallback getInstance(OraclePropertyGraph opg) { return new CollaboratorsVertexOpCallback(opg); } /** * Add attribute if and only if the vertex is a collaborator of Barack * Obama */ @Override public boolean needOp(OracleVertexBase v) { return m_obamaCollaborators != null && m_obamaCollaborators.contains(v); } @Override public String getAttributeKeyName(OracleVertexBase v) { return "obamaCollaborator"; } /** * Define the property's value based on the vertex role */ @Override public Object getAttributeKeyValue(OracleVertexBase v) { String role = v.getProperty("role"); role = role.toLowerCase(); if (role.contains("political")) { return "political"; } else if (role.contains("actor") || role.contains("singer") || role.contains("actress") || role.contains("writer") || role.contains("producer") || role.contains("director")) { return "arts"; } else if (role.contains("player")) { return "sports"; } else if (role.contains("journalist")) { return "journalism"; } else if (role.contains("business") || role.contains("economist")) { return "business"; } else if (role.contains("philant")) { return "philanthropy"; } return " "; } }
次のコード・フラグメントは、Barack Obamaの敵対者のみに関連付けられたobamaFeud
属性を操作するEdgeOpCallback
を実装します。このプロパティの値は、協力者の役職に基づいて指定されます。
private static class FeudsEdgeOpCallback implements EdgeOpCallback { private OracleVertexBase m_obama; private List<Edge> m_obamaFeuds; public FeudsEdgeOpCallback(OraclePropertyGraph opg) { // Get a list of Barack Obama's feuds m_obama = (OracleVertexBase) opg.getVertices("name", "Barack Obama") .iterator().next(); Iterable<Edge> iter = m_obama.getEdges(Direction.BOTH, "feuds"); m_obamaFeuds = OraclePropertyGraphUtils.listify(iter); } public static FeudsEdgeOpCallback getInstance(OraclePropertyGraph opg) { return new FeudsEdgeOpCallback(opg); } /** * Add attribute if and only if the edge is in the list of Barack Obama's * feuds */ @Override public boolean needOp(OracleEdgeBase e) { return m_obamaFeuds != null && m_obamaFeuds.contains(e); } @Override public String getAttributeKeyName(OracleEdgeBase e) { return "obamaFeud"; } /** * Define the property's value based on the in/out vertex role */ @Override public Object getAttributeKeyValue(OracleEdgeBase e) { OracleVertexBase v = (OracleVertexBase) e.getVertex(Direction.IN); if (m_obama.equals(v)) { v = (OracleVertexBase) e.getVertex(Direction.OUT); } String role = v.getProperty("role"); role = role.toLowerCase(); if (role.contains("political")) { return "political"; } else if (role.contains("actor") || role.contains("singer") || role.contains("actress") || role.contains("writer") || role.contains("producer") || role.contains("director")) { return "arts"; } else if (role.contains("journalist")) { return "journalism"; } else if (role.contains("player")) { return "sports"; } else if (role.contains("business") || role.contains("economist")) { return "business"; } else if (role.contains("philanthropist")) { return "philanthropy"; } return " "; } }
前に定義した操作コールバックを使用して、次のコード・フラグメントはプロパティ・グラフをロードし、操作コールバックのインスタンスを作成し、その後にOraclePropertyGraph
でaddAttributeToAllVertices
およびaddAttributeToAllEdges
メソッドを使用して属性を適切な頂点およびエッジに追加します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create the vertex operation callback CollaboratorsVertexOpCallback cvoc = CollaboratorsVertexOpCallback.getInstance(opg); // Add attribute to all people collaborating with Obama based on their role opg.addAttributeToAllVertices(cvoc, true /** Skip store to Cache */, dop); // Look up for all collaborators of Obama // The function getVerticesAsString prints the vertices in the given iterable Iterable<Vertex> collaborators = opg.getVertices("obamaCollaborator", "political"); System.out.println("Political collaborators of Barack Obama " + getVerticesAsString(collaborators)); collaborators = opg.getVertices("obamaCollaborator", "business"); System.out.println("Business collaborators of Barack Obama " + getVerticesAsString(collaborators)); // Add an attribute to all people having a feud with Barack Obama to set // the type of relation they have FeudsEdgeOpCallback feoc = FeudsEdgeOpCallback.getInstance(opg); opg.addAttributeToAllEdges(feoc, true /** Skip store to Cache */, dop); // Look up for all feuds of Obama // The function getEdgesAsString prints the edges in the given iterable Iterable<Edge> feuds = opg.getEdges("obamaFeud", "political"); System.out.println("\n\nPolitical feuds of Barack Obama " + getEdgesAsString(feuds)); feuds = opg.getEdges("obamaFeud", "business"); System.out.println("Business feuds of Barack Obama " + getEdgesAsString(feuds));
次のコード・フラグメントは、属性obamaCollaborator
にphilanthropyという値を持つ頂点を削除した後でAPI removeAttributeFromAllVertices
をコールするために使用できるVertexOpCallback
の実装を定義します。また、属性obamaFeud
にbusinessという値を持つエッジを削除した後でAPI removeAttributeFromAllEdges
をコールするために使用できるEdgeOpCallback
の実装も定義します。
System.out.println("\n\nRemove 'obamaCollaborator' property from all the" + "philanthropy collaborators"); PhilanthropyCollaboratorsVertexOpCallback pvoc = PhilanthropyCollaboratorsVertexOpCallback.getInstance(); opg.removeAttributeFromAllVertices(pvoc); System.out.println("\n\nRemove 'obamaFeud' property from all the" + "business feuds"); BusinessFeudsEdgeOpCallback beoc = BusinessFeudsEdgeOpCallback.getInstance(); opg.removeAttributeFromAllEdges(beoc); /** * Implementation of a EdgeOpCallback to remove the "obamaCollaborators" * property from all people collaborating with Barack Obama that have a * philanthropy role */ private static class PhilanthropyCollaboratorsVertexOpCallback implements VertexOpCallback { public static PhilanthropyCollaboratorsVertexOpCallback getInstance() { return new PhilanthropyCollaboratorsVertexOpCallback(); } /** * Remove attribute if and only if the property value for * obamaCollaborator is Philanthropy */ @Override public boolean needOp(OracleVertexBase v) { String type = v.getProperty("obamaCollaborator"); return type != null && type.equals("philanthropy"); } @Override public String getAttributeKeyName(OracleVertexBase v) { return "obamaCollaborator"; } /** * Define the property's value. In this case can be empty */ @Override public Object getAttributeKeyValue(OracleVertexBase v) { return " "; } } /** * Implementation of a EdgeOpCallback to remove the "obamaFeud" property * from all connections in a feud with Barack Obama that have a business role */ private static class BusinessFeudsEdgeOpCallback implements EdgeOpCallback { public static BusinessFeudsEdgeOpCallback getInstance() { return new BusinessFeudsEdgeOpCallback(); } /** * Remove attribute if and only if the property value for obamaFeud is * business */ @Override public boolean needOp(OracleEdgeBase e) { String type = e.getProperty("obamaFeud"); return type != null && type.equals("business"); } @Override public String getAttributeKeyName(OracleEdgeBase e) { return "obamaFeud"; } /** * Define the property's value. In this case can be empty */ @Override public Object getAttributeKeyValue(OracleEdgeBase e) { return " "; } }
データベース内のすべてのグラフ名など、グラフのメタデータと統計を取得できます。各グラフについて、最小/最大頂点ID、最小/最大エッジID、頂点プロパティ名、エッジ・プロパティ名、グラフ頂点内の分割の数、およびパラレル表スキャンをサポートするエッジ表などを取得します。
次のコード・フラグメントは、バックエンド・データベース(Oracle NoSQL DatabaseまたはApache HBase)に格納されている既存のプロパティ・グラフのメタデータおよび統計を取得します。必要な引数は、各データベースで異なります。
// Get all graph names in the database List<String> graphNames = OraclePropertyGraphUtils.getGraphNames(dbArgs); for (String graphName : graphNames) { OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args, graphName); System.err.println("\n Graph name: " + graphName); System.err.println(" Total vertices: " + opg.countVertices(dop)); System.err.println(" Minimum Vertex ID: " + opg.getMinVertexID(dop)); System.err.println(" Maximum Vertex ID: " + opg.getMaxVertexID(dop)); // The function getPropertyNamesAsString prints the given set of properties Set<String> propertyNamesV = new HashSet<String>(); opg.getVertexPropertyNames(dop, 0 /* timeout,0 no timeout */, propertyNamesV); System.err.println(" Vertices property names: " + getPropertyNamesAsString(propertyNamesV)); System.err.println("\n\n Total edges: " + opg.countEdges(dop)); System.err.println(" Minimum Edge ID: " + opg.getMinEdgeID(dop)); System.err.println(" Maximum Edge ID: " + opg.getMaxEdgeID(dop)); Set<String> propertyNamesE = new HashSet<String>(); opg.getEdgePropertyNames(dop, 0 /* timeout,0 no timeout */, propertyNamesE); System.err.println(" Edge property names: " + getPropertyNamesAsString(propertyNamesE)); System.err.println("\n\n Table Information: "); System.err.println("Vertex table number of splits: " + (opg.getVertexTableSplits())); System.err.println("Edge table number of splits: " + (opg.getEdgeTableSplits())); }
プロパティ・グラフを記述する際、次のOracle Property Graphクラスを使用して、プロパティ・グラフ・インスタンスを適切にオープンおよびクローズします。
OraclePropertyGraph.getInstance
: Oracleプロパティ・グラフのインスタンスをオープンします。このメソッドには、接続情報とグラフ名の2つのパラメータがあります。接続情報のフォーマットは、バックエンド・データベースとしてHBaseまたはOracle NoSQL Databaseのいずれを使用しているかによって異なります。
OraclePropertyGraph.clearRepository
: プロパティ・グラフ・インスタンスからすべての頂点およびエッジを削除します。
OraclePropertyGraph.shutdown
: グラフ・インスタンスをクローズします。
さらに、Oracle NoSQL DatabaseまたはHBase APIからの適切なクラスを使用する必要があります。
Oracle NoSQL Databaseでは、OraclePropertyGraph.getInstance
メソッドはKVストア名、ホスト・コンピュータ名およびポート番号を接続に使用します。
String kvHostPort = "cluster02:5000"; String kvStoreName = "kvstore"; String kvGraphName = "my_graph"; // Use NoSQL Java API KVStoreConfig kvconfig = new KVStoreConfig(kvStoreName, kvHostPort); OraclePropertyGraph opg = OraclePropertyGraph.getInstance(kvconfig, kvGraphName); opg.clearRepository(); // . // . Graph description // . // Close the graph instance opg.shutdown();
アプリケーションでインメモリー・アナリスト機能が必要な場合、GraphConfigBuilder
を使用してOracle NoSQL Databaseに対してグラフconfig
を作成し、引数としてconfig
を指定してOraclePropertyGraph
をインスタンス化することをお薦めします。
例として、次のコード・スニペットはグラフconfig
を作成し、OraclePropertyGraph
インスタンスを取得し、いくつかのデータをそのグラフにロードして、インメモリー・アナリストを取得します。
import oracle.pgx.config.*; import oracle.pgx.api.*; import oracle.pgx.common.types.*; ... String[] hhosts = new String[1]; hhosts[0] = "my_host_name:5000"; // need customization String szStoreName = "kvstore"; // need customization String szGraphName = "my_graph"; int dop = 8; PgNosqlGraphConfig cfg = GraphConfigBuilder.forPropertyGraphNosql() .setName(szGraphName) .setHosts(Arrays.asList(hhosts)) .setStoreName(szStoreName) .addEdgeProperty("lbl", PropertyType.STRING, "lbl") .addEdgeProperty("weight", PropertyType.DOUBLE, "1000000") .build(); OraclePropertyGraph opg = OraclePropertyGraph.getInstance(cfg); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // perform a parallel data load OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); ... PgxSession session = Pgx.createSession("session-id-1"); PgxGraph g = session.readGraphWithProperties(cfg); Analyst analyst = session.createAnalyst(); ...
Apache HBaseでは、OraclePropertyGraph.getInstance
メソッドはHadoopノードとApache HBaseポート番号を接続に使用します。
String hbQuorum = "bda01node01.example.com, bda01node02.example.com, bda01node03.example.com"; String hbClientPort = "2181" String hbGraphName = "my_graph"; // Use HBase Java APIs Configuration conf = HBaseConfiguration.create(); conf.set("hbase.zookeeper.quorum", hbQuorum); conf.set("hbase.zookeper.property.clientPort", hbClientPort); HConnection conn = HConnectionManager.createConnection(conf); // Open the property graph OraclePropertyGraph opg = OraclePropertyGraph.getInstance(conf, conn, hbGraphName); opg.clearRepository(); // . // . Graph description // . // Close the graph instance opg.shutdown(); // Close the HBase connection conn.close();
アプリケーションでインメモリー・アナリスト機能が必要な場合、GraphConfigBuilder
を使用してグラフconfig
を作成し、引数としてconfig
を指定してOraclePropertyGraph
をインスタンス化することをお薦めします。
例として、次のコード・スニペットはインメモリー分析の構成を設定し、Apache HBaseに対してグラフconfigを作成し、OraclePropertyGraph
インスタンスをインスタンス化し、インメモリー・アナリストを取得して、グラフ内のトライアングルの数をカウントします。
confPgx = new HashMap<PgxConfig.Field, Object>(); confPgx.put(PgxConfig.Field.ENABLE_GM_COMPILER, false); confPgx.put(PgxConfig.Field.NUM_WORKERS_IO, dop + 2); confPgx.put(PgxConfig.Field.NUM_WORKERS_ANALYSIS, 8); // <= # of physical cores confPgx.put(PgxConfig.Field.NUM_WORKERS_FAST_TRACK_ANALYSIS, 2); confPgx.put(PgxConfig.Field.SESSION_TASK_TIMEOUT_SECS, 0);// no timeout set confPgx.put(PgxConfig.Field.SESSION_IDLE_TIMEOUT_SECS, 0); // no timeout set ServerInstance instance = Pgx.getInstance(); instance.startEngine(confPgx); int iClientPort = Integer.parseInt(hbClientPort); int splitsPerRegion = 2; PgHbaseGraphConfig cfg = GraphConfigBuilder.forPropertyGraphHbase() .setName(hbGraphName) .setZkQuorum(hbQuorum) .setZkClientPort(iClientPort) .setZkSessionTimeout(60000) .setMaxNumConnections(dop) .setSplitsPerRegion(splitsPerRegion) .addEdgeProperty("lbl", PropertyType.STRING, "lbl") .addEdgeProperty("weight", PropertyType.DOUBLE, "1000000") .build(); PgxSession session = Pgx.createSession("session-id-1"); PgxGraph g = session.readGraphWithProperties(cfg); Analyst analyst = session.createAnalyst(); long triangles = analyst.countTriangles(g, false);
頂点を作成するには、次のOracle Property Graphメソッドを使用します。
OraclePropertyGraph.addVertex
: グラフに頂点インスタンスを追加します。
OracleVertex.setProperty
: 頂点にキー値プロパティを割り当てます。
OraclePropertyGraph.commit
: すべての変更をプロパティ・グラフ・インスタンスに保存します。
次のコード・フラグメントは、opg
プロパティ・グラフ・インスタンスに年齢、名前、体重、身長、性別のプロパティを指定して、V1
およびV2
という名前の2つの頂点を作成します。v1
プロパティはデータ型を明示的に設定します。
// Create vertex v1 and assign it properties as key-value pairs Vertex v1 = opg.addVertex(1l); v1.setProperty("age", Integer.valueOf(31)); v1.setProperty("name", "Alice"); v1.setProperty("weight", Float.valueOf(135.0f)); v1.setProperty("height", Double.valueOf(64.5d)); v1.setProperty("female", Boolean.TRUE); Vertex v2 = opg.addVertex(2l); v2.setProperty("age", 27); v2.setProperty("name", "Bob"); v2.setProperty("weight", Float.valueOf(156.0f)); v2.setProperty("height", Double.valueOf(69.5d)); v2.setProperty("female", Boolean.FALSE);
エッジを作成するには、次のOracle Property Graphメソッドを使用します。
OraclePropertyGraph.addEdge
: グラフにエッジ・インスタンスを追加します。
OracleEdge.setProperty
: エッジにキー値プロパティを割り当てます。
次のコード・フラグメントは、2つの頂点(v1
およびv2
)と1つのエッジ(e1
)を作成します。
// Add vertices v1 and v2 Vertex v1 = opg.addVertex(1l); v1.setProperty("name", "Alice"); v1.setProperty("age", 31); Vertex v2 = opg.addVertex(2l); v2.setProperty("name", "Bob"); v2.setProperty("age", 27); // Add edge e1 Edge e1 = opg.addEdge(1l, v1, v2, "knows"); e1.setProperty("type", "friends");
頂点インスタンスとエッジ・インスタンスを個別に、またはすべて同時に削除できます。次のメソッドを使用します。
OraclePropertyGraph.removeEdge
: 指定されたエッジをグラフから削除します。
OraclePropertyGraph.removeVertex
: 指定された頂点をグラフから削除します。
OraclePropertyGraph.clearRepository
: プロパティ・グラフ・インスタンスからすべての頂点およびエッジを削除します。
次のコード・フラグメントは、グラフ・インスタンスからエッジe1
と頂点v1
を削除します。頂点を削除するときに、隣接するエッジもグラフから削除されます。これは、すべてのエッジは開始頂点と終了頂点を持っている必要があるためです。開始頂点または終了頂点を削除した後、そのエッジは有効なエッジではなくなります。
// Remove edge e1 opg.removeEdge(e1); // Remove vertex v1 opg.removeVertex(v1);
OraclePropertyGraph
インスタンスからすべてのコンテンツを削除するには、OraclePropertyGraph.clearRepository
メソッドを使用できます。ただし、この操作は元に戻せないため、慎重に使用してください。
Apache HBaseまたはOracle NoSQL Databaseから、同じクライアントJavaアプリケーション(単一のJVM)に埋め込まれたインメモリー・アナリストにグラフを読み込むことができます。次のApache HBaseの例の場合:
正しいjava.io.tmpdir
設定が必要です。
dop + 2
は、リリース1.1.2よりも前のパフォーマンスの問題に対処する方法です。リリース1.1.2で有効ですが、かわりにdop
値を構成設定に直接指定できます。
int dop = 8; // need customization Map<PgxConfig.Field, Object> confPgx = new HashMap<PgxConfig.Field, Object>(); confPgx.put(PgxConfig.Field.ENABLE_GM_COMPILER, false); confPgx.put(PgxConfig.Field.NUM_WORKERS_IO, dop + 2); // use dop directly with release 1.1.2 or newer confPgx.put(PgxConfig.Field.NUM_WORKERS_ANALYSIS, dop); // <= # of physical cores confPgx.put(PgxConfig.Field.NUM_WORKERS_FAST_TRACK_ANALYSIS, 2); confPgx.put(PgxConfig.Field.SESSION_TASK_TIMEOUT_SECS, 0); // no timeout set confPgx.put(PgxConfig.Field.SESSION_IDLE_TIMEOUT_SECS, 0); // no timeout set PgHbaseGraphConfig cfg = GraphConfigBuilder.forPropertyGraphHbase() .setName("mygraph") .setZkQuorum("localhost") // quorum, need customization .setZkClientPort(2181) .addNodeProperty("name", PropertyType.STRING, "default_name") .build(); OraclePropertyGraph opg = OraclePropertyGraph.getInstance(cfg); ServerInstance localInstance = Pgx.getInstance(); localInstance.startEngine(confPgx); PgxSession session = localInstance.createSession("session-id-1"); // Put your session description here. Analyst analyst = session.createAnalyst(); // The following call will trigger a read of graph data from the database PgxGraph pgxGraph = session.readGraphWithProperties(opg.getConfig()); long triangles = analyst.countTriangles(pgxGraph, false); System.out.println("triangles " + triangles); // After reading a graph in memory, modifying the graph on the database side should not affect in memory results: // Remove edge e1 opg.removeEdge(e1); // Remove vertex v1 opg.removeVertex(v1);
「プロパティ・グラフとは」で説明されているように、データベースおよびデータ・アクセス・レイヤーには、頂点用のラベルは用意されていません。ただし、指定した頂点プロパティの値を1つ以上のラベルとして扱うことができます。このような変換が関連するのは、インメモリー・アナリストの場合のみです。
次の例では、プロパティ"country
"がsetUseVertexPropertyValueAsLabel()
への呼出しに指定されており、カンマ区切り",
"がsetPropertyValueDelimiter()
への呼出しに指定されています。これら2つをまとめると、country
頂点プロパティの値がカンマ区切りの頂点ラベルとして扱われることを意味します。たとえば、頂点Xの国プロパティの文字列値が"US"
である場合、頂点ラベルはUS
になり、頂点Yの文字列値が"UK,CN"
である場合、2つのラベルUK
およびCN
を持ちます。
GraphConfigBuilder.forPropertyGraph... .setName("<your_graph_name>") ... .setUseVertexPropertyValueAsLabel("country") .setPropertyValueDelimiter(",") .build();
「グラフ・データのメモリーへの読込み」以外にも、インメモリー・グラフをプログラムで作成できます。これにより、グラフのサイズが小さい場合やグラフのコンテンツが非常に動的である場合、開発を簡略化できます。主要なJavaクラスは、addVertex
およびaddEdge
APIを使用して追加された頂点とエッジのセットを累計できるGraphBuilder
です。すべての変更が行われた後、GraphBuilder
によってインメモリー・グラフ・インスタンス(PgxGraph
)を作成できます。
次のJavaコード・スニペットは、グラフの構築フローを示します。まだ存在していない頂点は隣接するエッジが作成されるときに動的に追加されるため、addVertex
に対する明示的な呼出しはありません。
import oracle.pgx.api.*; PgxSession session = Pgx.createSession("example"); GraphBuilder<Integer> builder = session.newGraphBuilder(); builder.addEdge(0, 1, 2); builder.addEdge(1, 2, 3); builder.addEdge(2, 2, 4); builder.addEdge(3, 3, 4); builder.addEdge(4, 4, 2); PgxGraph graph = builder.build();
頂点プロパティを使用してグラフを構築するには、作成された頂点オブジェクトに対してsetProperty
を使用できます。
PgxSession session = Pgx.createSession("example"); GraphBuilder<Integer> builder = session.newGraphBuilder(); builder.addVertex(1).setProperty("double-prop", 0.1); builder.addVertex(2).setProperty("double-prop", 2.0); builder.addVertex(3).setProperty("double-prop", 0.3); builder.addVertex(4).setProperty("double-prop", 4.56789); builder.addEdge(0, 1, 2); builder.addEdge(1, 2, 3); builder.addEdge(2, 2, 4); builder.addEdge(3, 3, 4); builder.addEdge(4, 4, 2); PgxGraph graph = builder.build();
頂点およびエッジ識別子としてLong整数を使用するには、GraphBuilder
の新しいインスタンスの取得時にIdType.LONG
を指定します。次に例を示します。
import oracle.pgx.common.types.IdType; GraphBuilder<Long> builder = session.newGraphBuilder(IdType.LONG);
エッジの構築時に、addEdge
への呼出しで前に作成した頂点オブジェクトを直接使用できます。
v1 = builder.addVertex(1l).setProperty("double-prop", 0.5) v2 = builder.addVertex(2l).setProperty("double-prop", 2.0) builder.addEdge(0, v1, v2)
頂点の場合と同じように、エッジもプロパティを持つことができます。次の例では、setLabel
を使用してエッジ・ラベルを設定します。
builder.addEdge(4, v4, v2).setProperty("edge-prop", "edge_prop_4_2").setLabel("label")
データベースからプロパティ・グラフを削除するには、OraclePropertyGraphUtils.dropPropertyGraph
メソッドを使用します。このメソッドには、接続情報とグラフ名の2つのパラメータがあります。
接続情報のフォーマットは、バックエンド・データベースとしてHBaseまたはOracle NoSQL Databaseのいずれを使用しているかによって異なります。これは、OraclePropertyGraph.getInstance
に指定する接続情報と同じです。
Oracle NoSQL Databaseでは、OraclePropertyGraphUtils.dropPropertyGraph
メソッドはKVストア名、ホスト・コンピュータ名およびポート番号を接続に使用します。このコード・フラグメントは、my_graph
という名前のグラフをOracle NoSQL Databaseから削除します。
String kvHostPort = "cluster02:5000"; String kvStoreName = "kvstore"; String kvGraphName = "my_graph"; // Use NoSQL Java API KVStoreConfig kvconfig = new KVStoreConfig(kvStoreName, kvHostPort); // Drop the graph OraclePropertyGraphUtils.dropPropertyGraph(kvconfig, kvGraphName);
Apache HBaseでは、OraclePropertyGraphUtils.dropPropertyGraph
メソッドはHadoopノードとApache HBaseポート番号を接続に使用します。このコード・フラグメントは、my_graph
という名前のグラフをApache HBaseから削除します。
String hbQuorum = "bda01node01.example.com, bda01node02.example.com, bda01node03.example.com"; String hbClientPort = "2181"; String hbGraphName = "my_graph"; // Use HBase Java APIs Configuration conf = HBaseConfiguration.create(); conf.set("hbase.zookeeper.quorum", hbQuorum); conf.set("hbase.zookeper.property.clientPort", hbClientPort); // Drop the graph OraclePropertyGraphUtils.dropPropertyGraph(conf, hbGraphName);
Oracle Big Data Spatial and Graphの索引付けは、特定のキー/値またはキー/テキスト・ペア別に要素を高速に読み取ることを可能にします。これらの索引は、要素タイプ(頂点またはエッジ)、キー(および値)のセットおよび索引タイプに基づいて作成されます。
Oracle Big Data Spatial and Graphは、手動と自動の2つのタイプの索引付け構造をサポートしています。
自動テキスト索引は、プロパティ・キーのセット別に頂点またはエッジの自動索引付けを行います。この主な目的は、特定のキー/値ペアに基づく頂点およびエッジの問合せパフォーマンスを向上させることです。
手動テキスト索引付けでは、プロパティ・グラフの指定された頂点およびエッジのセットに対して複数の索引を定義できます。索引に含めるグラフ要素を指定する必要があります。
Oracle Big Data Spatial and Graphは、Oracle NoSQL DatabaseおよびApache HBaseのプロパティ・グラフに対して手動および自動テキスト索引を作成するためのAPIを提供します。索引は、使用可能な検索エンジン、Apache LuceneおよびSolrCloudを使用して管理されます。この節の続きでは、データ・アクセス・レイヤーのプロパティ・グラフ機能を使用してテキスト索引を作成する方法に焦点を当てます。
テキスト索引の構成は、OracleIndexParameters
オブジェクトを使用して定義されます。このオブジェクトには、検索エンジン、場所、ディレクトリ(またはシャード)の数、および並列度などの索引に関する情報が含まれます。
デフォルトでは、テキスト索引はメソッドopg.setDefaultIndexParameters(indexParams)
を使用してプロパティ・グラフに関連付けられたOracleIndexParameters
に基づいて構成されます。自動索引の初期作成により、将来索引付けされるキーのために構成およびテキスト検索エンジンが区切られます。
別のパラメータ・セットを指定して索引を作成することもできます。次のコード・フラグメントは、Luceneエンジンとともに物理ディレクトリを使用して既存のプロパティ・グラフに対して自動テキスト索引を作成します。
// Create an OracleIndexParameters object to get Index configuration (search engine, etc). OracleIndexParameters indexParams = OracleIndexParameters.buildFS(args) // Create auto indexing on above properties for all vertices opg.createKeyIndex("name", Vertex.class, indexParams.getParameters());
テキスト索引の初期構成を変更するには、最初に既存のグラフを削除してから、新しい構成を使用して索引を再作成する必要がある場合があります。
Apache Lucene検索エンジンを使用したテキスト索引の構成
SolrCloud検索エンジンを使用したテキスト索引の構成
Apache Lucene検索エンジンを使用したテキスト索引の構成
Apache Lucene検索エンジンを使用したテキスト索引では、LuceneIndexParameters
構成オブジェクトを使用します。Lucene検索エンジンを使用した索引の構成パラメータには、次が含まれます。
ディレクトリの数: 自動索引に使用するApache Luceneディレクトリの数を指定する整数。複数のディレクトリを使用すると、記憶域とパフォーマンスのスケーラビリティを実現できます。デフォルト値は1に設定されています。
バッチ・サイズ: Apache Luceneでのバッチ処理用のドキュメントに使用するバッチ・サイズを指定する整数。デフォルトで使用されるバッチ・サイズは10000です。
バッチのコミット・サイズ:コミット操作が実行される前にApache Lucene索引に追加されるドキュメントの数を指定する整数。デフォルトで使用されるバッチのコミット・サイズは500000です。
データ型処理フラグ: Apache Luceneのデータ型処理を有効にするかどうかを指定するブール。データ型処理を有効にすると、数値および日時データ型に対する検索が高速になります。
ディレクトリ名: Apache Luceneディレクトリが作成されるベース・パスの場所を指定する文字列配列。
次のコード・フラグメントは、Apache Lucene検索エンジンとともに物理ディレクトリを使用してテキスト索引の構成を作成します。
OracleIndexParameters indexParams = OracleIndexParameters.buildFS(4, 4, 10000, 50000, true, "/home/data/text-index");
SolrCloud検索エンジンを使用したテキスト索引の構成
SolrCloud検索エンジンを使用したテキスト索引は、バックグラウンドでSolrIndexParameters
オブジェクトを使用して、索引構築時に使用されるSolrCloudホスト名、シャードの数およびレプリケーション・ファクタを識別します。SolrCloud検索エンジンを使用した索引の構成パラメータには、次が含まれます。
構成名: Oracle Property GraphのSolrCloud構成ファイルが格納されるApache Zookeeperディレクトリの名前。例: opgconfig。構成ファイルには、必要なフィールドのスキーマ(schema.xml)および記憶域設定(solrconfig.xml)が含まれます。
サーバーURL: SolrCloudサービスに接続するために使用されるSolrCloudサーバーURL。例: http://localhost:2181/solr
SolrCloudノード・セット: コレクションのシャードが格納されるSolrCloudサービス内のノードのホスト名。例: node01:8983_solr,node02:8983_solr,node03:8983_solr。値がnullに設定されている場合、コレクションはサービス内で使用可能なすべてのSolrCloudノードを使用して作成されます。
Zookeeperのタイムアウト: Zookeeper接続を待機するために使用されるタイムアウト(秒単位)を表す正の整数。
シャードの数: テキスト索引コレクション用として作成するシャードの数。SolrCloud構成でHDFSディレクトリを使用している場合、シャードの数が、SolrCloudノード・セットに指定されているSolrCloudノードの数を超えないようにする必要があります。
レプリケーション・ファクタ: SolrCloudコレクションで使用されるレプリケーション・ファクタ。デフォルト値は1に設定されています。
ノード当たりのシャードの最大数: 各SolrCloudノードで作成できるシャードの最大数。この値は、シャードの数をSolrCloudノード・セット内のノードの数で割った値より小さくしないようにする必要があります。
DOP: プロパティ・グラフから頂点(またはエッジ)を読み込み、キー/値ペアに索引を付けるときに使用する並列度。デフォルト値は1に設定されています。
バッチ・サイズ: Apache SolrCloudでのバッチ処理用のドキュメントに使用するバッチ・サイズを指定する整数。デフォルトで使用されるバッチ・サイズは10000です。
バッチのコミット・サイズ:コミット操作が実行される前にApache SolrCloud索引に追加されるドキュメントの数を指定する整数。デフォルトで使用されるバッチのコミット・サイズは500000 (50万)です。
書込みタイムアウト: 索引操作が完了するまで待機するために使用するタイムアウト(秒単位)。通信エラーが原因で索引操作が失敗した場合、タイムアウトに達するか操作が完了するまで必要に応じて操作が繰り返し再試行されます。
次のコード・フラグメントは、SolrCloudを使用してテキスト索引の構成を作成します。
String configName = "opgconfig"; String solrServerUrl = "nodea:2181/solr" String solrNodeSet = "nodea:8983_solr,nodeb:8983_solr," + "nodec:8983_solr,noded:8983_solr"; int zkTimeout = 15; int numShards = 4; int replicationFactor = 1; int maxShardsPerNode = 1; OracleIndexParameters indexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout, numShards, replicationFactor, maxShardsPerNode, 4, 10000, 500000, 15);SolrCloudを使用する場合、「ZookeeperへのコレクションのSolrCloud構成のアップロード」で説明されているように、最初にテキスト索引のためのコレクションの構成をApache Zookeeperにロードする必要があります。
自動テキスト索引は、プロパティ・キーのセット別に頂点またはエッジの自動索引付けを行います。その主な目的は、特定のキー/値ペアに基づく頂点およびエッジに対する索引速度を上げることです。特定のキーの自動索引が有効である場合、データベース索引を実行する代わりに、キー/値ペアの索引が索引に対してテキスト索引として実行されます。
プロパティ・グラフに対する自動索引を記述する場合、次のOracleプロパティ・グラフ・メソッドを使用して自動索引を作成、削除および操作します。
OraclePropertyGraph.createKeyIndex(String key, Class elementClass, Parameter[] parameters)
: 特定のプロパティ・キー別にelementClass
型の要素すべての自動索引を作成します。索引は、指定したパラメータに基づいて構成されます。
OraclePropertyGraph.createKeyIndex(String[] keys, Class elementClass, Parameter[] parameters)
: プロパティ・キー・セット別にelementClass
型の要素すべての自動索引を作成します。索引は、指定したパラメータに基づいて構成されます。
OraclePropertyGraph.dropKeyIndex(String key, Class elementClass)
: 特定のプロパティ・キー別にelementClass
型の要素すべての自動索引を削除します。
OraclePropertyGraph.dropKeyIndex(String[] keys, Class elementClass)
: 特定のプロパティ・キー・セット別にelementClass
型の要素すべての自動索引を削除します。
OraclePropertyGraph.getAutoIndex(Class elementClass)
: elementClass
型の自動索引の索引インスタンスを取得します。
OraclePropertyGraph.getIndexedKeys(Class elementClass)
: elementClass
型の要素すべての自動索引で現在使用されている索引付けされたキー・セットを取得します。
提供されているExampleNoSQL6
およびExampleHBase6
の例では、入力ファイルからプロパティ・グラフを作成し、頂点に自動テキスト索引を作成し、Apache Luceneを使用していくつかのテキスト検索問合せを実行します。
次のコード・フラグメントは、name、role、religion、countryのプロパティ・キーを指定して、既存のプロパティ・グラフの頂点に自動索引を作成します。自動テキスト索引は、/home/data/text-index
ディレクトリの下にある4つのサブディレクトリに格納されます。Apache Luceneデータ型処理が有効になります。この例では、再索引付けタスクのためにDOP (並列度) 4を使用しています。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // Do a parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create an automatic index using Apache Lucene engine. // Specify Index Directory parameters (number of directories, // number of connections to database, batch size, commit size, // enable datatypes, location) OracleIndexParameters indexParams = OracleIndexParameters.buildFS(4, 4, 10000, 50000, true, "/home/data/text-index "); opg.setDefaultIndexParameters(indexParams); // specify indexed keys String[] indexedKeys = new String[4]; indexedKeys[0] = "name"; indexedKeys[1] = "role"; indexedKeys[2] = "religion"; indexedKeys[3] = "country"; // Create auto indexing on above properties for all vertices opg.createKeyIndex(indexedKeys, Vertex.class);
デフォルトでは、索引はopg.setDefaultIndexParameters(indexParams)
メソッドを使用してプロパティ・グラフに関連付けられたOracleIndexParameters
に基づいて構成されます。
別のパラメータ・セットを指定して索引を作成することもできます。これは次のコード・スニペットに示されています。
// Create an OracleIndexParameters object to get Index configuration (search engine, etc). OracleIndexParameters indexParams = OracleIndexParameters.buildFS(args) // Create auto indexing on above properties for all vertices opg.createKeyIndex("name", Vertex.class, indexParams.getParameters());
次の例のコード・フラグメントは、すべての頂点に対して問合せを実行し、キー値ペアname:Barack Obama
を持つすべての一致する頂点を検索します。この操作は、テキスト索引の検索を実行します。
さらに、getVertices
APIコールでuseWildCards
パラメータを指定することにより、ワイルドカード検索がサポートされます。ワイルドカード検索は、指定されたプロパティ・キーに対して自動索引が有効化されている場合にのみサポートされます。Apache Luceneを使用したテキスト検索構文の詳細は、https://lucene.apache.org/core/2_9_4/queryparsersyntax.html
を参照してください。
// Find all vertices with name Barack Obama. Iterator<Vertices> vertices = opg.getVertices("name", "Barack Obama").iterator(); System.out.println("----- Vertices with name Barack Obama -----"); countV = 0; while (vertices.hasNext()) { System.out.println(vertices.next()); countV++; } System.out.println("Vertices found: " + countV); // Find all vertices with name including keyword "Obama" // Wildcard searching is supported. boolean useWildcard = true; Iterator<Vertices> vertices = opg.getVertices("name", "*Obama*",useWildcard).iterator(); System.out.println("----- Vertices with name *Obama* -----"); countV = 0; while (vertices.hasNext()) { System.out.println(vertices.next()); countV++; } System.out.println("Vertices found: " + countV);
前述のコード例では、次のような出力が生成されます。
----- Vertices with name Barack Obama----- Vertex ID 1 {name:str:Barack Obama, role:str:political authority, occupation:str:44th president of United States of America, country:str:United States, political party:str:Democratic, religion:str:Christianity} Vertices found: 1 ----- Vertices with name *Obama* ----- Vertex ID 1 {name:str:Barack Obama, role:str:political authority, occupation:str:44th president of United States of America, country:str:United States, political party:str:Democratic, religion:str:Christianity} Vertices found: 1
手動索引は、プロパティ・グラフの頂点およびエッジに対して複数の索引の定義をサポートしています。手動索引の場合、索引の要素を手動で挿入、取得および選択する必要があります。
プロパティ・グラフに対する手動索引を記述する場合、次のOracleプロパティ・グラフ・メソッドを使用して手動索引を追加、削除および操作します。
OraclePropertyGraph.createIndex(String name, Class elementClass, Parameter[] parameters)
: elementClass型の要素すべてに指定した名前を使用して手動索引を作成します。
OraclePropertyGraph.dropIndex(String name)
: 特定の手動索引を削除します。
OraclePropertyGraph.getIndex(String name, Class elementClass)
: elementClass型の特定の手動索引の索引インスタンスを取得します。
OraclePropertyGraph.getIndices()
: プロパティ・グラフ内で作成したすべての手動で索引の索引インスタンスの配列を取得します。
提供されているExampleNoSQL7
およびExampleHBase7
の例では、入力ファイルからプロパティ・グラフを作成し、エッジに手動テキスト索引を作成し、いくつかのデータを索引に含めて、Apache SolrCloudを使用していくつかのテキスト検索問合せを実行します。
SolrCloudを使用する場合、「ZookeeperへのコレクションのSolrCloud構成のアップロード」で説明されているように、最初にテキスト索引のためのコレクションの構成をApache Zookeeperにロードする必要があります。
次のコード・フラグメントは、4つのシャード(ノードごとに1つのシャード)とレプリケーション係数1を使用して既存のプロパティ・グラフに手動テキスト索引を作成します。シャードの数は、SolrCloudクラスタ上のノードの数と一致します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args, szGraphName); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // Do a parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create a manual text index using SolrCloud// Specify Index Directory parameters: configuration name, Solr Server URL, Solr Node set, // replication factor, zookeeper timeout (secs), // maximum number of shards per node, // number of connections to database, batch size, commit size, // write timeout (in secs) String configName = "opgconfig"; String solrServerUrl = "nodea:2181/solr" String solrNodeSet = "nodea:8983_solr,nodeb:8983_solr," + "nodec:8983_solr,noded:8983_solr"; int zkTimeout = 15; int numShards = 4; int replicationFactor = 1; int maxShardsPerNode = 1; OracleIndexParameters indexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout, numShards, replicationFactor, maxShardsPerNode, 4, 10000, 500000, 15); opg.setDefaultIndexParameters(indexParams); // Create manual indexing on above properties for all vertices OracleIndex<Edge> index = ((OracleIndex<Edge>) opg.createIndex("myIdx", Edge.class)); Vertex v1 = opg.getVertices("name", "Barack Obama").iterator().next(); Iterator<Edge> edges = v1.getEdges(Direction.OUT, "collaborates").iterator(); while (edges.hasNext()) { Edge edge = edges.next(); Vertex vIn = edge.getVertex(Direction.IN); index.put("collaboratesWith", vIn.getProperty("name"), edge); }
次のコード・フラグメントは、手動索引に対して問合せを実行して、キー値ペアcollaboratesWith:Beyonce
を持つすべてのエッジを取得します。さらに、get APIコールでuseWildCards
パラメータを指定することにより、ワイルドカード検索がサポートされます。
// Find all edges with collaboratesWith Beyonce. // Wildcard searching is supported using true parameter. edges = index.get("collaboratesWith", "Beyonce").iterator(); System.out.println("----- Edges with name Beyonce -----"); countE = 0; while (edges.hasNext()) { System.out.println(edges.next()); countE++; } System.out.println("Edges found: "+ countE); // Find all vertices with name including Bey*. // Wildcard searching is supported using true parameter. edges = index.get("collaboratesWith", "*Bey*", true).iterator(); System.out.println("----- Edges with collaboratesWith Bey* -----"); countE = 0; while (edges.hasNext()) { System.out.println(edges.next()); countE++; } System.out.println("Edges found: " + countE);
前述のコード例では、次のような出力が生成されます。
----- Edges with name Beyonce ----- Edge ID 1000 from Vertex ID 1 {country:str:United States, name:str:Barack Obama, occupation:str:44th president of United States of America, political party:str:Democratic, religion:str:Christianity, role:str:political authority} =[collaborates]=> Vertex ID 2 {country:str:United States, music genre:str:pop soul , name:str:Beyonce, role:str:singer actress} edgeKV[{weight:flo:1.0}] Edges found: 1 ----- Edges with collaboratesWith Bey* ----- Edge ID 1000 from Vertex ID 1 {country:str:United States, name:str:Barack Obama, occupation:str:44th president of United States of America, political party:str:Democratic, religion:str:Christianity, role:str:political authority} =[collaborates]=> Vertex ID 2 {country:str:United States, music genre:str:pop soul , name:str:Beyonce, role:str:singer actress} edgeKV[{weight:flo:1.0}] Edges found: 1
自動および手動テキスト索引に対してテキスト検索問合せを実行できます。これらの機能は、特定のキー/値ペアに基づく問合せと、(ワイルドカード、ファジー検索および範囲問合せなどの拡張問合せオプションを使用した)単一または複数のキーに対するテキスト検索の実行とでは異なります。
Apache Luceneを使用したテキスト索引に対する索引問合せの実行
SolrCloudを使用したテキスト索引に対する索引問合せの実行
Apache Luceneを使用したテキスト索引に対する索引問合せの実行
次のコード・フラグメントは、Apache Luceneを使用して自動索引を作成し、特定のキー/値ペアを指定してテキスト索引に対する問合せを実行します。
// Do a parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create an automatic index using Apache Lucene engine. // Specify Index Directory parameters (number of directories, // number of connections to database, batch size, commit size, // enable datatypes, location) OracleIndexParameters indexParams = OracleIndexParameters.buildFS(4, 4, 10000, 50000, true, "/home/data/text-index "); opg.setDefaultIndexParameters(indexParams); // Create manual indexing on above properties for all vertices OracleIndex<Edge> index = ((OracleIndex<Edge>) opg.createIndex("myIdx", Edge.class)); Vertex v1 = opg.getVertices("name", "Barack Obama").iterator().next(); Iterator<Edge> edges = v1.getEdges(Direction.OUT, "collaborates").iterator(); while (edges.hasNext()) { Edge edge = edges.next(); Vertex vIn = edge.getVertex(Direction.IN); index.put("collaboratesWith", vIn.getProperty("name"), edge); index.put("country", vIn.getProperty("country"), edge); } // Wildcard searching is supported using true parameter. Iterator<Edge> edges = index.get("country", "United States").iterator(); System.out.println("----- Edges with query: " + queryExpr + " -----"); long countE = 0; while (edges.hasNext()) { System.out.println(edges.next()); countE++; } System.out.println("Edges found: "+ countE);
この場合、テキスト索引により、キーおよび値オブジェクトから索引問合せが生成されます。また、useWildcards
フラグが指定または有効化されていない場合、取得される結果には正確な一致のみが含まれます。値オブジェクトが数値または日時値である場合、生成される問合せは、値によって下限および上限が定義されているかどうかとは関係なく、両端を含む範囲問合せになります。数値または日時の一致のみが取得されます。
値が文字列である場合、データ型とは関係なく一致するすべてのキー/値ペアが取得されます。このタイプの問合せの結果として生成されるテキスト問合せは、オプションの検索条件セット(サポート対象のデータ型ごとに1つずつ)が含まれるブール問合せです。データ型の処理の詳細は、「データ型の処理」を参照してください。
したがって、前のコード例では、問合せ式country1:"United States" OR country9:"United States" OR … OR countryE:"United States" (Luceneのデータ型処理が有効である場合)、または country:"1United States" OR country:"2United States" OR … OR country:"EUnited States" (Luceneのデータ型処理が無効である場合)を生成します。
文字列値オブジェクトでワイルドカードが有効である場合、値はApache Lucene構文を使用して書き込む必要があります。Apache Luceneを使用したテキスト検索構文の詳細は、https://lucene.apache.org/core/2_9_4/queryparsersyntax.htmlを参照してください
問合せの実行対象のデータ型クラスを指定することにより、一致するキー/値ペアのデータ型をフィルタできます。次のコード・フラグメントは、文字列データ型のみを持つ単一のキー/値ペアを使用してテキスト索引に対して問合せを実行します。次のコードは、問合せ式country1:"United States" (Luceneのデータ型処理が有効である場合)またはcountry:"1United States" (Luceneのデータ型処理が無効である場合)を生成します。
// Wildcard searching is supported using true parameter. Iterator<Edge> edges = index.get("country", "United States", true, String.class).iterator(); System.out.println("----- Edges with query: " + queryExpr + " -----"); long countE = 0; while (edges.hasNext()) { System.out.println(edges.next()); countE++; } System.out.println("Edges found: "+ countE);
ブール演算子を使用して処理する場合は、問合せで適切な一致が見つかるように、後続の各キー/値ペアにデータ型の接頭辞/接尾辞を追加する必要があります。自動および手動テキスト索引に必要な問合せ構文およびデータ型識別子を使用して独自のLuceneテキスト検索問合せを作成するユーザーを支援するためにユーティリティが用意されています。
LuceneIndex
内のメソッドbuildSearchTerm(key, value, dtClass)
は、キー(または値)にデータ型識別子を追加し、特定のデータ型およびApache Luceneのデータ型処理構成に基づいて値を必要な文字列表現に変換することにより、field:query_expr形式の問合せ式を作成します。
次のコード・フラグメントは、buildSearchTerm
メソッドを使用して、前の例で使用した問合せ式country1:United* (Luceneのデータ型処理が有効である場合)またはcountry:1United* (Luceneのデータ型処理が無効である場合)を生成します。
String szQueryStrCountry = index.buildSearchTerm("country", "United*", String.class);
キーおよび値を個別オブジェクトとして扱ってWildcardQuery
のような異なるLucene問合せを構築するために、LuceneIndex
内のメソッドappendDatatypesSuffixToKey(key, dtClass)
およびappendDatatypesSuffixToValue(value, dtClass)
は、適切なデータ型識別子を追加し、特定のデータ型に基づいて値を必要なLucene文字列表現に変換します。
次のコード・フラグメントは、appendDatatypesSuffixToKey
メソッドを使用してLuceneテキスト問合せで必要なフィールド名を生成します。Luceneのデータ型処理が有効である場合、返される文字列により、文字列データ型識別子がキー(country1
)の接尾辞として追加されます。それ以外の場合、取得された文字列は元のキー(country
)になります。
String key = index.appendDatatypesSuffixToKey("country", String.class);
次のコード・フラグメントは、appendDatatypesSuffixToValueメソッドを使用して、Luceneテキスト問合せで必要な問合せ本体式を生成します。Luceneのデータ型処理が無効である場合、返される文字列により、文字列データ型識別子がキー(1United*)の接頭辞として追加されます。他のすべての場合、返される文字列は、値の文字列表現(United*)になります。
String value = index.appendDatatypesSuffixToValue("United*", String.class);
LuceneIndex
は、メソッドbuildSearchTermObject(key, value, dtClass)
を使用した条件オブジェクトの生成もサポートしています。条件オブジェクトは通常、取得対象のドキュメントのフィールドおよび値を制約するためにLucene問合せオブジェクトの様々な型の間で使用されます。次のコード・フラグメントは、buildSearchTermObject
メソッドを使用してWildcardQuery
オブジェクトを作成する方法を示します。
Term term = index.buildSearchTermObject("country", "United*", String.class); Query query = new WildcardQuery(term);
SolrCloudを使用したテキスト索引に対する索引問合せの実行
次のコード・フラグメントは、SolrCloudを使用して自動索引を作成し、特定のキー/値ペアを指定してテキスト索引に対する問合せを実行します。
// Create a manual text index using SolrCloud// Specify Index Directory parameters: configuration name, Solr Server URL, Solr Node set, // replication factor, zookeeper timeout (secs), // maximum number of shards per node, // number of connections to database, batch size, commit size, // write timeout (in secs) String configName = "opgconfig"; String solrServerUrl = "nodea:2181/solr" String solrNodeSet = "nodea:8983_solr,nodeb:8983_solr," + "nodec:8983_solr,noded:8983_solr"; int zkTimeout = 15; int numShards = 4; int replicationFactor = 1; int maxShardsPerNode = 1; OracleIndexParameters indexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout, numShards, replicationFactor, maxShardsPerNode, 4, 10000, 500000, 15); opg.setDefaultIndexParameters(indexParams); // specify indexed keys String[] indexedKeys = new String[4]; indexedKeys[0] = "name"; indexedKeys[1] = "role"; indexedKeys[2] = "religion"; indexedKeys[3] = "country"; // Create auto indexing on above properties for all vertices opg.createKeyIndex(indexedKeys, Vertex.class); // Create manual indexing on above properties for all vertices OracleIndex<Vertex> index = ((OracleIndex<Vertex>) opg.getAutoIndex(Vertex.class); Iterator<Vertex> vertices = index.get("country", "United States").iterator(); System.out.println("----- Vertices with query: " + queryExpr + " -----"); countV = 0; while (vertices.hasNext()) { System.out.println(vertices.next()); countV++; } System.out.println("Vertices found: "+ countV);
この場合、テキスト索引により、値オブジェクトから索引が生成されます。また、useWildcards
フラグが指定または有効化されていない場合、取得される結果には正確な一致のみが含まれます。値オブジェクトが数値または日時値である場合、生成される問合せは、値によって下限および上限が定義されているかどうかとは関係なく、両端を含む範囲問合せになります。数値または日時の一致のみが取得されます。
値が文字列である場合、データ型とは関係なく一致するすべてのキー/値ペアが取得されます。このタイプの問合せの結果として生成されるテキスト問合せは、オプションの検索条件セット(サポート対象のデータ型ごとに1つずつ)が含まれるブール問合せです。データ型の処理の詳細は、「データ型の処理」を参照してください。
したがって、前のコード例では、問合せ式country_str:"United States" OR country_ser:"United States" OR … OR country_json:"United States"を生成します。
ワイルドカードが有効な状態で文字列値オブジェクトを使用するには、値がApache Lucene構文を使用して書き込まれる必要があります。Apache Luceneを使用したテキスト検索構文の詳細は、「データ型の処理」を参照してください
問合せの実行対象のデータ型クラスを指定することにより、一致するキー/値ペアのデータ型をフィルタできます。次のコード・フラグメントは、文字列データ型のみを持つ単一のキー/値ペアを使用してテキスト索引に対して問合せを実行します。次のコードは、問合せ式country_str:"United States"を作成します。
// Wildcard searching is supported using true parameter. Iterator<Edge> edges = index.get("country", "United States", true, String.class).iterator(); System.out.println("----- Edges with query: " + queryExpr + " -----"); countE = 0; while (edges.hasNext()) { System.out.println(edges.next()); countE++; } System.out.println("Edges found: "+ countE);
ブール演算子を使用して処理する場合は、問合せで適切な一致が見つかるように、後続の各キー/値ペアにデータ型の接頭辞/接尾辞を追加する必要があります。自動および手動テキスト索引に必要な問合せ構文およびデータ型識別子を使用して独自のSolrCloudテキスト検索問合せを作成するユーザーを支援するためにユーティリティ・セットが用意されています。
SolrIndex
内のメソッドbuildSearchTerm(key, value, dtClass)
は、キー(または値)にデータ型識別子を追加し、索引に必要なデータ型形式を使用して値を必要な文字列表現に変換することにより、field:query_expr形式の問合せ式を作成します。
次のコード・フラグメントは、buildSearchTerm
メソッドを使用して、前の例で使用した問合せ式country_str:United*を作成します。
String szQueryStrCountry = index.buildSearchTerm("country", "United*", String.class);
キーおよび値を個別オブジェクトとして扱ってWildcardQuery
のような異なるSolrClud問合せを構築するために、SolrIndex
内のメソッドappendDatatypesSuffixToKey(key, dtClass)
およびappendDatatypesSuffixToValue(value, dtClass)
は、適切なデータ型識別子を追加し、特定のデータ型に基づいてキーおよび値を必要なSolrCloud文字列表現に変換します。
次のコード・フラグメントは、appendDatatypesSuffixToKey
メソッドを使用してSolrCloudテキスト問合せで必要なフィールド名を生成します。取得した文字列は、文字列データ型識別子をキーの接尾辞(country_str
)として追加します。
String key = index.appendDatatypesSuffixToKey("country", String.class);
次のコード・フラグメントは、appendDatatypesSuffixToValue
メソッドを使用して、SolrCloudテキスト問合せで必要な問合せ本体式を生成します。返される文字列は、値の文字列表現(United*
)になります。
String value = index.appendDatatypesSuffixToValue("United*", String.class);
Oracleのプロパティ・グラフ・サポートは、値のデータ型に基づいて要素のキー/値ペアを索引付けおよび格納します。データ型処理の主な目的は、数値や日付範囲の問合せなど、包括的な問合せのサポートを提供することです。
デフォルトでは、特定のキー/値ペアに対する検索は、その値のデータ型に基づく問合せ式まで行われます。たとえば、キー値ペアage:30
を持つ頂点を検索する場合は、整数のデータ型が指定されたすべての年齢フィールドに対して問合せが実行されます。値が問合せ式である場合は、API get(String key, Object value, Class dtClass, Boolean useWildcards)
をコールすることにより、検索する値のデータ型クラスも指定できます。データ型が指定されていない場合、問合せ式はすべての使用可能なデータ型と一致します。
ブール演算子を使用して処理する場合は、問合せで適切な一致が見つかるように、後続の各キー/値ペアにデータ型の接頭辞/接尾辞を追加する必要があります。次の各トピックでは、Apache LuceneおよびSolrCloudでこの接頭辞/接尾辞を追加する方法について説明します。
Luceneのデータ型処理が有効化されている場合、問合せ式のキーの接尾辞として適切なデータ型識別子を追加する必要があります。これは、キーに対してString.concat()
の演算を実行することによって行うことができます。Luceneのデータ型処理が無効化されている場合、データ型識別子を値Stringに接頭辞として挿入する必要があります。表5-1は、Apache Luceneを使用したテキスト索引付けに使用可能なデータ型識別子を示しています(LuceneIndex
のJavadocも参照)。
表5-2 Apache Luceneデータ型識別子
Luceneデータ型識別子 | 説明 |
---|---|
TYPE_DT_STRING |
String |
TYPE_DT_BOOL |
Boolean |
TYPE_DT_DATE |
Date |
TYPE_DT_FLOAT |
Float |
TYPE_DT_DOUBLE |
Double |
TYPE_DT_INTEGER |
Integer |
TYPE_DT_LONG |
Long |
TYPE_DT_CHAR |
Character |
TYPE_DT_SHORT |
Short |
TYPE_DT_BYTE |
Byte |
TYPE_DT_SPATIAL |
Spatial |
TYPE_DT_SERIALIZABLE |
Serializable |
次のコード・フラグメントは、Luceneのデータ型処理を使用してエッジに手動索引を作成し、データを追加してから、手動索引に対して問合せを実行し、ワイルドカードを使用してキー/値ペアcollaboratesWith:Beyonce AND country1:United*
を持つすべてのエッジを取得します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args,
szGraphName);
String szOPVFile = "../../data/connections.opv";
String szOPEFile = "../../data/connections.ope";
// Do a parallel data loading
OraclePropertyGraphDataLoader opgdl =
OraclePropertyGraphDataLoader.getInstance();
opgdl.loadData(opg, szOPVFile, szOPEFile, dop);
// Specify Index Directory parameters (number of directories,
// number of connections to database, batch size, commit size,
// enable datatypes, location)
OracleIndexParameters indexParams =
OracleIndexParameters.buildFS(4, 4, 10000, 50000, true,
"/home/data/text-index ");
opg.setDefaultIndexParameters(indexParams);
// Create manual indexing on above properties for all edges
OracleIndex<Edge> index = ((OracleIndex<Edge>) opg.createIndex("myIdx", Edge.class));
Vertex v1 = opg.getVertices("name", "Barack Obama").iterator().next();
Iterator<Edge> edges
= v1.getEdges(Direction.OUT, "collaborates").iterator();
while (edges.hasNext()) {
Edge edge = edges.next();
Vertex vIn = edge.getVertex(Direction.IN);
index.put("collaboratesWith", vIn.getProperty("name"), edge);
index.put("country", vIn.getProperty("country"), edge);
}
// Wildcard searching is supported using true parameter.
String key = "country";
key = key.concat(String.valueOf(oracle.pg.text.lucene.LuceneIndex.TYPE_DT_STRING));
String queryExpr = "Beyonce AND " + key + ":United*";
edges = index.get("collaboratesWith", queryExpr, true /*UseWildcard*/).iterator();
System.out.println("----- Edges with query: " + queryExpr + " -----");
countE = 0;
while (edges.hasNext()) {
System.out.println(edges.next());
countE++;
}
System.out.println("Edges found: "+ countE);
前述のコード例では、次のような出力が生成される可能性があります。
----- Edges with name Beyonce AND country1:United* ----- Edge ID 1000 from Vertex ID 1 {country:str:United States, name:str:Barack Obama, occupation:str:44th president of United States of America, political party:str:Democratic, religion:str:Christianity, role:str:political authority} =[collaborates]=> Vertex ID 2 {country:str:United States, music genre:str:pop soul , name:str:Beyonce, role:str:singer actress} edgeKV[{weight:flo:1.0}] Edges found: 1
次のコード・フラグメントは、頂点に自動索引を作成し、Luceneのデータ型処理を無効化し、データを追加してから、前の例からの手動索引に対して問合せを実行し、ワイルドカードを使用してキー/値ペアcountry:United* AND role:1*political*
を持つすべての頂点を取得します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args,
szGraphName);
String szOPVFile = "../../data/connections.opv";
String szOPEFile = "../../data/connections.ope";
// Do a parallel data loading
OraclePropertyGraphDataLoader opgdl =
OraclePropertyGraphDataLoader.getInstance();
opgdl.loadData(opg, szOPVFile, szOPEFile, dop);
// Create an automatic index using Apache Lucene engine.
// Specify Index Directory parameters (number of directories,
// number of connections to database, batch size, commit size,
// enable datatypes, location)
OracleIndexParameters indexParams =
OracleIndexParameters.buildFS(4, 4, 10000, 50000, false, "/ home/data/text-index ");
opg.setDefaultIndexParameters(indexParams);
// specify indexed keys
String[] indexedKeys = new String[4];
indexedKeys[0] = "name";
indexedKeys[1] = "role";
indexedKeys[2] = "religion";
indexedKeys[3] = "country";
// Create auto indexing on above properties for all vertices
opg.createKeyIndex(indexedKeys, Vertex.class);
// Wildcard searching is supported using true parameter.
String value = "*political*";
value = String.valueOf(LuceneIndex.TYPE_DT_STRING) + value;
String queryExpr = "United* AND role:" + value;
vertices = opg.getVertices("country", queryExpr, true /*useWildcard*/).iterator();
System.out.println("----- Vertices with query: " + queryExpr + " -----");
countV = 0;
while (vertices.hasNext()) {
System.out.println(vertices.next());
countV++;
}
System.out.println("Vertices found: " + countV);
前述のコード例では、次のような出力が生成される可能性があります。
----- Vertices with query: United* and role:1*political* ----- Vertex ID 30 {name:str:Jerry Brown, role:str:political authority, occupation:str:34th and 39th governor of California, country:str:United States, political party:str:Democratic, religion:str:roman catholicism} Vertex ID 24 {name:str:Edward Snowden, role:str:political authority, occupation:str:system administrator, country:str:United States, religion:str:buddhism} Vertex ID 22 {name:str:John Kerry, role:str:political authority, country:str:United States, political party:str:Democratic, occupation:str:68th United States Secretary of State, religion:str:Catholicism} Vertex ID 21 {name:str:Hillary Clinton, role:str:political authority, country:str:United States, political party:str:Democratic, occupation:str:67th United States Secretary of State, religion:str:Methodism} Vertex ID 19 {name:str:Kirsten Gillibrand, role:str:political authority, country:str:United States, political party:str:Democratic, occupation:str:junior United States Senator from New York, religion:str:Methodism} Vertex ID 13 {name:str:Ertharin Cousin, role:str:political authority, country:str:United States, political party:str:Democratic} Vertex ID 11 {name:str:Eric Holder, role:str:political authority, country:str:United States, political party:str:Democratic, occupation:str:United States Deputy Attorney General} Vertex ID 1 {name:str:Barack Obama, role:str:political authority, occupation:str:44th president of United States of America, country:str:United States, political party:str:Democratic, religion:str:Christianity} Vertices found: 8
SolrCloudテキスト索引のブール演算では、問合せ式のキーの接尾辞として適切なデータ型識別子を追加する必要があります。これは、キーに対してString.concat()
の演算を実行することによって行うことができます。表5-3は、SolrCloudを使用したテキスト索引付けに使用可能なデータ型識別子を示しています(SolrIndex
のJavadocも参照)。
表5-3 SolrCloudデータ型識別子
Solrデータ型識別子 | 説明 |
---|---|
TYPE_DT_STRING |
String |
TYPE_DT_BOOL |
Boolean |
TYPE_DT_DATE |
Date |
TYPE_DT_FLOAT |
Float |
TYPE_DT_DOUBLE |
Double |
TYPE_DT_INTEGER |
Integer |
TYPE_DT_LONG |
Long |
TYPE_DT_CHAR |
Character |
TYPE_DT_SHORT |
Short |
TYPE_DT_BYTE |
Byte |
TYPE_DT_SPATIAL |
Spatial |
TYPE_DT_SERIALIZABLE |
Serializable |
次のコード・フラグメントは、SolrCloudを使用してエッジに手動索引を作成し、データを追加してから、手動索引に対して問合せを実行し、ワイルドカードを使用してキー/値ペアcollaboratesWith:Beyonce AND country1:United*
を持つすべてのエッジを取得します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args, szGraphName); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // Do a parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create a manual text index using SolrCloud// Specify Index Directory parameters: configuration name, Solr Server URL, Solr Node set, // replication factor, zookeeper timeout (secs), // maximum number of shards per node, // number of connections to database, batch size, commit size, // write timeout (in secs) String configName = "opgconfig"; String solrServerUrl = "nodea:2181/solr"; String solrNodeSet = "nodea:8983_solr,nodeb:8983_solr," + "nodec:8983_solr,noded:8983_solr"; int zkTimeout = 15; int numShards = 4; int replicationFactor = 1; int maxShardsPerNode = 1; OracleIndexParameters indexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout, numShards, replicationFactor, maxShardsPerNode, 4, 10000, 500000, 15); opg.setDefaultIndexParameters(indexParams); // Create manual indexing on above properties for all vertices OracleIndex<Edge> index = ((OracleIndex<Edge>) opg.createIndex("myIdx", Edge.class)); Vertex v1 = opg.getVertices("name", "Barack Obama").iterator().next(); Iterator<Edge> edges = v1.getEdges(Direction.OUT, "collaborates").iterator(); while (edges.hasNext()) { Edge edge = edges.next(); Vertex vIn = edge.getVertex(Direction.IN); index.put("collaboratesWith", vIn.getProperty("name"), edge); index.put("country", vIn.getProperty("country"), edge); } // Wildcard searching is supported using true parameter. String key = "country"; key = key.concat(oracle.pg.text.solr.SolrIndex.TYPE_DT_STRING); String queryExpr = "Beyonce AND " + key + ":United*"; edges = index.get("collaboratesWith", queryExpr, true /** UseWildcard*/).iterator(); System.out.println("----- Edges with query: " + queryExpr + " -----"); countE = 0; while (edges.hasNext()) { System.out.println(edges.next()); countE++; } System.out.println("Edges found: "+ countE);
前述のコード例では、次のような出力が生成される可能性があります。
----- Edges with name Beyonce AND country_str:United* ----- Edge ID 1000 from Vertex ID 1 {country:str:United States, name:str:Barack Obama, occupation:str:44th president of United States of America, political party:str:Democratic, religion:str:Christianity, role:str:political authority} =[collaborates]=> Vertex ID 2 {country:str:United States, music genre:str:pop soul , name:str:Beyonce, role:str:singer actress} edgeKV[{weight:flo:1.0}] Edges found: 1
Oracle Big Data Spatial and Graphプロパティ・グラフでSolrCloudテキスト索引を使用する前に、コレクションの構成をZookeeperにアップロードする必要があります。これは、SolrCloudクラスタ・ノードのいずれかでZkCliツールを使用して実行できます。
事前定義済のコレクション構成ディレクトリは、インストール・ホームの下にあるdal/opg-solr-config
にあります。次に、PropertyGraph構成ディレクトリのアップロード方法の例を示します。
インストール・ホームの下にあるdal/opg-solr-configを、Solrクラスタ・ノードのいずれかにある/tmpディレクトリにコピーします。次に例を示します。
scp –r dal/opg-solr-config user@solr-node:/tmp
同じノードでZkCliツールを使用して、次の例のように次のコマンドを実行します。
$SOLR_HOME/bin/zkcli.sh -zkhost 127.0.0.1:2181/solr -cmd upconfig –confname opgconfig -confdir /tmp/opg-solr-config
Oracleのプロパティ・グラフ・サポートは、Apache LuceneおよびSolrCloudとの統合によって手動および自動テキスト索引を管理します。作成時に、テキスト検索で使用される検索エンジンとその他の構成設定を指定するOracleIndexParameters
オブジェクトを作成する必要があります。プロパティ・グラフのテキスト索引が作成された後、これらの構成設定を変更することはできません。自動索引の場合、すべての頂点索引キーは単一のテキスト索引によって管理され、すべてのエッジ索引キーは最初の頂点またはエッジ・キーが索引付けされるときに指定された構成を使用して、異なるテキスト索引によって管理されます。
構成設定を変更する必要がある場合は、最初に現在の索引を無効にしてから、新しいOracleIndexParameters
オブジェクトを使用してそれを再度作成する必要があります。次のコード・フラグメントは、既存のプロパティ・グラフに対して2つのApache Luceneベースの自動索引(頂点およびエッジ)を作成し、それらを無効にしてから、SolrCloudを使用するために再作成します。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // Do parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create an automatic index using Apache Lucene. // Specify Index Directory parameters (number of directories, // number of connections to database, batch size, commit size, // enable datatypes, location) OracleIndexParameters luceneIndexParams = OracleIndexParameters.buildFS(4, 4, 10000, 50000, true, "/home/oracle/text-index "); // Specify indexed keys String[] indexedKeys = new String[4]; indexedKeys[0] = "name"; indexedKeys[1] = "role"; indexedKeys[2] = "religion"; indexedKeys[3] = "country"; // Create auto indexing on above properties for all vertices opg.createKeyIndex(indexedKeys, Vertex.class, luceneIndexParams.getParameters()); // Create auto indexing on weight for all edges opg.createKeyIndex("weight", Edge.class, luceneIndexParams.getParameters()); // Disable auto indexes to change parameters opg.getOracleIndexManager().disableVertexAutoIndexer(); opg.getOracleIndexManager().disableEdgeAutoIndexer(); // Recreate text indexes using SolrCloud // Specify Index Directory parameters: configuration name, Solr Server URL, Solr Node set, // replication factor, zookeeper timeout (secs), // maximum number of shards per node, // number of connections to database, batch size, commit size, // write timeout (in secs) String configName = "opgconfig"; String solrServerUrl = "nodea:2181/solr"; String solrNodeSet = "nodea:8983_solr,nodeb:8983_solr," + "nodec:8983_solr,noded:8983_solr"; int zkTimeout = 15; int numShards = 4; int replicationFactor = 1; int maxShardsPerNode = 1; OracleIndexParameters solrIndexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout, numShards, replicationFactor, maxShardsPerNode, 4, 10000, 500000, 15); // Create auto indexing on above properties for all vertices opg.createKeyIndex(indexedKeys, Vertex.class, solrIndexParams.getParameters()); // Create auto indexing on weight for all edges opg.createKeyIndex("weight", Edge.class, solrIndexParams.getParameters());
Oracle Big Data Spatial and Graphのテキスト索引では、パラレル問合せ実行を使用して、特定のキー/値またはキー/テキスト・ペア別に数百万の頂点およびエッジに対してテキスト問合せを実行できます。
パラレル・テキスト問合せは、SolrCloud(またはApache Luceneのサブディレクトリ)内のシャード間での索引データの配分を利用する最適化されたソリューションであり、各シャードは別個の索引接続を使用して問い合せられます。これには、読取り操作のパフォーマンスを向上させて索引から複数の要素を取得するために、複数のスレッドとSolrCloud (またはApache Lucene)検索エンジンへの接続が関連します。このアプローチでは、スコアに基づく一致結果のランク付けは行われません。
パラレル・テキスト問合せでは、各要素がシャードからの指定されたK/Vペアに一致する属性を持つすべての頂点(またはエッジ)を保持する配列が生成されます。問い合せられたシャードのサブセットは、特定の開始サブディレクトリIDと指定された接続の配列のサイズによって区切られます。これにより、サブセットは[開始, 開始 - 1 + 接続の配列のサイズ]の範囲内のシャードを考慮します。Nシャードを含む索引にあるすべてのシャードに、([0, N - 1]の範囲の)整数IDが割り当てられることに注意してください。
Apache Luceneを使用したパラレル・テキスト問合せ
LuceneIndex
でgetPartitioned
メソッドを呼び出して、サブディレクトリのセットへの接続の配列(SearcherManager
オブジェクト)、検索するキー/値ペア、および開始サブディレクトリIDを指定することにより、Apache Luceneを使用したパラレル・テキスト問合せを使用できます。各サブディレクトリは索引のその他のサブディレクトリに依存していないため、各接続が適切なサブディレクトリにリンクしている必要があります。
次のコード・フラグメントは、Apache Lucene検索エンジンを使用して自動テキスト索引を生成し、パラレル・テキスト問合せを実行します。LuceneIndex
クラスでのgetPartitioned
メソッドの呼出し数は、サブディレクトリの合計数と使用される接続の数によって制御されます。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create an automatic index OracleIndexParameters indexParams = OracleIndexParameters.buildFS(dop /* number of directories */, dop /* number of connections used when indexing */, 10000 /* batch size before commit*/, 500000 /* commit size before Lucene commit*/, true /* enable datatypes */, "./lucene-index" /* index location */); opg.setDefaultIndexParameters(indexParams); // Create auto indexing on name property for all vertices System.out.println("Create automatic index on name for vertices"); opg.createKeyIndex("name", Vertex.class); // Get the LuceneIndex object SearcherManager[] conns = new SearcherManager[dop]; LuceneIndex<Vertex> index = (LuceneIndex<Vertex>) opg.getAutoIndex(Vertex.class); long lCount = 0; for (int split = 0; split < index.getTotalShards(); split += conns.length) { // Gets a connection object from subdirectory split to //(split + conns.length) for (int idx = 0; idx < conns.length; idx++) { conns[idx] = index.getOracleSearcherManager(idx + split); } // Gets elements from split to split + conns.length Iterable<Vertex>[] iterAr = index.getPartitioned(conns /* connections */, "name"/* key */, "*" /* value */, true /* wildcards */, split /* start split ID */); lCount = countFromIterables(iterAr); /* Consume iterables in parallel */ // Do not close the connections to the subdirectories after completion, // because those connections are used by the LuceneIndex object itself. } // Count all vertices System.out.println("Vertices found using parallel query: " + lCount);
SolrCloudを使用したパラレル・テキスト検索
SolrIndex
でgetPartitioned
メソッドを呼び出して、SolrCloudへの接続の配列(CloudSolrServer
オブジェクト)、検索するキー/値ペア、および開始シャードIDを指定することにより、SolrCloudを使用したパラレル・テキスト問合せを使用できます。
次のコード・フラグメントは、SolrCloud検索エンジンを使用して自動テキスト索引を生成し、パラレル・テキスト問合せを実行します。SolrIndex
クラスでのgetPartitioned
メソッドの呼出し数は、索引内のシャードの合計数と使用される接続の数によって制御されます。
OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); String configName = "opgconfig"; String solrServerUrl = args[4];//"localhost:2181/solr" String solrNodeSet = args[5]; //"localhost:8983_solr"; int zkTimeout = 15; // zookeeper timeout in seconds int numShards = Integer.parseInt(args[6]); // number of shards in the index int replicationFactor = 1; // replication factor int maxShardsPerNode = 1; // maximum number of shards per node // Create an automatic index using SolrCloud OracleIndexParameters indexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout /* zookeeper timeout in seconds */, numShards /* total number of shards */, replicationFactor /* Replication factor */, maxShardsPerNode /* maximum number of shardsper node*/, 4 /* dop used for scan */, 10000 /* batch size before commit*/, 500000 /* commit size before SolrCloud commit*/, 15 /* write timeout in seconds */); opg.setDefaultIndexParameters(indexParams); // Create auto indexing on name property for all vertices System.out.println("Create automatic index on name for vertices"); opg.createKeyIndex("name", Vertex.class); // Get the SolrIndex object SearcherManager[] conns = new SearcherManager[dop]; SolrIndex<Vertex> index = (SolrIndex<Vertex>) opg.getAutoIndex(Vertex.class); // Open an array of connections to handle connections to SolrCloud needed for parallel text search CloudSolrServer[] conns = new CloudSolrServer[dop]; for (int idx = 0; idx < conns.length; idx++) { conns[idx] = index.getCloudSolrServer(15 /* write timeout in secs*/); } // Iterate to cover all the shards in the index long lCount = 0; for (int split = 0; split < index.getTotalShards(); split += conns.length) { // Gets elements from split to split + conns.length Iterable<Vertex>[] iterAr = index.getPartitioned(conns /* connections */, "name"/* key */, "*" /* value */, true /* wildcards */, split /* start split ID */); lCount = countFromIterables(iterAr); /* Consume iterables in parallel */ } // Close the connections to the subdirectories after completed for (int idx = 0; idx < conns.length; idx++) { conns[idx].shutdown(); } // Count results System.out.println("Vertices found using parallel query: " + lCount);
問合せオブジェクトの直接使用は上級ユーザーを対象としており、これらのユーザーは、テキスト索引エンジン(Apache LuceneまたはSolrCloud)の基礎となる問合せ機能を最大限に活用できるようになります。たとえば、一致スコアにboostを追加したりソート句を追加したりするなど、テキスト検索に制約を追加できます。
テキスト検索とともに問合せオブジェクトを使用すると、制約を満たしながら、テキスト問合せと一致する属性(または属性セット)とともにすべての頂点(またはエッジ)を保持する反復可能オブジェクトが作成されます。このアプローチでは、一致スコアに基づいて結果が自動的にランク付けされます。
問合せ本体内で句を構築するには、照合対象のキー/値ペアによって使用されるデータ型、および使用される検索エンジンの構成を考慮する必要がある場合があります。検索条件の構築の詳細は、「データ型の処理」を参照してください。
Apache Luceneを使用したネイティブ問合せオブジェクトの使用
LuceneIndex
でメソッドget(Query)
を呼び出すことにより、Apache Luceneを使用してネイティブ問合せオブジェクトを使用できます。LuceneIndex
でメソッドgetPartitioned(SearcherManager[], Query, int)
を呼び出して、サブディレクトリのセットへの接続の配列(SearcherManager
オブジェクト)、Lucene問合せオブジェクト、および開始サブディレクトリIDを指定することにより、ネイティブ問合せオブジェクトを使用したパラレル・テキスト問合せを使用することもできます。各サブディレクトリは索引のその他のサブディレクトリに依存していないため、各接続が適切なサブディレクトリにリンクしている必要があります。
次のコード・フラグメントは、Apache Lucene検索エンジンを使用して自動テキスト索引を生成し、Lucene問合せを作成し、パラレル・テキスト問合せを実行します。LuceneIndex
クラスでのgetPartitioned
メソッドの呼出し数は、サブディレクトリの合計数と使用される接続の数によって制御されます。
import oracle.pg.text.lucene.LuceneIndex; import org.apache.lucene.search.*; import org.apache.lucene.index.*; ... OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Create an automatic index OracleIndexParameters indexParams = OracleIndexParameters.buildFS(dop /* number of directories */, dop /* number of connections used when indexing */, 10000 /* batch size before commit*/, 500000 /* commit size before Lucene commit*/, true /* enable datatypes */, "./lucene-index" /* index location */); opg.setDefaultIndexParameters(indexParams); // Create auto indexing on name and country properties for all vertices System.out.println("Create automatic index on name and country for vertices"); String[] indexedKeys = new String[2]; indexedKeys[0]="name"; indexedKeys[1]="country"; opg.createKeyIndex(indexedKeys, Vertex.class); // Get the LuceneIndex object LuceneIndex<Vertex> index = (LuceneIndex<Vertex>) opg.getAutoIndex(Vertex.class); // Search first for Key name with property value Beyon* using only string //data types Term term = index.buildSearchTermObject("name", "Beyo*", String.class); Query queryBey = new WildcardQuery(term); // Add another condition to query all the vertices whose country is //"United States" String key = index.appendDatatypesSuffixToKey("country", String.class); String value = index.appendDatatypesSuffixToValue("United States", String.class); Query queryCountry = new PhraseQuery(); StringTokenizer st = new StringTokenizer(value); while (st.hasMoreTokens()) { queryCountry.add(new Term(key, st.nextToken())); }; //Concatenate queries BooleanQuery bQuery = new BooleanQuery(); bQuery.add(queryBey, BooleanClause.Occur.MUST); bQuery.add(queryCountry, BooleanClause.Occur.MUST); long lCount = 0; SearcherManager[] conns = new SearcherManager[dop]; for (int split = 0; split < index.getTotalShards(); split += conns.length) { // Gets a connection object from subdirectory split to //(split + conns.length). Skip the cache so we clone the connection and // avoid using the connection used by the index. for (int idx = 0; idx < conns.length; idx++) { conns[idx] = index.getOracleSearcherManager(idx + split, true /* skip looking in the cache*/ ); } // Gets elements from split to split + conns.length Iterable<Vertex>[] iterAr = index.getPartitioned(conns /* connections */, bQuery, split /* start split ID */); lCount = countFromIterables(iterAr); /* Consume iterables in parallel */ // Do not close the connections to the sub-directories after completed, // as those connections are used by the index itself } // Count all vertices System.out.println("Vertices found using parallel query: " + lCount);
SolrCloudを使用したネイティブ問合せオブジェクトの使用
SolrIndex
でメソッドget(SolrQuery)
を呼び出すことにより、SolrCloudに対してネイティブ問合せオブジェクトを直接使用できます。SolrIndex
でメソッドgetPartitioned(CloudSolrServer[],SolrQuery,int)
を呼び出して、SolrCloudへの接続の配列 (CloudSolrServer
オブジェクト)、SolrQuery
オブジェクト、および開始シャードIDを指定することにより、ネイティブ問合せオブジェクトを使用したパラレル・テキスト問合せを使用することもできます。
次のコード・フラグメントは、Apache SolrCloud検索エンジンを使用して自動テキスト索引を生成し、SolrQuery
オブジェクトを作成し、パラレル・テキスト問合せを実行します。SolrIndex
クラスでのgetPartitioned
メソッドの呼出し数は、サブディレクトリの合計数と使用される接続の数によって制御されます。
import oracle.pg.text.solr.*; import org.apache.solr.client.solrj.*; OraclePropertyGraph opg = OraclePropertyGraph.getInstance( args, szGraphName); // Clear existing vertices/edges in the property graph opg.clearRepository(); String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); String configName = "opgconfig"; String solrServerUrl = args[4];//"localhost:2181/solr" String solrNodeSet = args[5]; //"localhost:8983_solr"; int zkTimeout = 15; // zookeeper timeout in seconds int numShards = Integer.parseInt(args[6]); // number of shards in the index int replicationFactor = 1; // replication factor int maxShardsPerNode = 1; // maximum number of shards per node // Create an automatic index using SolrCloud OracleIndexParameters indexParams = OracleIndexParameters.buildSolr(configName, solrServerUrl, solrNodeSet, zkTimeout /* zookeeper timeout in seconds */, numShards /* total number of shards */, replicationFactor /* Replication factor */, maxShardsPerNode /* maximum number of shardsper node*/, 4 /* dop used for scan */, 10000 /* batch size before commit*/, 500000 /* commit size before SolrCloud commit*/, 15 /* write timeout in seconds */ ); opg.setDefaultIndexParameters(indexParams); // Create auto indexing on name property for all vertices System.out.println("Create automatic index on name and country for vertices"); String[] indexedKeys = new String[2]; indexedKeys[0]="name"; indexedKeys[1]="country"; opg.createKeyIndex(indexedKeys, Vertex.class); // Get the SolrIndex object SolrIndex<Vertex> index = (SolrIndex<Vertex>) opg.getAutoIndex(Vertex.class); // Search first for Key name with property value Beyon* using only string //data types String szQueryStrBey = index.buildSearchTerm("name", "Beyo*", String.class); String key = index.appendDatatypesSuffixToKey("country", String.class); String value = index.appendDatatypesSuffixToValue("United States", String.class); String szQueryStrCountry = key + ":" + value; Solrquery query = new SolrQuery(szQueryStrBey + " AND " + szQueryStrCountry); //Query using get operation index.get(query); // Open an array of connections to handle connections to SolrCloud needed // for parallel text search CloudSolrServer[] conns = new CloudSolrServer[dop]; for (int idx = 0; idx < conns.length; idx++) { conns[idx] = index.getCloudSolrServer(15 /* write timeout in secs*/); } // Iterate to cover all the shards in the index long lCount = 0; for (int split = 0; split < index.getTotalShards(); split += conns.length) { // Gets elements from split to split + conns.length Iterable<Vertex>[] iterAr = index.getPartitioned(conns /* connections */, query, split /* start split ID */); lCount = countFromIterables(iterAr); /* Consume iterables in parallel */ } // Close the connections to SolCloud after completion for (int idx = 0; idx < conns.length; idx++) { conns[idx].shutdown(); } // Count results System.out.println("Vertices found using parallel query: " + lCount);
プロパティ・グラフ・データに対してネイティブ問合せ結果を直接使用すると、ユーザーがテキスト索引エンジン(Apache LuceneまたはSolrCloud)の問合せ機能を最大限に活用できるようになります。この方法により、ユーザーは、テキスト・エンジンに対して様々なタイプの問合せ(ファセット問合せなど)を実行し、取得した結果を頂点(またはエッジ)オブジェクトに解析できます。
問合せ関係とともにテキスト検索を使用すると、特定の結果オブジェクトからすべての頂点を保持するIterable
オブジェクトが生成されます。このアプローチでは、結果セット順序に基づいて結果が自動的にランク付けされます。
Apache LuceneまたはSolrCloud索引に対して検索問合せを直接実行するには、照合対象のキー/値ペアによって使用されるデータ型、および使用される検索エンジンの構成を考慮する必要がある場合があります。検索条件の構築の詳細は、「データ型の処理」を参照してください。
Apache Luceneを使用したネイティブ問合せ結果の使用
SolrCloudを使用したネイティブ問合せ結果の使用
Apache Luceneを使用したネイティブ問合せ結果の使用
LuceneIndex
でメソッドget(TopDocs)
を呼び出すことにより、Apache Luceneを使用してネイティブ問合せ結果を使用できます。TopDocs
オブジェクトには、特定のApache Luceneディレクトリに対するテキスト検索問合せと一致するドキュメント・セットが用意されています。LuceneIndex
は、TopDocs
オブジェクト内で見つかったドキュメントからのすべての頂点(またはエッジ)を保持するIterable
オブジェクトを作成します。
Apache Luceneを使用したOracleプロパティ・グラフ・テキスト索引は、複数のApache Luceneディレクトリを使用して作成されます。索引付けされた頂点およびエッジは、記憶域のスケーラビリティおよび問合せのパフォーマンスを高めるためにディレクトリ間で分散されます。プロパティ・グラフのテキスト索引内のすべてのデータに対して問合せを実行する必要がある場合、各Apache Luceneディレクトリに対して問合せを実行します。LuceneIndex内のAPI getOracleSearcher
を使用することにより、ディレクトリに関連付けられたIndexSearcher
オブジェクトを簡単に取得できます。
次のコード・フラグメントは、Apache Lucene検索エンジンを使用して自動テキスト索引を生成し、Lucene問合せを作成し、これをIndexSearcher
オブジェクトに対して実行してTopDocs
オブジェクトを取得します。後で、特定の結果オブジェクトから頂点のIterable
オブジェクトが作成されます。
import oracle.pg.text.lucene.LuceneIndex;
import org.apache.lucene.search.*;
import org.apache.lucene.index.*;
...
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(
…);
// Create an automatic index
OracleIndexParameters indexParams = OracleIndexParameters.buildFS(dop /* number of directories */,
dop /* number of connections
used when indexing */,
10000 /* batch size before commit*/,
500000 /* commit size before Lucene commit*/,
true /* enable datatypes */,
"./lucene-index" /* index location */);
opg.setDefaultIndexParameters(indexParams);
// Create auto indexing on name and country properties for all vertices
System.out.println("Create automatic index on name and country for vertices");
String[] indexedKeys = new String[2];
indexedKeys[0]="name";
indexedKeys[1]="country";
opg.createKeyIndex(indexedKeys, Vertex.class);
// Get the LuceneIndex object
LuceneIndex<Vertex> index = (LuceneIndex<Vertex>) opg.getAutoIndex(Vertex.class);
// Search first for Key name with property value Beyon* using only string
//data types
Term term = index.buildSearchTermObject("name", "Beyo*", String.class);
Query queryBey = new WildcardQuery(term);
// Add another condition to query all the vertices whose country is
//"United States"
String key = index.appendDatatypesSuffixToKey("country", String.class);
String value = index.appendDatatypesSuffixToValue("United States", String.class);
Query queryCountry = new PhraseQuery();
StringTokenizer st = new StringTokenizer(value);
while (st.hasMoreTokens()) {
queryCountry.add(new Term(key, st.nextToken()));
};
//Concatenate queries
BooleanQuery bQuery = new BooleanQuery();
bQuery.add(queryBey, BooleanClause.Occur.MUST);
bQuery.add(queryCountry, BooleanClause.Occur.MUST);
// Get the IndexSearcher object needed to execute the query.
// The index searcher object is mapped to a single Apache Lucene directory
SearcherManager searcherMgr =
index.getOracleSearcherManager(0, true /* skip looking in the cache*/);
IndexSearcher indexSearcher = searcherMgr.acquire();
// search for the first 1000 results in the current index directory 0
TopDocs docs = index.search(bQuery, 1000);
long lCount = 0;
Iterable<Vertex> it = index.get(docs);
while (it.hasNext()) {
System.out.println(it.next());
lCount++;
}
System.out.println("Vertices found: "+ lCount);
SolrCloudを使用したネイティブ問合せ結果の使用
SolrIndex
でメソッドget(QueryResponse)
を呼び出すことにより、SolrCloudを使用してネイティブ問合せ結果を使用できます。QueryResponse
オブジェクトには、特定のSolrCloud
コレクションに対するテキスト検索問合せと一致するドキュメント・セットが用意されています。SolrIndex
は、QueryResponse
オブジェクト内で見つかったドキュメントからのすべての頂点(またはエッジ)を保持するIterable
オブジェクトを作成します。
次のコード・フラグメントは、Apache SolrCloud検索エンジンを使用して自動テキスト索引を生成し、SolrQuery
オブジェクトを作成し、これをCloudSolrServer
オブジェクトに対して実行してQueryResponse
オブジェクトを取得します。後で、特定の結果オブジェクトから頂点のIterable
オブジェクトが作成されます。
import oracle.pg.text.solr.*;
import org.apache.solr.client.solrj.*;
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(
…);
String configName = "opgconfig";
String solrServerUrl = args[4];//"localhost:2181/solr"
String solrNodeSet = args[5]; //"localhost:8983_solr";
int zkTimeout = 15; // zookeeper timeout in seconds
int numShards = Integer.parseInt(args[6]); // number of shards in the index
int replicationFactor = 1; // replication factor
int maxShardsPerNode = 1; // maximum number of shards per node
// Create an automatic index using SolrCloud
OracleIndexParameters indexParams =
OracleIndexParameters.buildSolr(configName,
solrServerUrl,
solrNodeSet,
zkTimeout /* zookeeper timeout in seconds */,
numShards /* total number of shards */,
replicationFactor /* Replication factor */,
maxShardsPerNode /* maximum number of shardsper node*/,
4 /* dop used for scan */,
10000 /* batch size before commit*/,
500000 /* commit size before SolrCloud commit*/,
15 /* write timeout in seconds */
);
opg.setDefaultIndexParameters(indexParams);
// Create auto indexing on name property for all vertices
System.out.println("Create automatic index on name and country for vertices");
String[] indexedKeys = new String[2];
indexedKeys[0]="name";
indexedKeys[1]="country";
opg.createKeyIndex(indexedKeys, Vertex.class);
// Get the SolrIndex object
SolrIndex<Vertex> index = (SolrIndex<Vertex>) opg.getAutoIndex(Vertex.class);
// Search first for Key name with property value Beyon* using only string
//data types
String szQueryStrBey = index.buildSearchTerm("name", "Beyo*", String.class);
String key = index.appendDatatypesSuffixToKey("country", String.class);
String value = index.appendDatatypesSuffixToValue("United States", String.class);
String szQueryStrCountry = key + ":" + value;
Solrquery query = new SolrQuery(szQueryStrBey + " AND " + szQueryStrCountry);
CloudSolrServer conn = index.getCloudSolrServer(15 /* write timeout in
secs*/);
//Query using get operation
QueryResponse qr = conn.query(query, SolrRequest.METHOD.POST);
Iterable<Vertex> it = index.get(qr);
long lCount = 0;
while (it.hasNext()) {
System.out.println(it.next());
lCount++;
}
System.out.println("Vertices found: "+ lCount);
Oracle Big Data Spatial and Graphは、豊富なグラフ・パターン一致機能セットをサポートしています。
これには、PGQL (Property Graph Query Language)と呼ばれるSQLに似た宣言言語が用意されています。PGQLを使用すると、頂点とエッジ、および頂点とエッジのプロパティに関する制約で構成されたグラフ問合せパターンを表現できます。詳細は、次を参照してください。
プロパティ・グラフ問合せの例を次に示します。これにより、古来の有名な格言である「敵の敵は味方である」から着想を得たグラフ・パターンが定義されます。この例では、変数x
、y
、z
が頂点に使用され、変数e1
、 e2
がエッジに使用されます。エッジ・ラベルに対する制約があり、問合せによって頂点x
およびy
のname
プロパティの値が返されます(予測されます。)。
SELECT x.name, z.name WHERE x -[e1:'feuds']-> y, y -[e2:'feuds']-> z
前の問合せを正常に実行するには、インメモリー・グラフの構築時に、頂点/エッジ・プロパティに加えて、エッジ・ラベルを読み込むために必要なフラグを設定します。Oracle NoSQL Databaseのグラフ構成の例は、次のとおりです。
cfg = GraphConfigBuilder.setName(...) .hasEdgeLabel(true).setLoadEdgeLabel(true) .addEdgeProperty(...).build();
問合せは、Groovyシェル環境で実行することも、Javaから実行することもできます。たとえば、前の問合せをApache HBaseまたはOracle NoSQL Database用のGroovyシェルから実行するには、最初にグラフをデータベースからインメモリー・アナリストに読み込み、インメモリー・グラフを取得し、queryPgql
関数を呼び出します。
// Read graph data from a backend database into memory // Note that opg is an instance of OraclePropertyGraph class opg-hbase> G = session.readGraphWithProperties(opg.getConfig()); opg-hbase> resultSet = G.queryPgql("SELECT x.name, z.name WHERE x -[e1 WITH label = 'feuds']-> y, y -[e2 WITH label = 'feuds']-> z")
結果セット内で最初に予測した変数の型および変数名を取得するには、次を入力できます。
opg-hbase> resultElement = resultElements.get(0) opg-hbase> type = resultElement.getElementType() // STRING opg-hbase> varName = resultElement.getVarName() // x.name
また、結果セットを反復することもできます。次に例を示します。
opg-hbase> resultSet.getResults().each { \ // the variable 'it' is implicitly declared to references each PgqlResult instance }
最後に、結果を表示(出力)できます。たとえば、最初の10の行を表示するには、次のようにします。
opg-hbase> resultSet.print(10) // print the first 10 results
関連項目:
PGQLを使用してインメモリー・グラフに対してパターンマッチング問合せを発行する例は、「グラフを使用したパターンマッチング問合せの使用」を参照してください
Apache Sparkは、大量のデータを効率的に処理することを可能にし、データを処理するためのライブラリ・セット(SQL、MLlib、Spark StreamingおよびDataFrame)が用意されています。Apache Sparkでは、HDFS、Oracle NoSQL DatabaseおよびApache HBaseなどの様々なソースからデータを読み込むことができます。
Oracle NoSQL DatabaseまたはApache HBaseに格納されているグラフ・データに対してApache Sparkジョブを実行するために、ヘルパー・メソッドのセットが用意されています。この方法により、Apache Sparkベースのアプリケーションにグラフを簡単にロードできるため、Spark SQLを使用して情報を問い合せたり、MLlibに用意されている関数を実行したりできるようになります。
インタフェースSparkUtilsBase
には、頂点(およびエッジ)表に格納されている頂点またはエッジの情報をすべて収集するためのメソッドのセットが用意されています。この情報には、頂点(またはエッジ)識別子、プロパティ名と値、およびラベル、入力および出力頂点(エッジの場合のみ)が含まれます。SparkUtils
は、(CDH 5.7および5.9に含まれる) Sparkバージョン1.6を使用します。
SparkUtilsBase
には、バックエンド表からグラフ情報にデータ変換するために次のメソッドが含まれます。
getGraphElementReprOnDB(dbObj)
: バックエンド・データベースに格納されている頂点(またはエッジ)のデータベース表現を取得します。
getElementID(Object graphElementReprOnDB)
: グラフ要素(頂点またはエッジ) IDを取得します。
getPropertyValue(Object graphElementReprOnDB, String key)
: 特定のプロパティ・キーのグラフ要素のプロパティ値を取得します。
getPropertyNames(Object graphElementReprOnDB)
: バックエンド・データベースから特定のグラフ要素表現のプロパティ名のセットを返します。
isElementForVertex(Object graphElementReprOnDB)
: データベース結果から取得した特定のグラフ要素オブジェクトが頂点の表現であるかどうかを検証します。
isElementForEdge(Object graphElementReprOnDB)
: データベース結果から取得した特定のグラフ要素オブジェクトが頂点の表現であるかどうかを検証します。
getInVertexID(Object graphElementReprOnDB)
: エッジのデータベース表現から入力頂点IDを取得します。
getOutVertexID(Object graphElementReprOnDB)
: エッジのデータベース表現から出力頂点IDを取得します。
getEdgeLabel(Object graphElementReprOnDB)
: エッジのデータベース表現からエッジ・ラベルを取得します。
oracle.pg.hbase.SparkUtils
クラスには、Apache HBaseに格納されている<graph_name>VT. (または<graph_name>GE.)表内の行として表現される頂点(またはエッジ)に関する情報を収集するメソッドが含まれます。Apache HBaseでは、表をスキャンする場合、各行には対応するorg.apache.hadoop.hbase.client.Result
オブジェクトがあります。
SparkUtils
を使用してApache Sparkジョブをプロパティ・グラフに対して実行するには、最初にグラフ・データをApache Spark RDDオブジェクトにロードする必要があります。これを行うには、sc
(アプリケーションのSparkコンテキスト)を作成する必要があります。次の例では、Sparkコンテキスト・オブジェクトを作成します。
import org.apache.spark.SparkContext.*; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import oracle.pg.hbase.SparkUtils; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.mapreduce.TableInputFormat; import org.apache.hadoop.conf.Configuration; SparkContext sc = new SparkContext(new SparkConf().setAppName("Example") .setMaster("spark://localhost:7077"));
このコンテキストを使用して、newAPIHadoopRDD
メソッドを呼び出すことにより、HadoopファイルからRDDを簡単に取得できます。これを行うには、Apache HBaseに格納されている頂点およびエッジ表にアクセスするためのHadoop構成オブジェクトを最初に作成する必要があります。構成オブジェクトは、Apache HBaseに接続するために使用するパラメータ(Zookeeper定数、Zookeperクライアント・ポートおよび表名など)を指定します。この構成オブジェクトは、newAPIHadoopRDD
とともにInputFormat
およびそのキーと値のクラスによって使用されます。このメソッドの結果は、RDD[(ImmutableBytesWritable, Result)]
型のRDDになります。
次の例では、Apache HBaseに接続し、グラフの頂点表を読み込むための構成オブジェクトを作成します。socialNetVT.
が、グラフの頂点に関する情報が含まれるApache HBase表の名前であることを前提とします。後で、この構成を使用して頂点表からRDDを取得します。
Configuration hBaseConfVertices = HBaseConfiguration.create(); hBaseConfVertices.set(TableInputFormat.INPUT_TABLE, "socialNetVT.") hBaseConfVertices.set("hbase.zookeeper.quorum", "node041,node042,node043") hBaseConfVertices.set("hbase.zookeeper.port", "2181") JavaPairRDD<ImmutableBytesWritable,Result> bytesResultVertices = sc.newAPIHadoopRDD(hBaseConfVertices, TableInputFormat.class, ImmutableBytesWritable.class, Result.class)
同様に、次の例では、Apache HBaseに格納されているエッジ表に接続し、表の行のRDDを取得するための構成オブジェクトを作成します。socialNetGE.は、エッジ定義が含まれる表の名前です。
Configuration hBaseConfEdges = HBaseConfiguration.create(); hBaseConfEdges.set(TableInputFormat.INPUT_TABLE, "socialNetGE.") hBaseConfEdges.set("hbase.zookeeper.quorum", "node041,node042,node043") hBaseConfEdges.set("hbase.zookeeper.port", "2181") JavaPairRDD<ImmutableBytesWritable,Result> bytesResultEdges = sc.newAPIHadoopRDD(hbaseConfEdges, TableInputFormat.class, ImmutableBytesWritable.class, Result.class)
各結果オブジェクトにはグラフのエッジの各ノードの属性が含まれるため、その情報を抽出するためにこれらのRDDに変換を適用する必要があります。oracle.pg.hbase.SparkUtils
は、このような変換を定義する上で役に立つ複数のメソッドを実装します。
たとえば、結果オブジェクトから各頂点属性値を抽出し、頂点のIDおよび名前を格納するJava BeanクラスであるMyVertex
のオブジェクト・インスタンスを作成する変換を定義できます。次の例では、頂点を表す特定の結果オブジェクトから識別子および名前キー/値ペアを抽出するためにSparkUtils
を使用するメソッドres2vertex
を定義します。
public static MyVertex res2vertex(Result res) throws Exception { SparkUtils su = SparkUtils.getInstance(); Object dbRepr = su.getGraphElementReprOnDB(res); long id = su.getElementId(dbRepr); String name = (String)su.getPropertyValue(dbRepr, "name"); return new MyVertex(id,name); }
メソッドgetGraphElemetReprOnDB
は、Apache HBaseに格納されているグラフ要素表現を返し、パラメータがnullまたは対応するクラスの非インスタンスである場合はIllegalArgumentException
例外をスローします。この表現はデータベース固有(Apache HBaseでのみ使用可能)であり、戻り値はインタフェースに定義されている他のAPIのみによって使用される必要があります。Apache HBaseの場合、dbRepr
はResult
クラスのnull以外のインスタンスです。データベース表現オブジェクトが生成されたら、これを、インタフェースに定義されている他の任意のメソッドのパラメータとして渡すことができます。
メソッドgetElementId
は頂点のIDを返し、メソッドgetPropertyValue
はオブジェクトdbRepr
から属性値name
を取得します。不適切なパラメータが渡された場合、例外IOException
およびjava.text.ParseException
がスローされます。
次の例では、エッジを表す特定の結果オブジェクトから識別子、ラベルおよび入力/出力頂点を抽出するためにSparkUtils
を使用するメソッドres2edge
を定義します。
public static MyEdge res2Edge( Result res) throws Exception { SparkUtils su = SparkUtils.getInstance(); Object dbRepr = su.getGraphElementReprOnDB(res); long rowId = su.getElementId(dbRepr); String label = (String)su.getEdgeLabel(dbRepr); long inVertex = (long)su.getInVertexId(dbRepr); long outVertex = (long)su.getOutVertexId(dbRepr); return new MyEdge(rowId,inVertex,outVertex,label); }
これらの変換が生成されたら、これらをbytesResultVertices
およびbytesResultEdges
の値セットにマップできます。次に例を示します。
JavaRDD<Result> resultVerticesRDD = bytesResult.values(); JavaRDD<Vertex> nodesRDD = resultVerticesRDD.map(result -> MyConverters.res2vertex(result)); JavaRDD<Result> resultEdgesRDD = bytesResultEdges.values(); JavaRDD<Edge> edgesRDD = resultEdgesRDD.map(result -> MyConverters.res2Edge(result));
これにより、Sparkアプリケーションで、nodesRDDおよびedgesRDDの操作を開始できます。たとえば、Spark SQL問合せを実行するために対応するデータ・フレームを作成できます。次の例では、SQLコンテキストを作成し、nodesRDDおよびedgesRDDから2つのデータ・フレームを取得し、ID 1を持つ頂点のすべての友人を取得する問合せを実行します。
SQLContext sqlCtx = new SQLContext(sc); DataFrame verticesDF = sqlCtx.createDataFrame(verticesRDD); verticesDF.registerTempTable("VERTICES_TABLE"); DataFrame edgesDF = sqlCtx.createDataFrame(edgesRDD); edgesDF.registerTempTable("EDGES_TABLE"); sqlCtx.sql("select name from (select target from EDGES_TABLE WHERE source = 1) REACHABLE left join VERTICES_TABLE on VERTICES_TABLE.id = REACHABLE.target ").show();
この場合、SparkではクラスMyVertex
およびMyEdge
を使用してデータ・フレームの列名を探すために、これらのクラスが重要な役割を果たします。
Apache HBaseからグラフ・データを直接読み込んだり、Apache Spark内のグラフに対して操作を実行したりする以外にも、「インメモリー・アナリストを使用したApache Spark内のグラフ・データの分析」で説明されているように、インメモリー・アナリストを使用してApache Spark内のグラフ・データを分析できます。
oracle.pg.nosql.SparkUtils
クラスには、Oracle NoSQL Databaseに格納されている<graph_name>VT_ (または<graph_name>GE_)表内の行として表現される頂点(またはエッジ)に関する情報を収集するメソッドが含まれます。Oracle NoSQL Databaseでは、表をスキャンする場合、表内の各行には対応するoracle.kv.table.Rowオブジェクトがあります。
SparkUtils
を使用してApache Sparkジョブをプロパティ・グラフに対して実行するには、最初にグラフ・データをApache Spark RDDオブジェクトにロードする必要があります。これを行うには、sc
(アプリケーションのSparkコンテキスト)を作成する必要があります。次の例は、Sparkコンテキスト・オブジェクトを作成する方法を示します。
import java.io.*; import org.apache.spark.SparkContext.*; import org.apache.spark.sql.SQLContext; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import org.apache.spark.sql.DataFrame; import oracle.kv.hadoop.table.TableInputFormat; import oracle.kv.table.PrimaryKey; import oracle.kv.table.Row; import org.apache.hadoop.conf.Configuration; SparkConf sparkConf = new SparkConf().setAppName("Testing SparkUtils").setMaster(“local”); JavaSparkContext sc = new JavaSparkContext(sparkConf);
このコンテキストを使用して、newAPIHadoopRDD
メソッドを呼び出すことにより、HadoopファイルからRDDを簡単に取得できます。RDDを作成するには、Oracle NoSQL Databaseに格納されている頂点およびエッジ表にアクセスするためのHadoop構成オブジェクトを最初に作成する必要があります。この構成オブジェクトは、newAPIHadoopRDD
とともにInputFormat
およびそのキーと値のクラスによって使用されます。このメソッドの結果は、RDD[(PrimaryKey, Row)]
型のRDDになります。
次の例では、Oracle NoSQL Databaseに接続し、グラフの頂点表を読み込むための構成オブジェクトを作成します。socialNetVT_
が、グラフの頂点情報が含まれる表の名前であることを前提とします。後で、この構成を使用して頂点表からRDDを取得します。
Configuration noSQLNodeConf = new Configuration(); noSQLNodeConf.set("oracle.kv.kvstore", "kvstore"); noSQLNodeConf.set("oracle.kv.tableName", “socialNetVT_”); noSQLNodeConf.set("oracle.kv.hosts", "localhost:5000");
同様に、次の例では、Oracle NoSQL Databaseに格納されているエッジ表に接続し、表の行のRDDを取得するための構成オブジェクトを作成します。socialNetGE_
は、エッジ・データが含まれる表の名前です。
Configuration noSQLEdgeConf = new Configuration(); noSQLEdgeConf.set("oracle.kv.kvstore", "kvstore"); noSQLEdgeConf.set("oracle.kv.tableName", “socialNetGE_”); noSQLEdgeConf.set("oracle.kv.hosts", "localhost:5000"); JavaPairRDD<PrimaryKey,Row> bytesResultVertices = sc.newAPIHadoopRDD(noSQLNodeConf, oracle.kv.hadoop.table.TableInputFormat.class,PrimaryKey.class, Row.class); JavaPairRDD<PrimaryKey,Row> bytesResultEdges = sc.newAPIHadoopRDD(noSQLEdgeConf, oracle.kv.hadoop.table.TableInputFormat.class, PrimaryKey.class, Row.class);
行オブジェクトにはグラフの頂点またはエッジの1つ以上の属性が含まれる場合があるため、関連情報を取得するためにこれらのRDDに変換を適用する必要があります。oracle.pg.nosql.SparkUtils
は、このような変換を定義する上で役に立つ複数のメソッドを実装します。
たとえば、結果オブジェクトから頂点プロパティ値を抽出し、頂点のIDおよび名前を格納するJava BeanクラスであるMyVertex
のオブジェクト・インスタンスを作成する変換を定義できます。次の例では、頂点を表す特定の行オブジェクトから識別子および名前キー/値ペアを抽出するためにSparkUtils
を使用するメソッドres2vertex
を定義します。
public static MyVertex res2vertex(Row res) throws Exception { SparkUtils su = SparkUtils.getInstance(); Object dbRepr = su.getGraphElementReprOnDB(res); long id = su.getElementId(dbRepr); String name = (String)su.getPropertyValue(dbRepr, "name"); return new MyVertex(id,name); }
メソッドgetGraphElemetReprOnDB
は、Oracle NoSQL Databaseに格納されているグラフ要素表現を返し、パラメータがnullまたは対応するクラスの非インスタンスである場合はIllegalArgumentException
例外をスローします。この表現はデータベース固有であり、戻り値はインタフェースに定義されている他のAPIのみによって使用される必要があります。Oracle NoSQL Databaseの場合、dbRepr
はRow
クラスのnull以外のインスタンスです。データベース表現オブジェクトが生成されたら、これを、インタフェースに定義されている他の任意のメソッドのパラメータとして渡すことができます。
メソッドgetElementId
は頂点のIDを返し、メソッドgetPropertyValue
はオブジェクトdbRepr
から属性値“name”を取得します。不適切なパラメータが渡された場合、例外IOException
およびjava.text.ParseException
がスローされます。
同様に、ID、ラベルおよび入力/出力頂点ID値を格納するJava Beanクラスを使用して、行オブジェクトからMyEdge
のオブジェクト・インスタンスを作成するための変換を定義できます。次の例では、エッジを表す特定の行オブジェクトから識別子、ラベルおよび入力/出力頂点IDを抽出するためにSparkUtils
を使用するメソッドres2edge
を定義します。
public static MyEdge res2Edge( Row res) throws Exception { SparkUtils su = SparkUtils.getInstance(); Object dbRepr = su.getGraphElementReprOnDB(res); long rowId = su.getElementId(dbRepr); String label = (String)su.getEdgeLabel(dbRepr); long inVertex = (long)su.getInVertexId(dbRepr); long outVertex = (long)su.getOutVertexId(dbRepr); return new MyEdge(rowId,inVertex,outVertex,label); }
これらの変換が生成されたら、これらをbytesResultVertices
およびbytesResultEdges
の値セットにマップできます。
JavaRDD<Row> resultVerticesRDD = bytesResult.values(); JavaRDD<Vertex> nodesRDD = resultVerticesRDD.map(result -> MyConverters.res2vertex(result)); JavaRDD<Row> resultEdgesRDD = bytesResultEdges.values(); JavaRDD<Edge> edgesRDD = resultEdgesRDD.map(result -> MyConverters.res2Edge(result));
前の手順の後、nodesRDD
およびedgesRDD
の操作を開始できます。たとえば、Spark SQL問合せを実行するために対応するデータ・フレームを作成できます。次の例では、SQLコンテキストを作成し、nodesRDD
およびedgesRDD
から2つのデータ・フレームを取得し、ID 1を持つ頂点のすべての友人を取得する問合せを実行します。
SQLContext sqlCtx = new SQLContext(sc); DataFrame verticesDF = sqlCtx.createDataFrame(verticesRDD); verticesDF.registerTempTable("VERTICES_TABLE"); DataFrame edgesDF = sqlCtx.createDataFrame(edgesRDD); edgesDF.registerTempTable("EDGES_TABLE"); sqlCtx.sql("select name from (select target from EDGES_TABLE WHERE source = 1) REACHABLE left join VERTICES_TABLE on VERTICES_TABLE.id = REACHABLE.target ").show();
この場合、SparkではクラスMyVertex
およびMyEdge
を使用してデータ・フレームの列名を確認するために、これらのクラスが重要な役割を果たします。
Oracle NoSQL Databaseからグラフ・データを直接読み込んだり、Apache Spark内のグラフに対して操作を実行したりする以外にも、「インメモリー・アナリストを使用したApache Spark内のグラフ・データの分析」で説明されているように、インメモリー・アナリストを使用してApache Spark内のグラフ・データを分析できます。
Oracle Big Data Spatial and Graphプロパティ・グラフ・サポートは、Oracle NoSQL Databaseのセキュア・インストールと非セキュア・インストールの両方で機能します。このトピックでは、セキュアなOracle NoSQL Database設定でプロパティ・グラフ機能を使用する方法についての情報を提供します。
ここでは、セキュアなOracle NoSQL Databaseがすでにインストールされていると想定します(http://docs.oracle.com/cd/NOSQL/html/SecurityGuide/secure_installation.html
にある『Oracle NoSQL Databaseセキュリティ・ガイド』の「Oracle NoSQL Databaseのセキュア・インストールの実行」で説明されているプロセス)。
セキュア・データベースにアクセスするには、正しい資格情報を持っている必要があります。次のようなユーザーを作成します。
kv-> plan create-user -name myusername -admin -wait
このユーザーにreadwrite
およびdbaadmin
ロールを付与します。次に例を示します。
kv-> plan grant -user myusername -role readwrite -wait kv-> plan grant -user myusername -role dbadmin -wait
client.security
ファイルからlogin_properties.txt
を生成する際、ユーザー名が正しいことを確認します。次に例を示します。
oracle.kv.auth.username=myusername
Oracleプロパティ・グラフのクライアント側で、セキュアなOracle NoSQL Databaseと対話するためのセキュリティ関連ファイルおよびライブラリを持っている必要があります。最初に、次のファイル(ディレクトリ)をKVROOT/security/
からクライアント側にコピーします。
client.security client.trust login.wallet/ login_properties.txt
セキュア・データベースへのアクセスに必要なパスワードを保持するためにOracle Walletを使用する場合、次の3つのライブラリをクライアント側にコピーして、クラス・パスを正しく設定します。
oraclepki.jar osdt_cert.jar osdt_core.jar
データベースとOracleプロパティ・グラフのクライアント側を正しく構成した後、次の2つのアプローチのいずれかを使用して、セキュアなNoSQL Databaseに格納されているグラフに接続できます。
Java VM設定を次の形式で使用して、ログイン・プロパティ・ファイルを指定します。
-Doracle.kv.security=/<your-path>/login_properties.txt
このJava VMプロパティは、J2EEコンテナにデプロイされたアプリケーション(インメモリー分析を含む)にも設定できます。たとえば、WebLogicサーバーを起動する前に、次の形式で環境変数を設定してログイン・プロパティ構成ファイルを参照できます。
setenv JAVA_OPTIONS "-Doracle.kv.security=/<your-path>/login_properties.txt"
次に、通常どおりにOraclePropertyGraph.getInstance(kconfig, szGraphName)
を呼び出してOraclePropertyGraph
インスタンスを作成します。
OraclePropertyGraph.getInstance(kconfig, szGraphName, username, password, truStoreFile)
を呼び出し、username
およびpassword
にはセキュアなOracle NoSQL Databaseにアクセスするための正しい資格情報、truStoreFile
にはクライアント側トラスト・ストア・ファイルclient.trust
へのパスを指定します。
次のコード・フラグメントは、セキュアなOracle NoSQL Databaseにプロパティ・グラフを作成し、データをロードしてから、グラフ内の頂点およびエッジの数をカウントします。
// This object will handle operations over the property graph OraclePropertyGraph opg = OraclePropertyGraph.getInstance(kconfig, szGraphName, username, password, truStoreFile); // Clear existing vertices/edges in the property graph opg.clearRepository(); opg.setQueueSize(100); // 100 elements String szOPVFile = "../../data/connections.opv"; String szOPEFile = "../../data/connections.ope"; // This object will handle parallel data loading over the property graph System.out.println("Load data for graph " + szGraphName); OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance(); opgdl.loadData(opg, szOPVFile, szOPEFile, dop); // Count all vertices long countV = 0; Iterator<Vertex> vertices = opg.getVertices().iterator(); while (vertices.hasNext()) { vertices.next(); countV++; } System.out.println("Vertices found: " + countV); // Count all edges long countE = 0; Iterator<Edge> edges = opg.getEdges().iterator(); while (edges.hasNext()) { edges.next(); countE++; } System.out.println("Edges found: " + countE);
Oracle Big Data Spatial and Graphのプロパティ・グラフを保護するために、Apache HBaseでKerberos認証を使用することが推奨されます。
Oracleのプロパティ・グラフ・サポートは、Cloudera Hadoop (CDH)クラスタのセキュア・インストールと非セキュア・インストールの両方で機能します。このトピックでは、セキュアなApache HBaseインストールについての情報を提供します。
Oracle Big Data Spatial and Graphのプロパティ・グラフを保護するために、Apache HBaseでKerberos認証を使用することが推奨されます。
このトピックでは、Kerberosを使用してセキュアなApache HBaseが構成されており、クライアント・マシンにKerberosライブラリがインストールされ、正しい資格情報を持っていると想定します。詳細は、http://www.cloudera.com/content/cloudera/en/documentation/core/latest/topics/cdh_sg_hbase_authentication.html
の『Configuring Kerberos Authentication for HBase』を参照してください。Kerberosクラスタおよびクライアントの設定方法の情報は、 http://web.mit.edu/kerberos/krb5-latest/doc/index.html
の『MIT Kerberos Documentation』を参照してください。
クライアント側で、対応HDFSデーモンと対話するために、Kerberos資格情報を持っている必要があります。さらに、(krb5.conf
にある)Kerberos構成情報を変更して、レルムおよびホスト名マッピングをセキュアなCDHクラスタで使用されるKerberosレルムに含める必要があります。
次のコード・フラグメントは、BDA.COM上のセキュアなCDHクラスタで使用されるレルムとホスト名マッピングを示しています。
[libdefaults] default_realm = EXAMPLE.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = yes [realms] EXAMPLE.COM = { kdc = hostname1.example.com:88 kdc = hostname2.example.com:88 admin_server = hostname1.example.com:749 default_domain = example.com } BDA.COM = { kdc = hostname1.bda.com:88 kdc = hostname2.bda.com:88 admin_server = hostname1.bda.com:749 default_domain = bda.com } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM .bda.com = BDA.COM bda.com = BDA.COM
krb5.conf
を変更した後、Java Authentication and Authorization Service (JAAS)構成ファイルを使用して資格情報をアプリケーションに提供することにより、Apache HBaseに格納されているグラフに接続できます。これは、非セキュアなApache HBaseインストールを使用するアプリケーションがすでに存在する場合に、コードをまったく変更することなく前述の例と同じ機能を提供します。
JAAS構成が設定されたHBaseでプロパティ・グラフ・サポートを使用するには、次の形式の内容を含むファイルを作成し、keytab
およびprincipal
エントリを独自の情報に置き換えます。
Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true useTicketCache=true keyTab="/path/to/your/keytab/user.keytab" principal="your-user/your.fully.qualified.domain.name@YOUR.REALM"; };
次のコード・フラグメントは、BDA.COM上のセキュアなCDHクラスタで使用されるレルムを含むJAASファイルの例を示しています。
Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true useTicketCache=true keyTab="/path/to/keytab/user.keytab" principal="hbaseuser/hostname1@BDA.COM"; };
セキュアなHBaseアプリケーションを実行するには、java.security.auth.login.configフラグを使用して、作成したJAAS構成ファイルを指定する必要があります。次の形式のコマンドを使用して、アプリケーションを実行できます。
java -Djava.security.auth.login.config=/path/to/your/jaas.conf/ -classpath ./classes/:../../lib/'*' YourJavaApplication
その後、通常どおりにOraclePropertyGraph.getInstance(conf, hconn, szGraphName)
を呼び出してOracleプロパティ・グラフを作成できます。
Oracle Big Data Spatial and Graphプロパティ・グラフ・サポートをセキュアなApache HBaseインストールで使用するための別の方法は、セキュアなHBase構成を使用することです。次のコード・フラグメントは、prepareSecureConfig()を使用してセキュアなHBase構成を取得する方法を示しています。このAPIは、Apache HadoopおよびApache HBaseで使用されるセキュリティ認証設定、および認可されたチケットを認証および取得するためのKerberos資格情報セットを必要とします。
次のコード・フラグメントは、セキュアなApache HBaseにプロパティ・グラフを作成し、データをロードしてから、グラフ内の頂点およびエッジの数をカウントします。
String szQuorum= "hostname1,hostname2,hostname3";
String szCliPort = "2181";
String szGraph = "SecureGraph";
String hbaseSecAuth="kerberos";
String hadoopSecAuth="kerberos";
String hmKerberosPrincipal="hbase/_HOST@BDA.COM";
String rsKerberosPrincipal="hbase/_HOST@BDA.COM";
String userPrincipal = "hbase/hostname1@BDA.COM";
String keytab= "/path/to/your/keytab/hbase.keytab";
int dop= 8;
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", szQuorum);
conf.set("hbase.zookeeper.property.clientPort", szCliPort);
// Prepare the secure configuration providing the credentials in the keytab
conf = OraclePropertyGraph.prepareSecureConfig(conf,
hbaseSecAuth,
hadoopSecAuth,
hmKerberosPrincipal,
rsKerberosPrincipal,
userPrincipal,
keytab);
HConnection hconn = HConnectionManager.createConnection(conf);
OraclePropertyGraph opg=OraclePropertyGraph.getInstance(conf, hconn, szGraph);
opg.setInitialNumRegions(24);
opg.clearRepository();
String szOPVFile = "../../data/connections.opv";
String szOPEFile = "../../data/connections.ope";
// Do a parallel data loading
OraclePropertyGraphDataLoader opgdl = OraclePropertyGraphDataLoader.getInstance();
opgdl.loadData(opg, szOPVFile, szOPEFile, dop);
opg.commit();
Oracle Big Data Spatial and Graphプロパティ・グラフ・サポートには、組込みのGroovyシェル(オリジナルのGremlin Groovyシェル・スクリプトに基づく)が含まれています。このコマンドライン・シェル・インタフェースを使用して、Java APIを参照できます。
Groovyシェルを起動するには、インストール・ホーム(デフォルトでは/opt/oracle/oracle-spatial-graph/property_graph
)の下にあるdal/groovy
ディレクトリに移動します。次に例を示します。
cd /opt/oracle/oracle-spatial-graph/property_graph/dal/groovy/
ここには、Oracle NoSQL DatabaseとApache HBaseにそれぞれ接続するためのスクリプトgremlin-opg-nosql.sh
およびgremlin-opg-hbase.sh
が含まれています。
注意:
gremlinトラバースの例を実行するには、最初に次のインポート操作を実行する必要があります。import com.tinkerpop.pipes.util.structures.*;
次の例は、Oracle NoSQL Databaseに接続し、グラフ名myGraph
を持つOraclePropertyGraph
のインスタンスを取得し、いくつかのサンプル・グラフ・データをロードして、頂点およびエッジのリストを取得します。
$ ./gremlin-opg-nosql.sh
opg-nosql>
opg-nosql> hhosts = new String[1];
==>null
opg-nosql> hhosts[0] = "bigdatalite:5000";
==>bigdatalite:5000
opg-nosql> cfg = GraphConfigBuilder.forPropertyGraphNosql().setName("myGraph").setHosts(Arrays.asList(hhosts)).setStoreName("mystore").addEdgeProperty("lbl", PropertyType.STRING, "lbl").addEdgeProperty("weight", PropertyType.DOUBLE, "1000000").build();
==>{"db_engine":"NOSQL","loading":{},"format":"pg","name":"myGraph","error_handling":{},"hosts":["bigdatalite:5000"],"node_props":[],"store_name":"mystore","edge_props":[{"type":"string","name":"lbl","default":"lbl"},{"type":"double","name":"weight","default":"1000000"}]}
opg-nosql> opg = OraclePropertyGraph.getInstance(cfg);
==>oraclepropertygraph with name myGraph
opg-nosql> opgdl = OraclePropertyGraphDataLoader.getInstance();
==>oracle.pg.nosql.OraclePropertyGraphDataLoader@576f1cad
opg-nosql> opgdl.loadData(opg, new FileInputStream("../../data/connections.opv"), new FileInputStream("../../data/connections.ope"), 1, 1, 0, null);
==>null
opg-nosql> opg.getVertices();
==>Vertex ID 5 {country:str:Italy, name:str:Pope Francis, occupation:str:pope, religion:str:Catholicism, role:str:Catholic religion authority}
[... other output lines omitted for brevity ...]
opg-nosql> opg.getEdges();
==>Edge ID 1139 from Vertex ID 64 {country:str:United States, name:str:Jeff Bezos, occupation:str:business man} =[leads]=> Vertex ID 37 {country:str:United States, name:str:Amazon, type:str:online retailing} edgeKV[{weight:flo:1.0}]
[... other output lines omitted for brevity ...]
次の例は、インメモリー分析用のいくつかの構成パラメータをカスタマイズします。ここでは、Apache HBaseに接続し、グラフ名myGraph
を持つOraclePropertyGraph
のインスタンスを取得し、いくつかのサンプル・グラフ・データをロードし、頂点およびエッジのリストを取得し、インメモリー・アナリストを取得して、組込み分析の1つであるトライアングル・カウンティングを実行します。
$ ./gremlin-opg-hbase.sh
opg-hbase>
opg-hbase> dop=2; // degree of parallelism
==>2
opg-hbase> confPgx = new HashMap<PgxConfig.Field, Object>();
opg-hbase> confPgx.put(PgxConfig.Field.ENABLE_GM_COMPILER, false);
==>null
opg-hbase> confPgx.put(PgxConfig.Field.NUM_WORKERS_IO, dop + 2);
==>null
opg-hbase> confPgx.put(PgxConfig.Field.NUM_WORKERS_ANALYSIS, 3);
==>null
opg-hbase> confPgx.put(PgxConfig.Field.NUM_WORKERS_FAST_TRACK_ANALYSIS, 2);
==>null
opg-hbase> confPgx.put(PgxConfig.Field.SESSION_TASK_TIMEOUT_SECS, 0);
==>null
opg-hbase> confPgx.put(PgxConfig.Field.SESSION_IDLE_TIMEOUT_SECS, 0);
==>null
opg-hbase> instance = Pgx.getInstance()
==>null
opg-hbase> instance.startEngine(confPgx)
==>null
opg-hbase> cfg = GraphConfigBuilder.forPropertyGraphHbase() .setName("myGraph") .setZkQuorum("bigdatalite") .setZkClientPort(iClientPort) .setZkSessionTimeout(60000) .setMaxNumConnections(dop) .setLoadEdgeLabel(true) .setSplitsPerRegion(1) .addEdgeProperty("lbl", PropertyType.STRING, "lbl") .addEdgeProperty("weight", PropertyType.DOUBLE, "1000000") .build();
==>{"splits_per_region":1,"max_num_connections":2,"node_props":[],"format":"pg","load_edge_label":true,"name":"myGraph","zk_client_port":2181,"zk_quorum":"bigdatalite","edge_props":[{"type":"string","default":"lbl","name":"lbl"},{"type":"double","default":"1000000","name":"weight"}],"loading":{},"error_handling":{},"zk_session_timeout":60000,"db_engine":"HBASE"}
opg-hbase> opg = OraclePropertyGraph.getInstance(cfg);
==>oraclepropertygraph with name myGraph
opg-hbase> opgdl = OraclePropertyGraphDataLoader.getInstance();
==>oracle.pg.hbase.OraclePropertyGraphDataLoader@3451289b
opg-hbase> opgdl.loadData(opg, "../../data/connections.opv", "../../data/connections.ope", 1, 1, 0, null);
==>null
opg-hbase> opg.getVertices();
==>Vertex ID 78 {country:str:United States, name:str:Hosain Rahman, occupation:str:CEO of Jawbone}
...
opg-hbase> opg.getEdges();
==>Edge ID 1139 from Vertex ID 64 {country:str:United States, name:str:Jeff Bezos, occupation:str:business man} =[leads]=> Vertex ID 37 {country:str:United States, name:str:Amazon, type:str:online retailing} edgeKV[{weight:flo:1.0}]
[... other output lines omitted for brevity ...]
opg-hbase> session = Pgx.createSession("session-id-1");
opg-hbase> g = session.readGraphWithProperties(cfg);
opg-hbase> analyst = session.createAnalyst();
opg-hbase> triangles = analyst.countTriangles(false).get();
==>22
Java APIの詳細は、インストール・ホーム(デフォルトでは/opt/oracle/oracle-spatial-graph/property_graph/
)の下のdoc/dal/
およびdoc/pgx/
にあるJavadocリファレンス情報を参照してください。
一連のRESTful APIによって、HTTP/RESTプロトコルを介してデータ・アクセス・レイヤーJava APIが公開されます。
これらのRESTful APIは、プロパティ・グラフの作成、更新、問合せおよびトラバースをサポートし、さらに、テキスト検索問合せの実行、gremlinを使用したグラフのトラバース問合せの実行、およびOracle NoSQL DatabaseやApache HBaseなどの複数のデータベース・バックエンドからのグラフの処理をサポートしています。
次のトピックでは、データ・アクセス・レイヤー(DAL)に含まれるREST APIを使用して、Oracle Big Data Spatial and Graphプロパティ・グラフ・サポートのためにRESTful Webサービスを作成する方法について説明します。このサービスを後でApache TomcatまたはOracle WebLogic Server (12cリリース2以上)にデプロイできます。
このトピックでは、Oracle Big Data Spatial and Graphでプロパティ・グラフのRESTful APIを使用するために、Webアプリケーション・アーカイブ(WAR)ファイルを作成する方法について説明します。
このトピックでは、opg_unified.war
ファイルをOracle WebLogic 12.2.0.1またはApache Server Apache Tomcatにデプロイする方法について説明します。
「REST Webアプリケーション・アーカイブ(WAR)ファイルの構築」で説明されているように、RESTサード・パーティ・ライブラリをダウンロードし、opg_unified.war REST Webアプリケーション・アーカイブ(WAR)ファイルを作成したことを確認します。
次のコマンドを使用して、opg_unified.war
にあるrexster.xml
ファイルを抽出します。
cd /tmp/work_unified/<MMDDhhmmss>/ jar xf opg_unified.war WEB-INF/classes/rexster.xml
REST構成ファイル(rexster.xml
)を変更して、デフォルトのバックエンド、バックエンドの追加リスト(存在する場合)、およびプロパティ・グラフ要求を処理するときに使用される使用可能なグラフのリストを指定します。このファイルの詳細は、RESTfulプロパティ・グラフ・サービス構成ファイル(rexster.xml)を参照してください。
次のようにrexster.xml
ファイルを更新して、opg_unified.war
を再構築します。
jar uf opg_unified.war WEB-INF/classes/rexster.xml
選択したJ2EEコンテナにopg_unified.war
をデプロイします。
デプロイメント・コンテナのオプション:
Apache Tomcatを使用したデプロイメント
この項では、Apache Tomcat 8.5.14 (以上)を使用してRESTfulプロパティ・グラフWebサービスをデプロイする方法について説明します。Apache Tomcatは、Java ServletとJavaServer Pages (JSP)を実装するオープンソースのWebサーバーであり、Webアプリケーションを実行するHTTP Webサーバー環境を構築します。Apache Tomcatの詳細は、http://tomcat.apache.org/を参照してください。
Apache Tomcat 8.5.14をダウンロードしてインストールします。
次のように、Apache Tomcat ServerのWebアプリケーション・ディレクトリに移動し、opg_unified.war
ファイルをコピーします。
cd $CATALINA_BASE cp -f /tmp/work_unified/<MMDDhhmmss>/opg_unified.war webapps
この操作で、warファイルが展開されてWebアプリケーションがデプロイされます。(Apache TomcatにおけるWebアプリケーションのデプロイの詳細は、Apache Tomcatのドキュメントを参照してください。)
ブラウザで次のURLをオープンしてデプロイされたことを確認します(Webアプリケーションがポート8080にデプロイされることを前提としています): http://<hostname>:8080/opg_unified
「Welcome to the unified property graph REST interface!」というタイトルのページが表示されます
Oracle WebLogic Serverを使用したデプロイメント
この項では、Oracle WebLogic Server 12cバージョン12.2.1.2.0を使用してRESTfulプロパティ・グラフ・エンドポイントをデプロイする方法について説明します。Oracle WebLogic Serverの詳細は、その製品ドキュメントを参照してください。
Oracle WebLogic Server 12cリリース2 (12.2.1.2.0)をダウンロードしてインストールします。
Jersey 2.5.1 (JAX-RS 2.0. RI)の共有の事前構築済共有ライブラリを登録します(WebLogic Serverインストールに含まれている)。このライブラリは、Big Data Spatial and Graphプロパティ・グラフのRESTful Webサービスなど、Jersey 2.5.1に基づくアプリケーションの実行に必要です。
WebLogic Server管理コンソール(http://localhost:7001/console
)にログインします。
「Deployments」を選択します。
「Install」をクリックして、共有ライブラリをインストールします。
「Path」フィールドで、ディレクトリ: MW_HOME\wlserver\common\deployable-librariesを入力するか、このディレクトリまでナビゲートします。
jax-rs-2.0.warファイルを選択し、「Next」をクリックします。
「Install this deployment as a library」を選択します。
「Next」をクリックします。
「Finish」をクリックします。
opg_unified.war
を変更して、WebLogic Serverによってすでに提供されているサード・パーティ・ライブラリjersey
およびhk2
を削除します。
opg_unified.war
が作成されたwork_unifiedディレクトリの下に一時作業ディレクトリを作成します。次に例を示します。
cd /tmp/work_unified/<MMDDhhmmss>/ mkdir work_weblogic cd work_weblogic
opg_unified.war
のコンテンツを一時ディレクトリに抽出します。次に例を示します。
jar xf ../opg_unified.war
Jersey 2.25サード・パーティ・ライブラリをWEB-INF/lib
ディレクトリから削除します。
rm –rf WEB-INF/lib/jersey-client-2.25.1.jar rm –rf WEB-INF/lib/jersey-common-2.25.1.jar rm –rf WEB-INF/lib/jersey-container-servlet-core-2.25.1.jar rm –rf WEB-INF/lib/jersey-entity-filtering-2.25.1.jar rm –rf WEB-INF/lib/jersey-guava-2.25.1.jar rm –rf WEB-INF/lib/jersey-server-2.25.1.jar rm –rf WEB-INF/lib/hk2-api-2.5.0-b32.jar rm –rf WEB-INF/lib/hk2-locator-2.5.0-b32.jar rm –rf WEB-INF/lib/hk2-utils-2.5.0-b32.jar
opg_unified.war
を再構築します。
jar cfM ../opg_unified.war *
WebLogic Serverインストールのautodeploy
ディレクトリに移動し、ファイルをコピーします。次に例を示します。
cd <domain_name>/autodeploy cp -rf /tmp/work_unified/<MMDDhhmmss>/opg_unified.war <domain_name>/autodeploy
上の例で、<domain_name>はWebLogic Serverのドメイン名です。
開発モードまたは本番モードでWebLogic Serverドメインを実行できますが、自動デプロイメント機能を使用できるのは開発モードのみであることに注意してください。
ブラウザで次のURLをオープンしてデプロイされたことを確認します(Webアプリケーションがポート7001にデプロイされることを前提としています): http://<hostname>:7001/opg_unified
「Welcome to the unified property graph REST interface!」というタイトルのページが表示されます
Oracle Big Data Spatial and Graphは、Tinkerpop Rexster RESTful APIを拡張してプロパティ・グラフにRESTful機能を提供します。RESTfulサービスの構成を有効にするために、サービスの起動時に設定およびロードする必要があるデータベース・バックエンドおよびグラフの構成を含むrexster.xml
ファイルが、opg_unified.war
に含まれています。
rexster.xml
ファイルは、少なくとも4つのメイン・セクション(またはタグ)を持つXMLベースの構成ファイルです。
<script-engines>: プロパティ・グラフに対するスクリプトの実行に使用されるスクリプト・エンジン。デフォルトでは、gremlin-groovy
が使用されます。
<oracle-pool-size>: プロパティ・グラフに許可される同時接続の数。デフォルトでは、構成でプール・サイズ3が使用されます。
<oracle-property-graph-backends>: RESTful APIが使用する必要があるデータベース・バックエンドに関する情報。デフォルトでは、すべてのRESTful APIサービスのデフォルト・データベース接続として使用するように、少なくとも1つのバックエンド構成を定義する必要があります。
<graphs>: サービスの起動時に要求を処理するために使用可能なグラフのリスト。このリストに定義されたグラフは、関連付けられたデータベース構成に基づいて作成されます。
デフォルトでは、rexster.xml
によって、<oracle-property-graph-backends>セクションに少なくとも1つのバックエンド構成を定義する必要があります。各バックエンドは、backend-nameおよびbackend-type (apache_hbase
またはoracle_nosql
のいずれか)によって識別されます。追加のデータベース・パラメータはバックエンドのプロパティとして指定する必要があります。Apache HBaseの場合、これらのプロパティにZookeeper定数およびZookeeperクライアント・ポートが含まれます。Oracle NoSQL Databaseの場合、これらのデータベース・パラメータにデータベース・ホストとポートおよびKVストア名が含まれます。
構成ファイルに、同じまたは異なるバックエンド・タイプに属する複数のバックエンド構成を含めることができます。
次のスニペットは、2つのバックエンド(最初の1つはApache HBaseデータベースに対するもので、2番目はOracle NoSQL Databaseに対するもの)を持つrexster.xmlの構成を示します。
<backend> <backend-name>hbase_connection</backend-name> <backend-type>apache_hbase</backend-type> <default-backend>true</default-backend> <properties> <quorum>127.0.0.1</quorum> <clientport>2181</clientport> </properties> </backend> <backend> <backend-name>nosql_connection</backend-name> <backend-type>oracle_nosql</backend-type> <properties> <host>127.0.0.1</host> <port>5000</port> <storeName>kvstore</storeName> </properties> </backend>
デフォルトのバックエンドは、rexster.xml
ファイルのグラフ・セクションで前に定義されていないグラフで実行されるすべてのプロパティ・グラフRESTful操作のデフォルトのデータベース構成として使用されるため、サービス用に設定される必要があります。前の例では、hbase_connectionsという名前のバックエンドがデフォルトのバックエンドとして設定されます。
<graphs> XML要素は、ユーザーの要求に使用可能なプロパティ・グラフのリストを識別します。各グラフは、graph-name およびgraph-type (oracle.pg.hbase
またはoracle.pg.nosql.OraclePropertyGraphConfiguration
)によって識別されます。追加のデータベース・パラメータは、グラフのタイプに基づくプロパティとして指定する必要があります。hbaseグラフの場合、これらのプロパティにZookeeper定数およびZookeeperクライアント・ポートが含まれます。nosqlグラフの場合、これらのデータベース・パラメータにデータベース・ホストとポートおよびKVストア名が含まれます。
さらに、extensions
サブセクションでtp:gremlin
値を指定したallowタグを使用することによってgremlin問合せを実行する機能など、グラフで実行できる拡張機能があるかどうかを指定できます。
次のスニペットは、2つのプロパティ・グラフ(Apache HBaseデータベースを使用するconnectionsグラフおよびOracle NoSQL Databaseを使用するtestグラフ)を持つrexster.xml
の構成を示します。
<graphs> <graph> <graph-name>connections</graph-name> <graph-type>oracle.pg.hbase.OraclePropertyGraphConfiguration</graph-type> <properties> <quorum>127.0.0.1</quorum> <clientport>2181</clientport> </properties> <extensions> <allows> <allow>tp:gremlin</allow> </allows> </extensions> </graph> <graph> <graph-name>connections</graph-name> <graph-type>oracle.pg.nosql.OraclePropertyGraphConfiguration</graph-type> <properties> <storeName>kvstore</storeName> <host>127.0.0.1</host> <port>5000</port> </properties> <extensions> <allows> <allow>tp:gremlin</allow> </allows> </extensions> </graph> </graphs>
HTTPリクエスト(GET、POST、PUT、DELETE)操作が特定のグラフ名に対して実行されると、サービスはrexster.xml
構成ファイルに定義されたグラフ・データベース構成を参照します。グラフが構成ファイルに含まれていない場合は、「graph cannot be found」というエラー・メッセージが表示されてリクエストは失敗し、操作は完了しません。
グラフの作成サービスでHTTP POSTリクエストを実行することによって、後続のHTTPリクエストで使用されるように新しいグラフを動的にサービスに追加できます。
このトピックでは、プロパティ・グラフREST APIの操作について説明します。
このトピックでは、プロパティ・グラフREST APIのGET操作について説明します。
注意:
プロパティ・グラフの索引の詳細は、プロパティ・グラフ・データの自動索引の使用およびプロパティ・グラフ・データの手動索引の使用の次の項目を参照してください。
/graphs/{graphname}/indices
説明: 指定されたグラフに作成されているすべての手動索引の名前およびクラスを取得します。
パラメータ
graphname
:
使用上の注意
このGET操作は、OraclePropertyGraph.getIndices()
メソッドの呼出しを実行します。
例
次のURLは、connections
という名前のグラフのすべての手動索引を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/indices
結果は次のようになります。
{ results: [ name: "myIdx", class: "vertex" ], totalSize:1, queryTime: 9.112078 }
/graphs/{graphname}/indices/{indexName}?key=<key>&value=<value>
説明 特定のキー値ペアを持つ指定された索引内の要素を取得します。
パラメータ
graphname
:
indexName
:
<key>
:
<value>
:
使用上の注意
キー値ペアを指定していない場合、指定した手動索引に関する情報が表示されます。索引が存在しない場合、「Could not find index」というメッセージが返されます。
このGET操作は、OracleIndex.get(key,value)
メソッドの呼出しを実行します。
例
次のURLは、キー値ペアname-Beyonce
を持つmyIdx索引内のすべての頂点を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/indices/myIdx?key=name&value=Beyonce
結果は次のようになります。
{ "results": [ { "country": { "type": "string", "value": "United States" }, "music genre": { "type": "string", "value": "pop soul " }, "role": { "type": "string", "value": "singer actress" }, "name": { "type": "string", "value": "Beyonce" }, "_id": 2, "_type": "vertex" } ], "totalSize": 1, "queryTime": 79.910928 }
/graphs/{graphname}/indices/{indexName}/count?key=<key>&value=<value>
説明: 特定のキー値ペアを持つ指定された索引内の要素の数を取得します。
パラメータ
graphname
:
indexName
:
<key>
:
<value>
:
使用上の注意
このGET操作は、OracleIndex.count(key,value)
メソッドの呼出しを実行します。
例
次のURLは、connections
グラフのmyIdx
索引内のキー値ペアname-Beyonce
を持つ頂点の数を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/indices/myIdx/count?key=name&value=Beyonce
結果は次のようになります。
{ totalSize: 1, queryTime: 20.781228 }
/graphs/{graphname}/keyindices
説明: 指定されたグラフのすべての自動テキスト索引に関する情報を取得します。現在自動索引で使用されている索引付けされたキーを提供します。
パラメータ
graphname
:
使用上の注意
このGET操作は、Vertex
とEdge
の両方のクラスに対するOraclePropertyGraph.getIndexedKeys(class)
メソッドの呼出しを実行します。
例
次のURLは、connections
グラフのすべての自動索引に関する情報を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/keyindices
結果は次のようになります。
{ keys: { edge: [ ], vertex: [ "name" ] }, queryTime: 28.776229 }
/graphs/{graphname}/keyindices/{class}
説明: 特定のタイプのすべての要素に対する自動索引で現在使用されている索引付けされたキーを取得します。
パラメータ
graphname
:
class
:
使用上の注意
このGET操作は、OraclePropertyGraph.getIndexedKeys(class)
メソッドの呼出しを実行します。
例
次のURLは、connections
グラフのすべての自動索引を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/keyindices/vertex/
結果は次のようになります。
{ results: [ "name" ], queryTime: 28.776229 }
/backends
説明: すべての使用可能なバックエンドおよびその構成情報を返します。
パラメータ
(なし。)
使用上の注意
(なし。)
例
次のURLは、すべての構成済バックエンドを取得します。
http://localhost:7001/opg_unified/dal/backends/
結果は次のようになります。
{ backends: [ { backendName: "hbase_connection", isDefault: false, port: "2181", backendType: "HBaseBackendConnection", quorum: " localhost " }, { host: "localhost", backendName: "nosql_connection", isDefault: true, store: "kvstore", port: "5000", backendType: "OracleNoSQLBackendConnection" } ], queryTime: 0.219886, upTime: "0[d]:02[h]:33[m]:40[s]" }
/backends/default
説明: グラフによって使用されるデフォルトのバックエンドを取得します。
パラメータ
(なし。)
使用上の注意
(なし。)
例
次のURLは、デフォルトのバックエンドを取得します。
http://localhost:7001/opg_unified/dal/backends/default/
結果は次のようになります。
{ defaultBackend: { host: "localhost", backendName: "nosql_connection", isDefault: true, store: "kvstore", port: "5000", backendType: "OracleNoSQLBackendConnection" }, queryTime: 0.219886, upTime: "0[d]:02[h]:33[m]:40[s]" }
/backends/{backendName}
説明: 指定されたバックエンドに関するすべての構成情報を取得します。
パラメータ
beckendName
:
使用上の注意
(なし。)
例
次のURLは、nosql_connection
バックエンドの構成を取得します。
http://localhost:7001/opg_unified/dal/backends/nosql_connection/
結果は次のようになります。
{ backend: { host: "localhost", backendName: "nosql_connection", isDefault: true, store: "kvstore", port: "5000", backendType: "OracleNoSQLBackendConnection" }, queryTime: 0.219886, upTime: "0[d]:02[h]:33[m]:40[s]" }
/graphs/{graphname}
説明: 指定されたグラフのタイプおよびサポートされる機能に関する情報を取得します。
パラメータ
graphname
:
使用上の注意
(なし。)
例
次のURLは、connections
グラフに関する情報を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/
結果は次のようになります。
{ name: "connections", graph: "oraclepropertygraph with name connections", features: { isWrapper: false, supportsVertexProperties: true, supportsMapProperty: true, supportsUniformListProperty: true, supportsIndices: true, ignoresSuppliedIds: false, supportsFloatProperty: true, supportsPrimitiveArrayProperty: true, supportsEdgeIndex: true, supportsKeyIndices: true, supportsDoubleProperty: true, isRDFModel: false, isPersistent: true, supportsVertexIteration: true, supportsEdgeProperties: true, supportsSelfLoops: false, supportsDuplicateEdges: true, supportsSerializableObjectProperty: true, supportsEdgeIteration: true, supportsVertexIndex: true, supportsIntegerProperty: true, supportsBooleanProperty: true, supportsMixedListProperty: true, supportsEdgeRetrieval: true, supportsTransactions: true, supportsThreadedTransactions: true, supportsStringProperty: true, supportsVertexKeyIndex: true, supportsEdgeKeyIndex: true, supportsLongProperty: true }, readOnly: false, type: "oracle.pg.nosql.OraclePropertyGraph", queryTime: 1010.203456, upTime: "0[d]:19[h]:28[m]:37[s]" }
/graphs/{graphname}/edges
説明: 指定されたグラフのエッジに関する情報を取得します。
パラメータ
graphname
:
opg.showTypes
(問合せパラメータ):
opg.offset.start
(問合せパラメータ):
opg.offset.limit
(問合せパラメータ):
opg.ids=[<id1>, <id2>, <id3>, ...]
(問合せパラメータ):
使用上の注意
(なし。)
例
次のGETリクエストは、connections
グラフのすべてのエッジに関する情報を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/edges
結果は次のようになります。
{ results: [ { weight: 1, _id: 1001, _type: "edge", _outV: 1, _inV: 3, _label: "collaborates" }, { weight: 1, _id: 1002, _type: "edge", _outV: 1, _inV: 4, _label: "admires" }, … ], totalSize: 164, queryTime: 49.491961 }
次のGETリクエストは、connections
グラフ内のID値が1001および1002であるエッジのみを要求するように、前のリクエストを変更します。
http://localhost:7001/opg_unified/dal/graphs/connections/edges?opg.ids=[1001,1002]
結果は次のようになります。
{ results: [ { weight: 1, _id: 1001, _type: "edge", _outV: 1, _inV: 3, _label: "collaborates" }, { weight: 1, _id: 1002, _type: "edge", _outV: 1, _inV: 4, _label: "admires" } ], totalSize: 2, queryTime: 49.491961 }
次のGETリクエストは、connections
グラフの最初の5つのエッジをスキップした後に1つのエッジをフェッチします。
http://localhost:7001/opg_unified/dal/graphs/connections/edges?opg.offset.start=5&opg.offset.limit=1
結果は次のようになります。
{ results: [ { weight: 1, _id: 1005, _type: "edge", _outV: 1, _inV: 7, _label: "collaborates" } ], totalSize: 1, queryTime: 49.491961 }
/graphs/{graphname}/edges/{id}
説明: グラフの指定されたIDのエッジに関する情報を取得します。
パラメータ
graphname
:
id
:
opg.showTypes
(問合せパラメータ):
使用上の注意
(なし。)
例
次のGETリクエストは、connections
グラフのエッジID 1001に関する情報を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/edges/1001
結果は次のようになります。
{ results: { weight: { type: "double", value: 1 }, _id: 1001, _type: "edge", _outV: 1, _inV: 3, _label: "collaborates" }, queryTime: 43.720456 }
次のGETリクエストは、connections
グラフに存在しないエッジ1に対する失敗したリクエストの出力を表示します。
http://localhost:7001/opg_unified/dal/graphs/connections/edges/1
結果は次のようになります。
{ message: "Edge with name [1] cannot be found." }
次のGETリクエストは、connections
グラフの最初の5つのエッジをスキップした後に1つのエッジをフェッチします。
http://localhost:7001/opg_unified/dal/graphs/connections/edges?opg.offset.start=5&opg.offset.limit=1
結果は次のようになります。
{ results: [ { weight: 1, _id: 1005, _type: "edge", _outV: 1, _inV: 7, _label: "collaborates" } ], totalSize: 1, queryTime: 49.491961 }
/graphs/{graphname}/vertices
説明: 指定されたグラフの頂点に関する情報を取得します。
パラメータ
graphname
:
opg.showTypes
(問合せパラメータ):
opg.offset.start
(問合せパラメータ):
opg.offset.limit
(問合せパラメータ):
opg.ids=[<id1>, <id2>, <id3>, ...]
(問合せパラメータ):
使用上の注意
(なし。)
例
次のGETリクエストは、connections
グラフのすべての頂点に関する情報を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices
結果は次のようになります。
{ results: [ { country: "Portugal", occupation: "Professional footballer", name: "Cristiano Ronaldo", _id: 63, _type: "vertex" }, { country: "North Korea", occupation: "Supreme leader of North Korea", role: "political authority", name: "Kim Jong Un", political party: "Workers' Party of Korea", religion: "atheism", _id: 32, _type: "vertex" }, … ], totalSize: 78, queryTime: 22.345108 }
次のGETリクエストは、connections
グラフ内のID値が4および63である頂点のみを要求するように、前のリクエストを変更します。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices?opg.ids=[4,63]
結果は次のようになります。
{ results: [ { country: "United States", role: " american economist", name: "Janet Yellen", political party: "Democratic", _id: 4, _type: "vertex" }, { country: "Portugal", occupation: "Professional footballer", name: "Cristiano Ronaldo", _id: 63, _type: "vertex" }, ], totalSize: 2, queryTime: 22.345108 }
次のGETリクエストは、connections
グラフの最初の5つの頂点をスキップした後に1つの頂点をフェッチします。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices?opg.offset.start=5&opg.offset.limit=1
結果は次のようになります。
{ results: [ { country: "United States", occupation: "founder", role: "philantropist", name: "Tom Steyer", company: "Farallon Capital Management", political party: "Democratic", _id: 20, _type: "vertex" } ], totalSize: 1, queryTime: 65.366488 }
/graphs/{graphname}/vertices/{id}
説明: グラフの指定されたIDの頂点に関する情報を取得します。
パラメータ
graphname
:
id
:
opg.showTypes
(問合せパラメータ):
使用上の注意
(なし。)
例
次のGETリクエストは、connections
グラフの頂点ID 1に関する情報を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices/1
結果は次のようになります。
{ results: { country: "United States", occupation: "44th president of United States of America", role: "political authority", name: "Barack Obama", political party: "Democratic", religion: "Christianity", _id: 1, _type: "vertex" }, queryTime: 13.95932 }
次のGETリクエストは、頂点1のすべてのプロパティのデータ型を含むように前のリクエストを変更しました。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices/1?opg.showTypes=true
結果は次のようになります。
{ results: { country: { type: "string", value: "United States" }, occupation: { type: "string", value: "44th president of United States of America" }, role: { type: "string", value: "political authority" }, name: { type: "string", value: "Barack Obama" }, political party: { type: "string", value: "Democratic" }, religion: { type: "string", value: "Christianity" }, _id: 1, _type: "vertex" }, queryTime: 13.147989 }
次のGETリクエストは、connections
グラフに存在しない頂点1000に対する失敗したリクエストの出力を表示します。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices/1000
結果は次のようになります。
{ message: "Vertex with name [1000] cannot be found." }
/graphs/{graphName}/vertices/{id}/{direction}
説明: 指定されたID値を持つ頂点の{in,out,both}の隣接する頂点を取得します。
パラメータ
direction
:
in
、出力頂点の場合はout
、入力頂点と出力頂点の場合はboth
とすることができます。使用上の注意
(なし。)
例
次のURLは、ID 5を持つ頂点の出力頂点を取得します。
http://localhost:7001/opg_unified/dal/graphs/connections/vertices/5/out/
結果は次のようになります。
{ results: [ { name: "Omar Kobine Layama", _id: 56, _type: "vertex" }, { name: "Dieudonne Nzapalainga", _id: 57, _type: "vertex" }, { name: "Nicolas Guerekoyame Gbangou", _id: 58, _type: "vertex" }, { country: "Rome", name: "The Vatican", type: "state", religion: "Catholicism", _id: 59, _type: "vertex" } ], totalSize: 4, queryTime: 56.044806 }
/graphs/{graphname}/config
説明: 指定されたグラフの構成の表現(JSON形式)を取得します。
パラメータ
graphname
:
使用上の注意
(なし。)
例
次のURLは、connections
グラフのグラフ構成を取得します。
http://localhost:7001/opg_unified/graphs/connections/config
結果は次のようになります。
{ edge_props: [ { name: "weight", type: "string" } ], db_engine: "NOSQL", hosts: [ "localhost:5000" ], vertex_props: [ { name: "name", type: "string" }, { name: "role", type: "string" }, … { name: "country", type: "string" } ], format: "pg", name: "connections", store_name: "kvstore", attributes: { }, max_num_connections: 2, error_handling: { }, loading: { load_edge_label: true }, edge_label: true }
/graphs/{graphname}/exportData
説明: Oracleプロパティ・グラフ・フラット・ファイル形式(.opv
および.ope
ファイル)のグラフを含む.zipファイルをダウンロードします。
パラメータ
graphname
:
dop
(問合せパラメータ)
使用上の注意
(なし。)
例
次のURLは、4つまでの並列実行スレッドを使用して、connections
グラフをエクスポートします。
http://localhost:7001/opg_unified/graphs/connections/exportData?dop=4
これは、次のようなコンテンツのOPV (頂点)ファイルおよびOPE (エッジ)ファイルを含むzipファイルをダウンロードします。
OPVファイル:
1,name,1,Barack%20Obama,, 1,role,1,political%20authority,, 1,occupation,1,44th%20president%20of%20United%20States%20of%20America,, 1,country,1,United%20States,, …
OPEファイル:
1000,1,2,collaborates,weight,3,,1.0, 1001,1,3,collaborates,weight,3,,1.0, 1002,1,4,admires,weight,3,,1.0, 1003,1,5,admires,weight,3,,1.0, …
/edges/{graphname}/properties
説明: 指定されたグラフのエッジによって使用されるプロパティ・キーのセットを取得します。
パラメータ
graphname
:
使用上の注意
(なし。)
例
次のURLは、connections
グラフのエッジ・プロパティ・キーを取得します。
http://localhost:7001/opg_unified/edges/connections/properties
結果は次のようになります。
{ complete: 1, results: [ "weight" ], totalSize: 1, queryTime: 360.491961 }
/vertices/{graphname}/textquery
説明 特定のキー値ペアの基準と一致するグラフの頂点を取得します。既存の索引に対して全文検索を実行します。
パラメータ
graphname
:
key
(問合せパラメータ)
value
(問合せパラメータ)
useWildCards
(問合せパラメータ)
false
)、またはワイルドカードを使用するか(true
)を指定するブール文字列。使用上の注意
返される結果は、パラメータの値のみでなくパラメータの存在によっても異なります。
問合せパラメータを指定しない場合、/graphs/{graphname}/verticesとまったく同じように動作します。key
問合せパラメータのみを指定した場合、値に関係なく、そのプロパティ・キーを持つエッジのみを返します。
key
およびvalue
問合せパラメータを指定し、useWildCards
問合せパラメータがtrue
ではない場合は、値にワイルドカード文字(*)が含まれていても、キー値ペアとの完全一致がある頂点のみを返します。
key
およびvalue
問合せパラメータを指定し、useWildCards
問合せパラメータがtrue
である場合は、索引を使用してテキスト検索を実行し、一致する頂点を返します。
ワイルドカード検索が要求され、要求した索引が指定したキーに存在しない場合、エラーが返されます。
例
次のURLは、connections
グラフ内の、value
が文字列Poで開始するnameキーを持つ頂点を取得します。
http://localhost:7001/opg_unified/vertices/connections/textquery?key=name&value=Po*&useWildCards=true
返されるJSONは次のようになります。
{ results: [ { country: "Italy", occupation: "pope", role: "Catholic religion authority", name: "Pope Francis", religion: "Catholicism", _id: 5, _type: "vertex" }, { country: "China", occupation: "business man", name: "Pony Ma", _id: 71, _type: "vertex" } ], totalSize: 2, queryTime: 49.491961 }
/edges/{graphname}/textquery
説明: 特定のキー値ペアの基準と一致するグラフのエッジを取得します。既存の索引に対して全文検索を実行します。
パラメータ
graphname
:
key
(問合せパラメータ)
value
(問合せパラメータ)
useWildCards
(問合せパラメータ)
false
)、またはワイルドカードを使用するか(true
)を指定するブール文字列。使用上の注意
返される結果は、パラメータの値のみでなくパラメータの存在によっても異なります。
問合せパラメータを指定しない場合、/graphs/{graphname}/edgesとまったく同じように動作します。key
問合せパラメータのみを指定した場合、値に関係なく、そのプロパティ・キーを持つエッジのみを返します。
key
およびvalue
問合せパラメータを指定し、useWildCards
問合せパラメータがtrue
ではない場合は、値にワイルドカード文字(*)が含まれていても、キー値ペアとの完全一致があるエッジを返します。
key
およびvalue
問合せパラメータを指定し、useWildCards
問合せパラメータがtrue
である場合は、索引を使用してテキスト検索を実行し、一致するエッジを返します。
例
次のURLは、connections
グラフ内の、値が文字列frienで開始するtype
キーを持つエッジを取得します。
http://localhost:7001/opg_unified/edges/connections/textquery?key=type&value=frien*&useWildCards=true
返されるJSONは次のようになります。
{ results: [ { weight: 1, type: "friends", _id: 10000, _type: "edge", _outV: 1, _inV: 3, _label: "collaborates" } ], totalSize: 1, queryTime: 49.491961 }
このトピックでは、プロパティ・グラフREST APIのPOST操作について説明します。
注意:
プロパティ・グラフの索引の詳細は、プロパティ・グラフ・データの自動索引の使用およびプロパティ・グラフ・データの手動索引の使用の次の項目を参照してください。
/graphs/{graphname}/indices/{indexName}?class=<class>
説明: 指定されたグラフの指定された手動索引を作成します。
パラメータ
graphname
:
indexName
:
class
:
vertex
またはedge
のいずれかにすることができます。使用上の注意
このPOST操作は、OraclePropertyGraph.createIndex(name,class)
メソッドの呼出しを実行します。
例
次のPOST操作は、connections
プロパティ・グラフにクラスvertex
のmyIdx
索引を作成します。
http:// localhost:7001/opg_unified/dal/graphs/connections/indices/myIdx?class=vertex
結果は次のようになります。
{ "queryTime": 551.798547, "results": { "name": "myIdx", "class": "vertex" }}
/graphs/{graphname}/keyindices/{class}/{keyName}
説明: 指定されたグラフに自動キー索引を作成します。
パラメータ
graphname
:
class
:
vertex
またはedge
のいずれかにすることができます。keyName
:
使用上の注意
このPOST操作は、OraclePropertyGraph.createKeyIndex(key,class)
メソッドの呼出しを実行します。
例
次のPOST操作は、connections
プロパティ・グラフにクラスvertex
のmyVKeyIdx
自動索引を作成します。
http:// localhost:7001/opg_unified/dal/graphs/connections/keyindices/vertex/myVKeyIdx
結果は次のようになります。
{ "queryTime": 234.970874 }
/graphs/connections/edges
…edges?_outV=<id>&_label=value&_inV=<id> …edges/<edgeId>?_outV=<id>&_label=value&_inV=<id> …edges/<edgeId>?<key>=value
説明: 2つの頂点の間に新しいエッジを作成します。
パラメータ
_outV
:
_inV
:
_label
:
edgeID
:
key
:
使用上の注意
(なし。)
例
次のPOST操作は、頂点29から頂点26にラベルfriend
のエッジを作成します。
http://localhost:8080/graphs/connections/edges_outV=29&_label=friend&_inV=26
結果は次のようになります。
{"results": {"_id": 1810534020425227300,"_type": "edge","_outV": 29,"_inV": 26,"_label": "friend"},"queryTime": 36.635908}
/csv/edges
説明: エッジ・ファイルをCSV形式からOPE形式に変換します。
パラメータ
fileName
:
cboxEdgeIDColName
:
cboxEdgeSVIDColName
:
cboxEdgeLabelColName
:
cboxEdgeDVIDColName
:
使用上の注意
ファイル形式の詳細は、Oracleフラット・ファイル形式の定義を参照してください。
例
POST操作の実行およびCSVファイルのOPEファイルへの変換に使用できるHTMLフォームを次に示します。
<html> <body> <h1>CSV Example - Edges</h1> <form id="myForm" action="http://localhost:7001/opg_unified/dal/csv/edges" method="POST" enctype="multipart/form-data"> <p>Select a file for edges : <input type="file" name="fileEdge" size="45" /></p> <p>Edge Id : <input type="text" name="cboxEdgeIDColName" size="25" /></p> <p>Start vertex Id : <input type="text" name="cboxEdgeSVIDColName" size="25" /></p> <p>Edge Label : <input type="text" name="cboxEdgeLabelColName" size="25" /></p> <p>End vertex Id : <input type="text" name="cboxEdgeDVIDColName" size="25" /></p> <input type="button" onclick="myFunction()" value="Upload"> </form> <script> function myFunction() { frm = document.getElementById("myForm"); frm.submit(); } </script> </body> </html>
このフォームはブラウザで次のように表示されます。
入力エッジ・ファイル(edges.csv
)の内容は次のとおりです。
EDGE_ID,START_ID:long,weight:float,END_ID:long,label:string 1,1,1.0,2,knows
出力エッジ・ファイル(vertices.ope
)の内容は次のとおりです。
1,1,2,knows,weight,3,,1.0,
/csv/vertices
説明: 頂点ファイルをCSV形式からOPV形式に変換します。
パラメータ
fileVertex
:
cboxVertexIDColName
:
使用上の注意
ファイル形式の詳細は、Oracleフラット・ファイル形式の定義を参照してください。
例
POST操作の実行およびCSVファイルのOPVファイルへの変換に使用できるHTMLフォームを次に示します。
<html> <body> <h1>CSV Example</h1> <form id="myForm" action="http://localhost:7001/opg_unified/dal/csv/vertices" method="POST" enctype="multipart/form-data"> <p>Select a file for vertices : <input type="file" name="fileVertex" size="45" /></p> <p>Vertex Id : <input type="text" name="cboxVertexIDColName" size="25" /></p> <input type="button" onclick="myFunction()" value="Upload"> </form> <script> function myFunction() { frm = document.getElementById("myForm"); frm.submit(); } </script> </body> </html>
このフォームはブラウザで次のように表示されます。
入力頂点ファイル(vertices.csv
)の内容は次のとおりです。
id,name,country 1,Eros%20Ramazzotti,Italy 2,Monica%20Bellucci,Italy
出力頂点ファイル(vertices.opv
)の内容は次のとおりです。
1,name,1,Eros%20Ramazzotti,, 1,country,1,Italy,, 2,name,1,Monica%20Bellucci,, 2,country,1,Italy}
/graphs/{graphname}/loadData
説明: OPVおよびOPEファイルをサーバーにアップロードし、頂点およびエッジをグラフにインポートします。グラフ・メタデータを返します。
パラメータ
graphname
:
vertexFile
(リクエスト・ペイロード):
.opv
)ファイル。edgeFile
(リクエスト・ペイロード):
.ope
)ファイル。clearRepository
(リクエスト・ペイロード):
dop
(リクエスト・ペイロード):
使用上の注意
この操作では、頂点ファイルとエッジ・ファイルの両方を同じ操作でポストできます。
例
次の単純なHTMLフォームを使用して、.OPVおよび.OPEファイルのペアをサーバーにアップロードできます。
http://localhost:7001/opg_unified/graphs/connections/loadData <html> <body> <h1>File Upload to OPG Unified</h1> <p> Graph name : <input type="text" name="graphTxt" id="graphTxt" size="45" /> </p> <form id="myForm" action="http://localhost:7001/opg_unified/graphs/" method="POST" enctype="multipart/form-data"> <p> Select a file for vertices : <input type="file" name="vertexFile" size="45" /> </p> <p> Select a file for edges : <input type="file" name="edgeFile" size="45" /> </p> <p> Clear graph ? : <input type="text" name="clearRepository" size="25" /> </p> <input type="button" onclick="myFunction()" value="Upload"> </form> <script> function myFunction() { frm = document.getElementById("myForm"); frm.action = frm.action + graphTxt.value + '/loadData'; frm.submit(); } </script> </body> </html>
表示されるフォームは次のようになります。
OPV (頂点)ファイルの内容は次のとおりです。
1,name,1,Barack%20Obama,, 1,role,1,political%20authority,, 1,occupation,1,44th%20president%20of%20United%20States%20of%20America,, 1,country,1,United%20States,, …
OPE (エッジ)ファイルの内容は次のとおりです。
1000,1,2,collaborates,weight,3,,1.0, 1001,1,3,collaborates,weight,3,,1.0, 1002,1,4,admires,weight,3,,1.0, 1003,1,5,admires,weight,3,,1.0, …
返されるJSON結果は次のようになります。
{ name: "connections", graph: "oraclepropertygraph with name connections", features: { isWrapper: false, supportsVertexProperties: true, supportsMapProperty: true, supportsUniformListProperty: true, supportsIndices: true, ignoresSuppliedIds: false, supportsFloatProperty: true, supportsPrimitiveArrayProperty: true, supportsEdgeIndex: true, supportsKeyIndices: true, supportsDoubleProperty: true, isRDFModel: false, isPersistent: true, supportsVertexIteration: true, supportsEdgeProperties: true, supportsSelfLoops: false, supportsDuplicateEdges: true, supportsSerializableObjectProperty: true, supportsEdgeIteration: true, supportsVertexIndex: true, supportsIntegerProperty: true, supportsBooleanProperty: true, supportsMixedListProperty: true, supportsEdgeRetrieval: true, supportsTransactions: true, supportsThreadedTransactions: true, supportsStringProperty: true, supportsVertexKeyIndex: true, supportsEdgeKeyIndex: true, supportsLongProperty: true }, readOnly: false, type: "oracle.pg.nosql.OraclePropertyGraph", queryTime: 1010.203456, upTime: "0[d]:19[h]:28[m]:37[s]" }
/backends/{newBackendName}
説明: 指定されたプロパティで新しいバックエンド・エントリを設定します。
パラメータ
newBackendName
:
使用上の注意
バックエンド名がすでに存在する場合、エラーが生成されます
isDefault
やbackendType
など、指定されたその他のパラメータは、ペイロードの一部として渡されます。
例
次のPOST操作は、hbase_connection2
という名前の新しいバックエンドを作成します。
http://localhost:7001/opg_unified/dal/backends/hbase_connection2
ペイロードの例:
{"isDefault": false,"port": "2181","backendType":"HBaseBackendConnection","quorum": "127.0.0.1"}
結果は次のようになります。
{"backend": {"backendName": "hbase_connection2","isDefault": false,"port": "2181","backendType": "HBaseBackendConnection","quorum": "127.0.0.1"},"queryTime": 49.904438,"upTime": "0[d]:00[h]:56[m]:14[s]"}
/edges/{graphName}/ids
説明: 一連のエッジを返します。
パラメータ
graphname
:
ids
(リクエスト・ペイロード):
使用上の注意
このAPIは、IDキーのJSON配列および整数ID値の配列を送信します。入力idsパラメータのサイズと一致する配列を返します
エッジが見つからない場合、結果の配列内の対応する値はnullになります。
グラフにエッジが存在しない場合でも常に結果の配列を返し、その場合は、null値ばかりの配列を返しますが、404 HTTPコードは返しません。
例
次のコマンドは、connections
グラフ内のIDが1001および1002 (存在する場合)のエッジを取得します。
curl -v -X POST 'http://localhost:7001/opg_unified/edges/connections/ids' -H "Content-Type: application/json" -d '{"ids":[1001,1002,1]}
返されるJSONは次のようになります。
{ results: [ { weight: 1, _id: 1001, _type: "edge", _outV: 1, _inV: 3, _label: "collaborates" }, { weight: 1, _id: 1002, _type: "edge", _outV: 1, _inV: 4, _label: "admires" }, null ], totalSize: 3, queryTime: 49.491961 }
/edges/{graphName}/properties
説明: 指定されたエッジの指定されたプロパティを返します。
パラメータ
graphname
:
ids
(リクエスト・ペイロード):
propertyName
(リクエスト・ペイロード):
使用上の注意
このAPIは、idsキーのJSON配列および整数ID値の配列を送信します。入力idsパラメータのサイズと一致する配列を返します
エッジが見つからない場合、結果の配列内の対応する値はnullになります。
グラフにエッジが存在しない場合でも常に結果の配列を返し、その場合は、null値ばかりの配列を返しますが、404 HTTPコードは返しません。
例
次のコマンドは、connections
グラフ内のIDが1001、1002および1003 (存在する場合)のエッジのweight
値を取得します。
curl -v -X POST 'http://localhost:7001/opg_unified/edges/connections/properties' -H "Content-Type: application/json" -d '{"ids":[1001,1002,1003],"propertyName":"weight"}'
返されるJSONは次のようになります。
{ results: [ { _id: 1001, weight: 1 }, { _id: 1002, weight: 1 }, { _id: 1003, weight: 1 } ], totalSize: 3, queryTime: 12.491961 }
このトピックでは、プロパティ・グラフREST APIのPUT操作について説明します。
注意:
プロパティ・グラフの索引の詳細は、プロパティ・グラフ・データの自動索引の使用およびプロパティ・グラフ・データの手動索引の使用の次の項目を参照してください。
/backends/{backendNameNew}
説明: 指定されたプロパティで新しいバックエンド・エントリを設定します。
パラメータ
backendNameNew
:
backendType
:
(other)
:
使用上の注意
バックエンド名がすでに存在する場合、エラーが生成されます。
isDefault
やbackendType
など、指定されたその他のパラメータは、ペイロードの一部として渡されます。
例
次のPUT操作は、hbase_connection2
という名前の新しいバックエンドを作成します。
http://localhost:7001/opg_unified/dal/backends/hbase_connection2
ペイロードの例:
{"isDefault": false,"port": "2182","backendType":"HBaseBackendConnection","quorum": "127.0.0.1"}
結果は次のようになります。
{"backend": {"backendName": "hbase_connection2","isDefault": false,"port": "2182","backendType": "HBaseBackendConnection","quorum": "127.0.0.1"}, "queryTime": 20.929009, "upTime": "0[d]:02[h]:22[m]:19[s]"}
/graphs/connections/edges
…edges?_outV=<id>&_label=value&_inV=<id> …edges/<edgeId>?_outV=<id>&_label=value&_inV=<id> …edges/<edgeId>?<key>=value
説明: 2つの頂点の間に新しいエッジを作成します。
パラメータ
_outV
:
_inV
:
_label
:
edgeID
:
key
:
使用上の注意
(なし。)
例
次のPUT操作は、頂点29から頂点26にラベルfriend
のエッジを作成します。
http://localhost:8080/graphs/connections/edges_outV=29&_label=friend&_inV=26
結果は次のようになります。
{"results": {"_id": 1810534020425227300,"_type": "edge","_outV": 29,"_inV": 26,"_label": "friend"},"queryTime": 36.635908}
/graphs/{graphname}/indices/{indexName}}?key=<key>&value=<value>&id=<id>
説明: 指定された頂点またはエッジを、指定された手動索引のキー値ペアに追加します。
パラメータ
graphName
:
indexName
:
<key>
:
<value>
:
<id>
:
使用上の注意
このPUT操作は、OracleIndex.put(key,value,class)
メソッドの呼出しを実行します。
例
次の例では、キー値ペア"name"-"Beyonce"
をID 2の頂点に追加します。
http://localhost:7001/opg_unified/dal/graphs/connections/indices/myIdx?key=name&value=Beyonce&id=2
PUT操作が正常に行われた場合、次のようなレスポンスが表示されます。
{ "queryTime": 39.265613 }
このトピックでは、プロパティ・グラフREST APIのDELETE操作について説明します。
注意:
プロパティ・グラフの索引の詳細は、プロパティ・グラフ・データの自動索引の使用およびプロパティ・グラフ・データの手動索引の使用の次の項目を参照してください。
/backends/{backendName}
説明: グラフ・サーバーの使用可能なバックエンドのリストから指定されたバックエンドを削除します。削除したバックエンドの情報を返します。
パラメータ
backendName
:
使用上の注意
(なし。)
例
次のPUT操作
結果は次のようになります。
{"backend":{"backendName":"hbase_connection","isDefault":false,"port":"2181","backendType":"HBaseBackendConnection","quorum":"127.0.0.1"},"queryTime":0.207346,"upTime":"0[d]:00[h]:18[m]:40[s]"}
/graphs/{graphName}/edges/<id>
説明: 指定されたグラフから指定されたエッジIDを持つエッジを削除します。
パラメータ
id
:
使用上の注意
このAPIは操作にかかった時間を返します。
例
次の例は、ID 1010のエッジを削除します。
http://localhost:7001/opg_unified/dal/graphs/connections/edges/1010
操作が正常に行われた場合、次のようなレスポンスが表示されます。
{ "queryTime": 10.925611 }
/graphs/{graphName}/indices/{IndexName}
説明: 指定されたグラフから指定された手動索引を削除します。
パラメータ
graphName
:
indexName
:
使用上の注意
このDELETE操作は、OraclePropertyGraph.dropIndex(name)
メソッドの呼出しを実行します。
例
次の例では、手動索引myIdx
をconnections
グラフから削除します。
http:// localhost:7001/opg_unified/dal/graphs/connections/indices/myIdx
/graphs/{graphName}/keyindices/{class}/{keyName}
説明: 指定されたグラフから指定された自動索引を削除します。
パラメータ
graphName
:
indexName
:
使用上の注意
このDELETE操作は、OraclePropertyGraph.dropKeyIndex(name,class)
メソッドの呼出しを実行します。
例
次の例では、自動索引myVKeyIdx
をconnections
グラフから削除します。
http:// localhost:7001/opg_unified/dal/graphs/connections/keyindices/vertex/myVKeyIdx
ソフトウェア・インストールには、プロパティ・グラフの作成および操作方法を習得するために使用できる、プログラムの例のディレクトリが含まれています。
サンプル・プログラムは、examples/dal
という名前のインストール・サブディレクトリに配布されます。例はHBaseおよびOracle NoSQL Database用にレプリケートされるため、選択したバックエンド・データベースに対応するプログラムのセットを使用できます。次の表に、プログラムの要素を示します。
表5-4 プロパティ・グラフのプログラム例(一部)
プログラム名 | 説明 |
---|---|
ExampleNoSQL1 ExampleHBase1 |
1つの頂点からなる最小プロパティ・グラフを作成し、様々なデータ型のプロパティを頂点に設定し、保存済のグラフの記述をデータベースに問い合せます。 |
ExampleNoSQL2 ExampleHBase2 |
Example1と同じ最小プロパティ・グラフを作成してから、それを削除します。 |
ExampleNoSQL3 ExampleHBase3 |
複数の頂点およびエッジを持つグラフを作成します。いくつかの頂点およびエッジを明示的に削除し、その他は他の必須オブジェクトを削除することによって暗黙的に削除します。この例は、オブジェクトの現在のリストを表示するために、データベースを繰り返し問い合せます。 |
Javaソース・ファイルをコンパイルおよび実行するには、次のようにします。
例のディレクトリに変更します。
cd examples/dal
Javaコンパイラを使用します。
javac -classpath ../../lib/'*' filename.java
例: javac -classpath ../../lib/'*' ExampleNoSQL1.java
コンパイルしたコードを実行します。
java -classpath ../../lib/'*':./ filename args
引数は、グラフを格納するためにOracle NoSQL DatabaseまたはApache HBaseのいずれを使用しているかによって異なります。値はOraclePropertyGraph.getInstance
に渡されます。
Apache HBaseの引数の説明
HBaseの例を使用している場合は、次の引数を指定します。
quorum: "node01.example.com, node02.example.com, node03.example.com"
など、HBaseの実行ノードを識別する名前のカンマ区切りリスト。
client_port: "2181"
など、HBaseクライアントのポート番号。
graph_name: "customer_graph"
など、グラフの名前。
Oracle NoSQL Databaseの引数の説明
NoSQLの例を使用している場合は、次の引数を指定します。
host_name: "cluster02:5000"
など、Oracle NoSQL Database登録のクラスタ名およびポート番号。
store_name: "kvstore"
など、キー値ストアの名前
graph_name: "customer_graph"
など、グラフの名前。
プログラムの例は、System.out.println
を使用して、プロパティ・グラフの記述を格納先のデータベース(Oracle NoSQL DatabaseまたはApache HBaseのいずれか)から取得します。キー名、データ型および値はコロンで区切られます。たとえば、weight:flo:30.0
は、キー名がweight
、データ型がfloat
、値が30.0
であることを示しています。
表5-5に、出力で使用されるデータ型の略称を示します。
表5-5 プロパティ・グラフのデータ型の略称
略称 | データ型 |
---|---|
bol |
Boolean |
dat |
date |
dbl |
double |
flo |
float |
int |
integer |
ser |
serializable |
str |
string |
ExampleNoSQL1
およびExampleHBase1
は、1つの頂点からなる最小プロパティ・グラフを作成します。例5-5のコード・フラグメントは、v1
という名前の頂点を作成し、様々なデータ型のプロパティを設定します。次に、保存済のグラフの記述をデータベースに問い合せます。
例5-5 プロパティ・グラフの作成
// Create a property graph instance named opg
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args);
// Clear all vertices and edges from opg
opg.clearRepository();
// Create vertex v1 and assign it properties as key-value pairs
Vertex v1 = opg.addVertex(1l);
v1.setProperty("age", Integer.valueOf(18));
v1.setProperty("name", "Name");
v1.setProperty("weight", Float.valueOf(30.0f));
v1.setProperty("height", Double.valueOf(1.70d));
v1.setProperty("female", Boolean.TRUE);
// Save the graph in the database
opg.commit();
// Display the stored vertex description
System.out.println("Fetch 1 vertex: " + opg.getVertices().iterator().next());
// Close the graph instance
opg.shutdown();
OraclePropertyGraph.getInstance
引数(args)は、グラフを格納するためにOracle NoSQL DatabaseまたはApache HBaseのいずれを使用しているかによって異なります。「サンプル・プログラムのコンパイルおよび実行」を参照してください。
System.out.println
は次の出力を表示します。
Fetch 1 vertex: Vertex ID 1 {age:int:18, name:str:Name, weight:flo:30.0, height:dbl:1.7, female:bol:true}
次については、プロパティ・グラフ・サポートのJavadoc (デフォルトでは/opt/oracle/oracle-spatial-graph/property_graph/doc/pgx
)を参照してください。
OraclePropertyGraph.addVertex OraclePropertyGraph.clearRepository OraclePropertyGraph.getInstance OraclePropertyGraph.getVertices OraclePropertyGraph.shutdown Vertex.setProperty
ExampleNoSQL2およびExampleHBase2は、「例: プロパティ・グラフの作成」で作成したようなグラフを作成し、それをデータベースから削除します。
例5-6のコード・フラグメントは、グラフを削除します。OraclePropertyGraphUtils.dropPropertyGraph
引数の説明は、「サンプル・プログラムのコンパイルおよび実行」を参照してください。
例5-6 プロパティ・グラフの削除
// Drop the property graph from the database OraclePropertyGraphUtils.dropPropertyGraph(args); // Display confirmation that the graph was dropped System.out.println("Graph " + graph_name + " dropped. ");
System.out.println
は次の出力を表示します。
Graph graph_name dropped.
OraclePropertyGraphUtils.dropPropertyGraph
のJavadocを参照してください。
ExampleNoSQL3およびExampleHBase3は、頂点とエッジの両方を追加および削除します。
例5-7 頂点の作成
例5-7のコード・フラグメントは、3つの頂点を作成します。これは例5-5をシンプルにしたバリエーションです。
// Create a property graph instance named opg
OraclePropertyGraph opg = OraclePropertyGraph.getInstance(args);
// Clear all vertices and edges from opg
opg.clearRepository();
// Add vertices a, b, and c
Vertex a = opg.addVertex(1l);
a.setProperty("name", "Alice");
a.setProperty("age", 31);
Vertex b = opg.addVertex(2l);
b.setProperty("name", "Bob");
b.setProperty("age", 27);
Vertex c = opg.addVertex(3l);
c.setProperty("name", "Chris");
c.setProperty("age", 33);
例5-8 エッジの作成
例5-8のコード・フラグメントは、頂点a、bおよびcを使用してエッジを作成します。
// Add edges e1, e2, and e3 Edge e1 = opg.addEdge(1l, a, b, "knows"); e1.setProperty("type", "partners"); Edge e2 = opg.addEdge(2l, a, c, "knows"); e2.setProperty("type", "friends"); Edge e3 = opg.addEdge(3l, b, c, "knows"); e3.setProperty("type", "colleagues");
例5-9 エッジおよび頂点の削除
例5-9のコード・フラグメントは、エッジe3
と頂点b
を明示的に削除します。これにより、頂点b
に接続していたエッジe1
が暗黙的に削除されます。
// Remove edge e3 opg.removeEdge(e3); // Remove vertex b and all related edges opg.removeVertex(b);
例5-10 頂点およびエッジの問合せ
この例は、データベースに問い合せて、オブジェクトがいつ追加および削除されるかを表示します。例5-10のコード・フラグメントは、使用されるメソッドを表示します。
// Print all vertices vertices = opg.getVertices().iterator(); System.out.println("----- Vertices ----"); vCount = 0; while (vertices.hasNext()) { System.out.println(vertices.next()); vCount++; } System.out.println("Vertices found: " + vCount); // Print all edges edges = opg.getEdges().iterator(); System.out.println("----- Edges ----"); eCount = 0; while (edges.hasNext()) { System.out.println(edges.next()); eCount++; } System.out.println("Edges found: " + eCount);
このトピックの例では、次のような出力が生成されます。
----- Vertices ---- Vertex ID 3 {name:str:Chris, age:int:33} Vertex ID 1 {name:str:Alice, age:int:31} Vertex ID 2 {name:str:Bob, age:int:27} Vertices found: 3 ----- Edges ---- Edge ID 2 from Vertex ID 1 {name:str:Alice, age:int:31} =[knows]=> Vertex ID 3 {name:str:Chris, age:int:33} edgeKV[{type:str:friends}] Edge ID 3 from Vertex ID 2 {name:str:Bob, age:int:27} =[knows]=> Vertex ID 3 {name:str:Chris, age:int:33} edgeKV[{type:str:colleagues}] Edge ID 1 from Vertex ID 1 {name:str:Alice, age:int:31} =[knows]=> Vertex ID 2 {name:str:Bob, age:int:27} edgeKV[{type:str:partners}] Edges found: 3 Remove edge Edge ID 3 from Vertex ID 2 {name:str:Bob, age:int:27} =[knows]=> Vertex ID 3 {name:str:Chris, age:int:33} edgeKV[{type:str:colleagues}] ----- Vertices ---- Vertex ID 1 {name:str:Alice, age:int:31} Vertex ID 2 {name:str:Bob, age:int:27} Vertex ID 3 {name:str:Chris, age:int:33} Vertices found: 3 ----- Edges ---- Edge ID 2 from Vertex ID 1 {name:str:Alice, age:int:31} =[knows]=> Vertex ID 3 {name:str:Chris, age:int:33} edgeKV[{type:str:friends}] Edge ID 1 from Vertex ID 1 {name:str:Alice, age:int:31} =[knows]=> Vertex ID 2 {name:str:Bob, age:int:27} edgeKV[{type:str:partners}] Edges found: 2 Remove vertex Vertex ID 2 {name:str:Bob, age:int:27} ----- Vertices ---- Vertex ID 1 {name:str:Alice, age:int:31} Vertex ID 3 {name:str:Chris, age:int:33} Vertices found: 2 ----- Edges ---- Edge ID 2 from Vertex ID 1 {name:str:Alice, age:int:31} =[knows]=> Vertex ID 3 {name:str:Chris, age:int:33} edgeKV[{type:str:friends}] Edges found: 1
プロパティ・グラフは、頂点用の記述ファイルとエッジ用の記述ファイルの2つのフラット・ファイルに定義できます。
ファイルのペアにより、プロパティ・グラフが記述されます。
頂点ファイル: プロパティ・グラフの頂点を記述します。このファイルには、.opv
というファイル名拡張子が付きます。
エッジ・ファイル: プロパティ・グラフのエッジを記述します。このファイルには、.ope
というファイル名拡張子が付きます。
これら2つのファイルは同じベース名を共有することをお薦めします。たとえば、simple.opv
およびsimple.ope
によってプロパティ・グラフを定義します。
頂点ファイルの各行は、プロパティ・グラフの1つの頂点を記述する1つのレコードです。1つのレコードは1つの頂点の1つのキー値プロパティを記述できるため、複数のプロパティを持つ頂点を記述する場合は複数のレコード/行が使用されます。
レコードには、カンマで区切られた6つのフィールドが含まれています。各レコードには、値があるかどうかに関係なく、すべてのフィールドを区切るために5つのカンマが含まれている必要があります。
vertex_ID, key_name, value_type, value, value, value
表5-6に、頂点ファイルのレコードを構成するフィールドを示します。
表5-6 頂点ファイルのレコードの形式
フィールド番号 | 名前 | 説明 |
---|---|---|
1 |
vertex_ID |
頂点を一意に識別する整数 |
2 |
key_name |
キー値ペアのキーの名前 頂点にプロパティが指定されていない場合は、空白( 1,%20,,,, |
3 |
value_type |
キー値ペアの値のデータ型を表す整数。
|
4 |
value |
数値でもタイムスタンプ(日付)でもない場合のkey_nameのエンコードされたnullでない値 |
5 |
value |
数値である場合のkey_nameのエンコードされたnullでない値 |
6 |
value |
タイムスタンプ(日付)である場合のkey_nameのエンコードされたnullでない値 日付の形式を識別するには、Java SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); encode(sdf.format((java.util.Date) value)); |
頂点の必須グループ化: 1つの頂点には複数のプロパティを指定でき、頂点ファイルには、頂点IDとその頂点の1つのプロパティの組合せごとに1つのレコード(フラット・ファイル内の単一テキスト行によって表される)が含まれます。頂点ファイルでは、各頂点のすべてのレコードがまとめてグループ化されている(つまり、他の頂点のレコードが間に入っていない)必要があります。これは任意の方法で行えますが、便利な方法は、頂点ファイルのレコードを頂点ID別に昇順(または降順)にソートすることです。(ただし、頂点ファイルのすべてのレコードを頂点ID別にソートする必要があるわけではありません。これはグループ化要件を満たすための単なる1つの方法です。)
Oracleフラット・ファイル形式で頂点ファイルを構築する場合、頂点プロパティ名および値フィールドが正しくエンコードされていることを確認することが重要です(特に「特殊文字のエンコーディング」を参照してください)。エンコードを簡略化するには、OraclePropertyGraphUtils.escape
Java APIを使用できます。
OraclePropertyGraphUtils.outputVertexRecord(os, vid, key, value)
ユーティリティ・メソッドを使用して、Oracleフラット・ファイル形式で頂点レコードを直接シリアル化できます。このメソッドを使用すると、特殊文字のエンコーディングについて心配する必要がなくなります。このメソッドは、vidによって識別される特定の頂点のkey/valueプロパティを表す特定の出力ストリーム内のテキストの新しい行を作成します。
例5-11 OraclePropertyGraphUtils.outputVertexRecordの使用
この例では、OraclePropertyGraphUtils.outputVertexRecord
を使用して頂点1の2つの新しい行を作成します。
String opv = "./example.opv"; OutputStream os = new FileOutputStream(opv); int birthYear = 1961; long vid = 1; OraclePropertyGraphUtils.outputVertexRecord(os, vid, "name", "Barack Obama"); OraclePropertyGraphUtils.outputVertexRecord(os, vid, "birth year", birthYear); os.flush(); os.close();
生成された出力ファイルの最初の行は、値"Barack Obama"を持つプロパティ名を示し、2番目の行は、その誕生日である1961を示します。
% cat example.opv 1,name,Barack%20Obama,, 1,birth%20year,2,,1961,
エッジ・ファイルの各行は、プロパティ・グラフの1つのエッジを記述する1つのレコードです。1つのレコードは1つのエッジの1つのキー値プロパティを記述できるため、複数のプロパティを持つエッジを記述する場合は複数のレコードが使用されます。
レコードには、カンマで区切られた9つのフィールドが含まれています。各レコードには、値があるかどうかに関係なく、すべてのフィールドを区切るために8つのカンマが含まれている必要があります。
edge_ID, source_vertex_ID, destination_vertex_ID, edge_label, key_name, value_type, value, value, value
表5-7に、エッジ・ファイルのレコードを構成するフィールドを示します。
表5-7 エッジ・ファイルのレコードの形式
フィールド番号 | 名前 | 説明 |
---|---|---|
1 |
edge_ID |
エッジを一意に識別する整数 |
2 |
source_vertex_ID |
エッジの出力始点のvertex_ID。 |
3 |
destination_vertex_ID |
エッジの入力終点のvertex_ID。 |
4 |
edge_label |
2つの頂点間の関係を記述する、エッジのエンコードされたラベル |
5 |
key_name |
キー値ペアのキーのエンコードされた名前 エッジにプロパティが指定されていない場合は、空白( 100,1,2,likes,%20,,,, |
6 |
value_type |
キー値ペアの値のデータ型を表す整数。
|
7 |
value |
数値でもタイムスタンプ(日付)でもない場合のkey_nameのエンコードされたnullでない値 |
8 |
value |
数値である場合のkey_nameのエンコードされたnullでない値 |
9 |
value |
タイムスタンプ(日付)である場合のkey_nameのエンコードされたnullでない値 日付の形式を識別するには、Java SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'Th'HH:mm:ss.SSSXXX"); encode(sdf.format((java.util.Date) value)); |
エッジの必須グループ化: 1つのエッジには複数のプロパティを指定でき、エッジ・ファイルには、エッジIDとそのエッジの1つのプロパティの組合せごとに1つのレコード(フラット・ファイル内の単一テキスト行によって表される)が含まれます。エッジ・ファイルでは、各エッジのすべてのレコードがまとめてグループ化されている(つまり、他のエッジのレコードが間に入っていない)必要があります。これは任意の方法で行えますが、便利な方法は、エッジ・ファイルのレコードをエッジID別に昇順(または降順)にソートすることです。(ただし、エッジ・ファイルのすべてのレコードをエッジID別にソートする必要があるわけではありません。これはグループ化要件を満たすための単なる1つの方法です。)
Oracleフラット・ファイル形式でエッジ・ファイルを構築する場合、エッジ・プロパティ名および値フィールドが正しくエンコードされていることを確認することが重要です(特に「特殊文字のエンコーディング」を参照してください)。エンコードを簡略化するには、OraclePropertyGraphUtils.escape
Java APIを使用できます。
OraclePropertyGraphUtils.outputEdgeRecord(os, eid, svid, dvid, label, key, value)
ユーティリティ・メソッドを使用して、Oracleフラット・ファイル形式でエッジ・レコードを直接シリアル化できます。このメソッドを使用すると、特殊文字のエンコーディングについて心配する必要がなくなります。このメソッドは、eidによって識別される特定のエッジのkey/valueプロパティを表す特定の出力ストリーム内のテキストの新しい行を作成します。
例5-12 OraclePropertyGraphUtils.outputEdgeRecordの使用
この例では、OraclePropertyGraphUtils.outputEdgeRecord
を使用して、頂点1と頂点2の間のエッジ100の2つの新しい行をラベルfriendOf
を使用して作成します。
String ope = "./example.ope"; OutputStream os = new FileOutputStream(ope); int sinceYear = 2009; long eid = 100; long svid = 1; long dvid = 2; OraclePropertyGraphUtils.outputEdgeRecord(os, eid, svid, dvid, "friendOf", "since (year)", sinceYear); OraclePropertyGraphUtils.outputEdgeRecord(os, eid, svid, dvid, "friendOf", "weight", 1); os.flush(); os.close();
生成された出力ファイルの最初の行はプロパティ“since (year)"を値2009で表し、2番目の行と次の行はエッジの重みを1に設定しています
% cat example.ope 100,1,2,friendOf,since%20(year),2,,2009, 100,1,2,friendOf,weight,2,,1,
頂点およびエッジ・ファイルのエンコーディングはUTF-8です。表5-8に、頂点またはエッジ・プロパティ(キー値ペア)またはエッジ・ラベルに表示されるときに文字列としてエンコードされる必要のある特殊文字をリストします。その他すべての文字は、エンコーディングは必要ありません。
表5-8 Oracleフラット・ファイル形式での特殊文字コード
特殊文字 | 文字列のエンコーディング | 説明 |
---|---|---|
|
|
パーセント |
|
|
タブ |
|
|
スペース |
|
|
改行 |
|
|
リターン |
|
|
カンマ |
Oracleフラット・ファイル形式でのプロパティ・グラフの例を次に示します。この例では、2つの頂点(JohnおよびMary)と、JohnがMaryの友人であることを示す単一のエッジがあります。
%cat simple.opv 1,age,2,,10, 1,name,1,John,, 2,name,1,Mary,, 2,hobby,1,soccer,, %cat simple.ope 100,1,2,friendOf,%20,,,,
グラフの頂点およびエッジを表すOracle Database表をOracle定義のフラット・ファイル形式(.opv
および.ope
ファイル拡張子)に変換できます。
グラフ・データがOracle Database表に格納されている場合、Java APIメソッドを使用してこのデータをフラット・ファイルに変換し、後で表をプロパティ・グラフとしてOracle Databaseにロードできます。これにより、既存のOracle Database表からフラット・ファイルを生成するために他の手動アプローチを使用する必要がなくなります。
グラフの頂点が格納された表から.opvファイルへの変換
(グラフの頂点として表すことができる)エンティティが含まれるOracle Database表を.opv
形式のプロパティ・グラフ・フラット・ファイルに変換できます。
たとえば、EmployeeTab (empID integer not null, hasName varchar(255), hasAge integer, hasSalary number)
というリレーショナル表を想定します
この表に次のデータがあるとします。
101, Jean, 20, 120.0 102, Mary, 21, 50.0 103, Jack, 22, 110.0 ……
各従業員をグラフ内の頂点として捉えることができます。頂点IDは、employeeID、またはハッシュなどのヒューリスティックを使用して生成されたIDの値である場合があります。列hasName、hasAgeおよびhasSalaryは属性として捉えることができます。
JavaメソッドOraclePropertyGraphUtils.convertRDBMSTable2OPV
およびそのJavadoc情報は、次のとおりです。
/** * conn: is an connect instance to the Oracle relational database * rdbmsTableName: name of the RDBMS table to be converted * vidColName is the name of an column in RDBMS table to be treated as vertex ID * lVIDOffset is the offset will be applied to the vertex ID * ctams defines how to map columns in the RDBMS table to the attributes * dop degree of parallelism * dcl an instance of DataConverterListener to report the progress and control the behavior when errors happen */ OraclePropertyGraphUtils.convertRDBMSTable2OPV( Connection conn, String rdbmsTableName, String vidColName, long lVIDOffset, ColumnToAttrMapping[] ctams, int dop, OutputStream opvOS, DataConverterListener dcl);
次のコード・スニペットは、この表をOracle定義の頂点ファイル(.opv
)に変換します。
// location of the output file String opv = "./EmployeeTab.opv"; OutputStream opvOS = new FileOutputStream(opv); // an array of ColumnToAttrMapping objects; each object defines how to map a column in the RDBMS table to an attribute of the vertex in an Oracle Property Graph. ColumnToAttrMapping[] ctams = new ColumnToAttrMapping[3]; // map column "hasName" to attribute "name" of type String ctams[0] = ColumnToAttrMapping.getInstance("hasName", "name", String.class); // map column "hasAge" to attribute "age" of type Integer ctams[1] = ColumnToAttrMapping.getInstance("hasAge", "age", Integer.class); // map column "hasSalary" to attribute "salary" of type Double ctams[2] = ColumnToAttrMapping.getInstance("hasSalary", "salary",Double.class); // convert RDBMS table "EmployeeTab" into opv file "./EmployeeTab.opv", column "empID" is the vertex ID column, offset 1000l will be applied to vertex ID, use ctams to map RDBMS columns to attributes, set DOP to 8 OraclePropertyGraphUtils.convertRDBMSTable2OPV(conn, "EmployeeTab", "empID", 1000l, ctams, 8, opvOS, (DataConverterListener) null);
注意:
オフセット値1000l
内の最後の文字データ小文字"l"は、その前にある値が長整数であることを示します。
変換結果は次のとおりです。
1101,name,1,Jean,, 1101,age,2,,20, 1101,salary,4,,120.0, 1102,name,1,Mary,, 1102,age,2,,21, 1102,salary,4,,50.0, 1103,name,1,Jack,, 1103,age,2,,22, 1103,salary,4,,110.0,
この場合、表EmployeeTab内の各行は、3つの属性を持つ1つの頂点に変換されます。たとえば、データ"101, Jean, 20, 120.0"は、属性name/"Jean"、age/20、salary/120.0を持つID 1101の頂点に変換されます。オフセット1000lが適用されるため、元のempID 101と頂点ID 1101の間にはオフセットがあります。オフセットは、グラフ要素のID値の競合を回避する上で役に立ちます。
グラフのエッジが格納された表から.opeファイルへの変換
(グラフのエッジとして表すことができる)エンティティ関係が含まれるOracle Database表を.ope
形式のプロパティ・グラフ・フラット・ファイルに変換できます。
たとえば、EmpRelationTab (relationID integer not null, source integer not null, destination integer not null, relationType varchar(255), startDate date)
というリレーショナル表があると想定します
この表に次のデータがあるとします。
90001, 101, 102, manage, 10-May-2015 90002, 101, 103, manage, 11-Jan-2015 90003, 102, 103, colleague, 11-Jan-2015 ……
各リレーション(行)は、グラフ内のエッジとして捉えることができます。特に、エッジIDは、relationID、またはハッシュなどのヒューリスティックを使用して生成されたIDと同じである場合があります。列relationTypeはエッジ・ラベルを定義するために使用でき、列startDateはエッジ属性として扱うことができます。
JavaメソッドOraclePropertyGraphUtils.convertRDBMSTable2OPE
およびそのJavadoc情報は、次のとおりです。
/** * conn: is an connect instance to the Oracle relational database * rdbmsTableName: name of the RDBMS table to be converted * eidColName is the name of an column in RDBMS table to be treated as edge ID * lEIDOffset is the offset will be applied to the edge ID * svidColName is the name of an column in RDBMS table to be treated as source vertex ID of the edge * dvidColName is the name of an column in RDBMS table to be treated as destination vertex ID of the edge * lVIDOffset is the offset will be applied to the vertex ID * bHasEdgeLabelCol a Boolean flag represents if the given RDBMS table has a column for edge labels; if true, use value of column elColName as the edge label; otherwise, use the constant string elColName as the edge label * elColName is the name of an column in RDBMS table to be treated as edge labels * ctams defines how to map columns in the RDBMS table to the attributes * dop degree of parallelism * dcl an instance of DataConverterListener to report the progress and control the behavior when errors happen */ OraclePropertyGraphUtils.convertRDBMSTable2OPE( Connection conn, String rdbmsTableName, String eidColName, long lEIDOffset, String svidColName, String dvidColName, long lVIDOffset, boolean bHasEdgeLabelCol, String elColName, ColumnToAttrMapping[] ctams, int dop, OutputStream opeOS, DataConverterListener dcl);
次のコード・スニペットは、この表をOracle定義のエッジ・ファイル(.ope
)に変換します。
// location of the output file String ope = "./EmpRelationTab.ope"; OutputStream opeOS = new FileOutputStream(ope); // an array of ColumnToAttrMapping objects; each object defines how to map a column in the RDBMS table to an attribute of the edge in an Oracle Property Graph. ColumnToAttrMapping[] ctams = new ColumnToAttrMapping[1]; // map column "startDate" to attribute "since" of type Date ctams[0] = ColumnToAttrMapping.getInstance(“startDate", “since",Date.class); // convert RDBMS table “EmpRelationTab" into ope file “./EmpRelationTab.opv", column “relationID" is the edge ID column, offset 10000l will be applied to edge ID, the source and destination vertices of the edge are defined by columns “source" and “destination", offset 1000l will be applied to vertex ID, the RDBMS table has an column “relationType" to be treated as edge labels, use ctams to map RDBMS columns to edge attributes, set DOP to 8 OraclePropertyGraphUtils.convertRDBMSTable2OPE(conn, “EmpRelationTab", “relationID", 10000l, “source", “destination", 1000l, true, “relationType", ctams, 8, opeOS, (DataConverterListener) null);
注意:
オフセット値10000l
内の最後の文字データ小文字"l"は、その前にある値が長整数であることを示します。
変換結果は次のとおりです。
100001,1101,1102,manage,since,5,,,2015-05-10T00:00:00.000-07:00 100002,1101,1103,manage,since,5,,,2015-01-11T00:00:00.000-07:00 100003,1102,1103,colleague,since,5,,,2015-01-11T00:00:00.000-07:00
この場合、表EmpRelationTab内の各行は、属性since
を持つ個別エッジに変換されます。たとえば、データ“90001, 101, 102, manage, 10-May-2015"を持つ行は、頂点1101と頂点1102をリンクするID 100001を持つエッジに変換されます。このエッジは、属性since/“2015-05-10T00:00:00.000-07:00"を持ちます。オフセット10000lが適用されるため、元のrelationID “90001"とエッジID “100001"の間にはオフセットがあります。同様に、オフセット1000lがソース頂点IDおよび宛先頂点IDに適用されます。
一部のアプリケーションでは、CSV (カンマ区切りの値)形式を使用してグラフの頂点およびエッジをエンコードします。この形式では、CSVファイルの各レコードが、単一の頂点またはエッジおよびそのプロパティを表します。グラフの頂点を表すCSVファイルをOracle定義のフラット・ファイル形式定義(頂点を表す.opv
、エッジを表す.ope
)に変換できます。
変換するCSVファイルには、列が表す属性の列名および型を指定するヘッダー行が含まれる場合があります。ヘッダーに属性名のみが含まれる場合、コンバータでは、値のデータ型が文字列であると見なされます。
CSVをOPVまたはOPEに変換するJava APIは、InputStream
を受け取り、ここから頂点またはエッジを(CSVから)読み込み、これらを.opv
または.ope
形式でOutputStream
に書き込みます。コンバータのAPIを使用して変換プロセスをカスタマイズすることもできます。
次のサブトピックでは、頂点およびエッジの変換の手順を示します。最初の2つの手順は非常に似ていますが、頂点およびエッジに固有の差異があります。
CSVファイルにヘッダーが含まれない場合、CSVファイルに表示される順序と同じ順序ですべての属性名(値のデータ型にマップされたもの)が表されたColumnToAttrMapping
配列を指定する必要があります。また、頂点のIDなどの特別な列などを含む、CSVファイル内の列全体をこの配列内に記述する必要があります。同じCSVファイルの最初の行内の列にヘッダーを指定するには、このパラメータをnullに設定する必要があります。
頂点を表すCSVファイルを変換するには、convertCSV2OPV
APIの1つを使用できます。これらのAPIのうち最も単純なものには、次が必要です。
CSVファイルから頂点を読み取るInputStream
頂点IDを表す列の名前(この列はCSVファイル内に表示される必要があります)
VIDに追加する整数のオフセット(オフセットはグラフ要素のID値の競合を回避する上で役に立ちます)
ColumnToAttrMapping
配列(ファイル内にヘッダーが指定されている場合、nullである必要があります)
並列度(DOP)
変換前のオフセット(スキップする頂点レコードの数)を表す整数
頂点フラット・ファイル(.opv)の書込み先のOutputStream
変換の進捗状況を追跡し、エラーが発生したときに何をすべきか決定するために使用できるオプションのDataConverterListener
追加パラメータを使用して、CSVファイルの異なる形式を指定できます。
レコード内のトークンを区切るために使用されるデリミタ文字。デフォルトはカンマ文字',’です。
文字列値に特殊文字(カンマなど)が含めることができるように文字列値に引用符を付けるために使用する引用符。文字列自体の値に引用符を使用する場合、引用符を複製するか引用符の前にバックスラッシュ文字'\'を配置してエスケープする必要があります。例をいくつか示します。
"画面に、""Hello, world""と表示され…"
"しかし、ベーダーは、\"いや、私がお前の父親だ\"と答えた。"
日付値を解析するために使用する日付形式。CSV変換の場合、このパラメータはnullにすることができますが、CSVに特定の日付形式が使用されている場合は指定することをお薦めします。特定の日付形式を指定すると、日付値を解析しようとするときにこの形式が最初のオプションとして使用されるため、パフォーマンスが向上します。日付形式の例をいくつか示します。
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
"MM/dd/yyyy HH:mm:ss"
"ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"
"dddd, dd MMMM yyyy hh:mm:ss"
"yyyy-MM-dd"
"MM/dd/yyyy"
CSVファイルに文字列値とともに改行文字が含まれるかどうかを示すフラグ。このパラメータがtrueに設定されている場合、改行または引用符が値として含まれるファイル内のすべての文字列に引用符を付ける必要があります。
"ドンキホーテの1行目は、""名前は思い出せないが、ラ・マンチャのある村に、""です。"
次のコード・フラグメントは、ColumnToAttrMapping
配列を作成し、APIを使用してCSVファイルを.opv
ファイルに変換する方法を示します。
String inputCSV = "/path/mygraph-vertices.csv"; String outputOPV = "/path/mygraph.opv"; ColumnToAttrMapping[] ctams = new ColumnToAttrMapping[4]; ctams[0] = ColumnToAttrMapping.getInstance("VID", Long.class); ctams[1] = ColumnToAttrMapping.getInstance("name", String.class); ctams[2] = ColumnToAttrMapping.getInstance("score", Double.class); ctams[3] = ColumnToAttrMapping.getInstance("age", Integer.class); String vidColumn = "VID"; isCSV = new FileInputStream(inputCSV); osOPV = new FileOutputStream(new File(outputOPV)); // Convert Vertices OraclePropertyGraphUtilsBase.convertCSV2OPV(isCSV, vidColumn, 0, ctams, 1, 0, osOPV, null); isOPV.close(); osOPV.close();
この例では、変換対象のCSVファイルには、ヘッダーを含めず、4つの列(頂点ID、名前、スコアおよび年齢)を含める必要があります。CVSの例を次に示します。
1,John,4.2,30 2,Mary,4.3,32 3,"Skywalker, Anakin",5.0,46 4,"Darth Vader",5.0,46 5,"Skywalker, Luke",5.0,53
生成される.opv
ファイルは、次のとおりです。
1,name,1,John,, 1,score,4,,4.2, 1,age,2,,30, 2,name,1,Mary,, 2,score,4,,4.3, 2,age,2,,32, 3,name,1,Skywalker%2C%20Anakin,, 3,score,4,,5.0, 3,age,2,,46, 4,name,1,Darth%20Vader,, 4,score,4,,5.0, 4,age,2,,46, 5,name,1,Skywalker%2C%20Luke,, 5,score,4,,5.0, 5,age,2,,53,
頂点データが含まれるCSVファイルを変換するもう1つの方法は、次の入力引数の1つとしてCSV2OPVConfig
オブジェクトを使用するconvertCSV2OPV
APIを使用する方法です。
CSVファイルから頂点を読み取るInputStream
構成を指定するCSV2OPVConfig
オブジェクト
頂点フラット・ファイル(.opv)の書込み先のOutputStream
CSV2OPVConfig
クラスには、目的のチューニングに応じて設定できる各種メンバーがあります。これは、各種構成パラメータをすべて使用してconvertCSV2OPV
APIを呼び出すことと等価です。
次のコード・フラグメントは、CSV2OPVConfig
オブジェクトを作成し、APIを使用してCSVファイルを.opv
ファイルに変換する方法を示します。
String inputCSV = "/path/mygraph-vertices.csv"; String outputOPV = "/path/mygraph.opv"; ColumnToAttrMapping[] ctams = new ColumnToAttrMapping[4]; ctams[0] = ColumnToAttrMapping.getInstance("VID", Long.class); ctams[1] = ColumnToAttrMapping.getInstance("name", String.class); ctams[2] = ColumnToAttrMapping.getInstance("score", Double.class); ctams[3] = ColumnToAttrMapping.getInstance("age", Integer.class); InputStream isCSV = new FileInputStream(inputCSV); OutputStream osOPV = new FileOutputStream(new File(outputOPV)); CSV2OPVConfig config = (CSV2OPVConfig) new CSV2OPVConfig() .setVidColumnName("VID") .setCtams(ctams) .setAllowExtraFields(false) .setDelimiterChar(',') .setQuotationChar('"'); // Convert vertices OraclePropertyGraphCSVConverter.convertCSV2OPV(isCSV, config, osOPV); isCSV.close(); osOPV.close();
CSV2OPVConfig
にColumnToAttrMapping
配列が含まれる場合、ColumnToAttrMapping
配列にマッピングがすでに定義されているため、入力CSVにはヘッダーを含めないようにする必要があります。また、setAllowExtraFields
フラグがCSV2OPVConfig
内でfalse
に設定されているため、CSVファイル内の列の数がColumnToAttrMapping
配列の長さと一致する必要があります(この例では、1つは頂点ID用、2番目は名前用、3番目はスコア用、4番目は年齢用です)。CSVの例を次に示します。
1,John,4.2,30 2,Mary,4.3,32 3,"Skywalker, Anakin",5.0,46 4,"Darth Vader",5.0,46 5,"Skywalker, Luke",5.0,53
生成される.opv
ファイルは、次のとおりです。
1,name,1,John,, 1,score,4,,4.2, 1,age,2,,30, 2,name,1,Mary,, 2,score,4,,4.3, 2,age,2,,32, 3,name,1,Skywalker%2C%20Anakin,, 3,score,4,,5.0, 3,age,2,,46, 4,name,1,Darth%20Vader,, 4,score,4,,5.0, 4,age,2,,46, 5,name,1,Skywalker%2C%20Luke,, 5,score,4,,5.0, 5,age,2,,53,
CSVファイルにヘッダーが含まれない場合、CSVファイルに表示される順序と同じ順序ですべての属性名(値のデータ型にマップされたもの)が表されたColumnToAttrMapping
配列を指定する必要があります。また、CSVファイルの列全体を配列内に記述する必要があり、これには、エッジのID (適用される場合)、および必須のSTART_ID、END_IDおよびTYPEなどが含まれます。同じCSVファイルの最初の行内の列にヘッダーを指定するには、このパラメータをnullに設定する必要があります。
頂点を表すCSVファイルを変換するには、convertCSV2OPE
APIの1つを使用できます。これらのAPIのうち最も単純なものには、次が必要です。
CSVファイルから頂点を読み取るInputStream
エッジIDを表す列の名前(これは、存在しない場合、CSVファイル内でオプションです。その場合、行番号がIDとして使用されます)
EIDに追加する整数のオフセット(オフセットはグラフ要素のID値の競合を回避する上で役に立ちます)
ソース頂点IDを表す列の名前(この列はCSVファイル内に表示される必要があります)
宛先頂点IDを表す列の名前(この列はCSVファイル内に表示される必要があります)
VIDへのオフセット(lOffsetVID
)。このオフセットは、元のSVIDおよびDVID値の上に追加されます。(このAPIのバリエーションには、2つの引数(lOffsetSVID
およびlOffsetDVID
)が使用されます。1つはSVIDのオフセット用、もう1つはDVIDのオフセット用です。)
エッジ・ラベル列がCSVファイル内に存在するかどうかを示すブール・フラグ。
エッジ・ラベルを表す列の名前(この列がCSVファイル内に存在しない場合、このパラメータがすべてのエッジ・ラベルの定数として使用されます)
ColumnToAttrMapping
配列(ファイル内にヘッダーが指定されている場合、nullである必要があります)
並列度(DOP)
変換前のオフセット(スキップするエッジ・レコードの数)を表す整数
エッジ・フラット・ファイル(.ope)の書込み先のOutputStream
変換の進捗状況を追跡し、エラーが発生したときに何をすべきか決定するために使用できるオプションのDataConverterListener
追加パラメータを使用して、CSVファイルの異なる形式を指定できます。
レコード内のトークンを区切るために使用されるデリミタ文字。デフォルトはカンマ文字',’です。
文字列値に特殊文字(カンマなど)が含めることができるように文字列値に引用符を付けるために使用する引用符。文字列自体の値に引用符を使用する場合、引用符を複製するか引用符の前にバックスラッシュ文字'\'を配置してエスケープする必要があります。例をいくつか示します。
"画面に、""Hello, world""と表示され…"
"しかし、ベーダーは、\"いや、私がお前の父親だ\"と答えた。"
日付値を解析するために使用する日付形式。CSV変換の場合、このパラメータはnullにすることができますが、CSVに特定の日付形式が使用されている場合は指定することをお薦めします。特定の日付形式を指定すると、日付値を解析しようとするときにこの形式が最初のオプションとして使用されるため、パフォーマンスが向上します。日付形式の例をいくつか示します。
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
"MM/dd/yyyy HH:mm:ss"
"ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"
"dddd, dd MMMM yyyy hh:mm:ss"
"yyyy-MM-dd"
"MM/dd/yyyy"
CSVファイルに文字列値とともに改行文字が含まれるかどうかを示すフラグ。このパラメータがtrueに設定されている場合、改行または引用符が値として含まれるファイル内のすべての文字列に引用符を付ける必要があります。
"ドンキホーテの1行目は、""名前は思い出せないが、ラ・マンチャのある村に、""です。"
次のコード・フラグメントは、APIを使用して、nullのColumnToAttrMapping
配列を使用してCSVファイルを.ope
ファイルに変換する方法を示します。
String inputOPE = "/path/mygraph-edges.csv"; String outputOPE = "/path/mygraph.ope"; String eidColumn = null; // null implies that an integer sequence will be used String svidColumn = "START_ID"; String dvidColumn = "END_ID"; boolean hasLabel = true; String labelColumn = "TYPE"; isOPE = new FileInputStream(inputOPE); osOPE = new FileOutputStream(new File(outputOPE)); // Convert Edges OraclePropertyGraphUtilsBase.convertCSV2OPE(isOPE, eidColumn, 0, svidColumn, dvidColumn, hasLabel, labelColumn, null, 1, 0, osOPE, null);
変換対象の前の例を使用する入力CSVには、列名およびその型を指定するヘッダーを含める必要があります。CSVファイルの例を次に示します。
START_ID:long,weight:float,END_ID:long,:TYPE 1,1.0,2,loves 1,1.0,5,admires 2,0.9,1,loves 1,0.5,3,likes 2,0.0,4,likes 4,1.0,5,is the dad of 3,1.0,4,turns to 5,1.0,3,saves from the dark side
生成される.opeファイルは、次のとおりです。
1,1,2,loves,weight,3,,1.0, 2,1,5,admires,weight,3,,1.0, 3,2,1,loves,weight,3,,0.9, 4,1,3,likes,weight,3,,0.5, 5,2,4,likes,weight,3,,0.0, 6,4,5,is%20the%20dad%20of,weight,3,,1.0, 7,3,4,turns%20to,weight,3,,1.0, 8,5,3,saves%20from%20the%20dark%20side,weight,3,,1.0,
エッジ・データが含まれるCSVファイルを変換するもう1つの方法は、次の入力引数の1つとしてCSV2OPEConfig
オブジェクトを使用するconvertCSV2OPE
APIを使用する方法です。
CSVファイルからエッジを読み取るInputStream
構成を指定するCSV2OPVConfig
オブジェクト
エッジ・フラット・ファイル(.opv)の書込み先のOutputStream
CSV2OPEConfig
クラスには、目的のチューニングに応じて設定できる各種メンバーがあります。これは、各種構成パラメータをすべて使用してconvertCSV2OPE
APIを呼び出すことと等価です。
次のコード・フラグメントは、CSV2OPEConfig
オブジェクトを作成し、APIを使用してCSVファイルを.ope
ファイルに変換する方法を示します。
String inputOPE = "/path/mygraph-edges.csv"; String outputOPE = "/path/mygraph.ope"; String eidColumn = null; // null implies that an integer sequence will be used String svidColumn = "START_ID"; String dvidColumn = "END_ID"; boolean hasLabel = true; String labelColumn = "TYPE"; InputStream isCSV = new FileInputStream(inputOPE); OutputStream osOPE = new FileOutputStream(new File(outputOPE)); CSV2OPEConfig config = (CSV2OPEConfig) new CSV2OPEConfig() .setEidColumnName(eidColumn) .setSvidColumnName(svidColumn) .setDvidColumnName(dvidColumn) .setHasEdgeLabelColumn(hasLabel) .setElColumnName(labelColumn) .setCtams(null) .setDelimiterChar(',') .setQuotationChar('"'); // Convert Edges OraclePropertyGraphCSVConverter.convertCSV2OPE(isCSV, config, osOPE); isCSV.close(); osOPE.close();
CSV2OPEConfig
にColumnToAttrMapping
配列が含まれないか、この配列がnullに設定されている場合、入力CSVには、列名およびデータ型を指定ヘッダーを含める必要があります。CSVファイルの例を次に示します。
START_ID:long,weight:float,END_ID:long,:TYPE 1,1.0,2,loves 1,1.0,5,admires 2,0.9,1,loves 1,0.5,3,likes 2,0.0,4,likes 4,1.0,5,is the dad of 3,1.0,4,turns to 5,1.0,3,saves from the dark side
生成される.ope
ファイルは、次のとおりです。
1,1,2,loves,weight,3,,1.0, 2,1,5,admires,weight,3,,1.0, 3,2,1,loves,weight,3,,0.9, 4,1,3,likes,weight,3,,0.5, 5,2,4,likes,weight,3,,0.0, 6,4,5,is%20the%20dad%20of,weight,3,,1.0, 7,3,4,turns%20to,weight,3,,1.0, 8,5,3,saves%20from%20the%20dark%20side,weight,3,,1.0,
プロパティ・グラフのサポートでは、頂点とエッジの両方のデータが含まれる単一のCSVファイルをグラフ・フラット・ファイルのペアに変換するオプションも用意されています。convertCSV2OPG APIを使用すると、この変更を行うことができ、その入力パラメータは、次のとおりです。
CSVファイルから頂点およびエッジを読み取るInputStream
構成を指定するCSV2OPGConfig
オブジェクト
頂点フラット・ファイル(.opv
)の書込み先のOutputStream
エッジ・フラット・ファイル(.ope
)の書込み先のOutputStream
次のコード・フラグメントは、CSV2OPGConfig
オブジェクトを作成し、APIを使用して単一のCSVファイルを.opv
および.ope
ファイルに変換する方法を示します。
String inputCSV = "/path/mygraph.csv"; String outputOPV = "/path/mygraph.opv"; String outputOPE = "/path/mygraph.ope"; String eidColumn = null; // null implies that an integer sequence will be used String svidColumn = "START_ID"; String dvidColumn = "END_ID"; boolean hasLabel = true; String labelColumn = "TYPE"; String[] vertexNames = new String [2]; vertexNames[0] = svidColumn; vertexNames[1] = dvidColumn; InputStream isCSV = new FileInputStream(inputOPE); OutputStream osOPV = new FileOutputStream(new File(outputOPV)); OutputStream osOPE = new FileOutputStream(new File(outputOPE)); CSV2OPGConfig config = (CSV2OPGConfig) new CSV2OPGConfig() .setVidColumnNames(vertexNames) .setKeepOriginalID(true) .setOriginalIDName("myId") .setEidColumnName(eidColumn) .setSvidColumnName(svidColumn) .setDvidColumnName(dvidColumn) .setHasEdgeLabelColumn(hasLabel) .setElColumnName(labelColumn) .setCtams(null) .setDelimiterChar(',') .setQuotationChar('"'); // Convert Graph OraclePropertyGraphCSVConverter.convertCSV2OPG(isCSV, config, osOPV, osOPE); isCSV.close(); osOPV.close(); osOPE.close();
CSV2OPEConfig
にColumnToAttrMapping
配列が含まれないか、この配列がnullに設定されている場合、入力CSVには、列名およびデータ型を指定ヘッダーを含める必要があります。CSVファイルの例を次に示します。
START_ID:long,weight:float,END_ID:long,:TYPE John,1.0,Mary,loves John,1.0,"Skywalker, Luke",admires Mary,0.9,John,loves John,0.5,"Skywalker, Anakin",likes Mary,0.0,"Darth Vader",likes "Darth Vader",1.0,"Skywalker, Luke",is the dad of "Skywalker, Anakin",1.0,"Darth Vader",turns to "Skywalker, Luke",1.0,"Skywalker, Anakin",saves from the dark side
生成される.opv
ファイルは、次のとおりです。
-4984830045544402721,myId,1,John,, 6010046165116255926,myId,1,Mary,, -5861570303285508288,myId,1,Skywalker%2C%20Anakin,, -6450119557041804291,myId,1,Darth%20Vader,, 3941046021651468440,myId,1,Skywalker%2C%20Luke,,
生成される.ope
ファイルは、次のとおりです。
1,-4984830045544402721,6010046165116255926,loves,weight,3,,1.0, 2,-4984830045544402721,3941046021651468440,admires,weight,3,,1.0, 3,6010046165116255926,-4984830045544402721,loves,weight,3,,0.9, 4,-4984830045544402721,-5861570303285508288,likes,weight,3,,0.5, 5,6010046165116255926,-6450119557041804291,likes,weight,3,,0.0, 6,-6450119557041804291,3941046021651468440,is%20the%20dad%20of,weight,3,,1.0, 7,-5861570303285508288,-6450119557041804291,turns%20to,weight,3,,1.0, 8, 3941046021651468440,-5861570303285508288,saves%20from%20the%20dark%20side,weight,3,,1.0,
The Oracle Big Data Spatial and Graphのプロパティ・グラフ・サポートには、Pythonユーザー・インタフェースの例が含まれています。これは、様々なプロパティ・グラフ操作を実行するPythonスクリプトおよびモジュールの例のセットを起動できます。
Pythonユーザー・インタフェースの例のインストール手順は、インストール・ホーム(デフォルトでは/opt/oracle/oracle-spatial-graph
)の下にある/property_graph/examples/pyopg/README
ファイルにあります。
/property_graph/examples/pyopg/
にあるPythonスクリプトの例は、Oracle Spatial and Graphプロパティ・グラフとともに使用でき、ニーズに応じてその例(またはそのコピー)を変更および拡張できます。
例を実行するためにユーザー・インタフェースを起動するには、pyopg.sh
スクリプトを使用します。
例には次のものが含まれています。
例1: Oracle NoSQL Databaseに接続して、頂点およびエッジの数の単純なチェックを実行します。これを実行するには、次のようにします。
cd /opt/oracle/oracle-spatial-graph/property_graph/examples/pyopg ./pyopg.sh connectONDB("mygraph", "kvstore", "localhost:5000") print "vertices", countV() print "edges", countE()
前の例で、mygraph
はOracle NoSQL Databaseに格納されているグラフの名前で、kvstore
およびlocalhost:5000
はOracle NoSQL Databaseにアクセスするための接続情報です。これらは環境に応じてカスタマイズする必要があります。
例2: Apache HBaseに接続して、頂点およびエッジの数の単純なチェックを実行します。これを実行するには、次のようにします。
cd /opt/oracle/oracle-spatial-graph/property_graph/examples/pyopg ./pyopg.sh connectHBase("mygraph", "localhost", "2181") print "vertices", countV() print "edges", countE()
前の例で、mygraph
はApache HBaseに格納されているグラフの名前で、localhost
および2181
はApache HBaseにアクセスするための接続情報です。これらは環境に応じてカスタマイズする必要があります。
例3: Oracle NoSQL Databaseに接続していくつかの分析機能を実行します。これを実行するには、次のようにします。
cd /opt/oracle/oracle-spatial-graph/property_graph/examples/pyopg ./pyopg.sh connectONDB("mygraph", "kvstore", "localhost:5000") print "vertices", countV() print "edges", countE() import pprint analyzer = analyst() print "# triangles in the graph", analyzer.countTriangles() graph_communities = [{"commid":i.getName(),"size":i.size()} for i in analyzer.communities().iterator()] import pandas as pd import numpy as np community_frame = pd.DataFrame(graph_communities) community_frame[:5] import matplotlib as mpl import matplotlib.pyplot as plt fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(16,12)); community_frame["size"].plot(kind="bar", title="Communities and Sizes") ax.set_xticklabels(community_frame.index); plt.show()
前の例は、Oracle NoSQL Databaseに接続し、頂点およびエッジに関する基本情報を出力し、インメモリー・アナリストを取得し、トライアングル数を計算し、コミュニティ検出を実行して、最後にコミュニティとそのサイズを棒グラフに表します。
例4: Apache HBaseに接続していくつかの分析機能を実行します。これを実行するには、次のようにします。
cd /opt/oracle/oracle-spatial-graph/property_graph/examples/pyopg ./pyopg.sh connectHBase("mygraph", "localhost", "2181") print "vertices", countV() print "edges", countE() import pprint analyzer = analyst() print "# triangles in the graph", analyzer.countTriangles() graph_communities = [{"commid":i.getName(),"size":i.size()} for i in analyzer.communities().iterator()] import pandas as pd import numpy as np community_frame = pd.DataFrame(graph_communities) community_frame[:5] import matplotlib as mpl import matplotlib.pyplot as plt fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(16,12)); community_frame["size"].plot(kind="bar", title="Communities and Sizes") ax.set_xticklabels(community_frame.index); plt.show()
前の例は、Apache HBaseに接続し、頂点およびエッジに関する基本情報を出力し、インメモリー・アナリストを取得し、トライアングル数を計算し、コミュニティ検出を実行して、最後にコミュニティとそのサイズを棒グラフに表します。
Pythonインタフェースの例の詳細は、インストール・ホームの下にある次のディレクトリを参照してください。
property_graph/examples/pyopg/doc/
主なプロパティ・グラフ機能に対する次のタイプのiPython Notebookシェル・インタフェースのサポートが提供されています。
iPython Notebookは、プロパティ・グラフに基づいてワークフローまたはデモを構築するのに便利なツールです。このトピックでは、iPython Notebookベースのプロパティ・グラフ・ワークフローに視覚化を追加する方法について説明します。
iPython Notebookのインストール手順は、インストール・ホーム(デフォルトでは/opt/oracle/oracle-spatial-graph
)の下にある/property_graph/examples/pyopg/README
ファイルにあります。
iPython Notebookをインストールしたら、コード・スニペットをiPythonノートブックにコピーおよび貼付けできます。
開始するには次の手順に従います。
必要なライブラリをいくつか選択してインポートします。次に例を示します。
import matplotlib as mpl import matplotlib.pyplot as plt import sys default_stdout = sys.stdout default_stderr = sys.stderr reload(sys) sys.setdefaultencoding("utf-8") sys.stdout = default_stdout sys.stderr = default_stderr from pyopg.core import * pgx_config = JPackage('oracle.pgx.config') pgx_types = JPackage('oracle.pgx.common.types') pgx_control = JPackage('oracle.pgx.api') hbase = JPackage('oracle.pg.hbase')
グラフ構成を作成します。次に例を示します。
graph_builder = pgx_config.GraphConfigBuilder.forPropertyGraphHbase() \ .setName("my_graph").setZkQuorum("hostname1").setZkClientPort(2181) \ .setZkSessionTimeout(120000).setInitialEdgeNumRegions(3) \ .setInitialVertexNumRegions(3).setSplitsPerRegion(1) graph_builder.addEdgeProperty("weight", pgx_types.PropertyType.DOUBLE, "1000000")
グラフをインメモリー・アナリストに読み込みます。次に例を示します。
opg = hbase.OraclePropertyGraph.getInstance(graph_builder.build()) pgx_param = JClass("java.util.HashMap")() instance = JClass("oracle.pgx.api.Pgx").getInstance() if not instance.isEngineRunning():instance.startEngine(pgx_param) session = instance.createSession("my_recommender_session1") analyst = session.createAnalyst() pgxGraph = session.readGraphWithProperties(opg.getConfig(), True) pgxGraph.getNumEdges()
(オプション)いくつかの頂点を読み出します。次に例を示します。
for element in range(1,10,1): vertex = opg.getVertex(element) print 'Vertex ID: ' + str(element) + ' - Name: ' + vertex.getProperty("name") #Vertex ID: 1 - Name: Barack Obama #Vertex ID: 2 - Name: Beyonce #...
視覚化するエッジ(および頂点)からJSONオブジェクト(ノード、リンク)を作成します。次に例を示します。
# Get Edges edges = opg.getEdges().iterator(); edge = edges.next() # Dictiony for Nodes and Links nodes = [] links = [] names = [] sources = [] targets = [] values = [] # Get Nodes for count in range(1,20,1): # Vertex Values outVertexName = edge.getOutVertex().getProperty("name") outVertexRole = edge.getOutVertex().getProperty("country") inVertexName = edge.getInVertex().getProperty("name") inVertexRole = edge.getInVertex().getProperty("country") # Add out Vertex if {"name": outVertexName, "group": outVertexRole} not in nodes: nodes.append({"name": outVertexName, "group": outVertexRole}) names.append(outVertexName) # Add in Vertex if {"name": inVertexName, "group": inVertexRole} not in nodes: nodes.append({"name": inVertexName, "group": inVertexRole}) names.append(inVertexName) # Edge Information sources.append(outVertexName) targets.append(inVertexName) values.append(edge.getLabel()) # Next Edge edge = edges.next() # Get Links for count in range(0,19,1): # Vertex Values outVertexName = sources[count] inVertexName = targets[count] # Edge Values source = names.index(outVertexName) target = names.index(inVertexName) value = values[count] links.append({"source": source, "target": target, "value": value})
from IPython.display import Javascript import json # Transform the graph into a JSON graph data = {"nodes":nodes, "links":links} jsonGraph = json.dumps(data, indent=4) # Send to Javascript Javascript("""window.jsonGraph={};""".format(jsonGraph))
グラフ描画用の<div>...</div>を設定します。次に例を示します。
%%html <div id="d3-example"></div> <style> .node {stroke: #fff; stroke-width: 1.5px;} .link {stroke: #999; stroke-opacity: 5.6;} </style>
D3力指向レイアウトでグラフ処理を実行します。次に例を示します。
%%javascript // We load the d3.js library from the Web. require.config({paths: {d3: "http://d3js.org/d3.v3.min"}}); require(["d3"], function(d3) { // The code in this block is executed when the // d3.js library has been loaded. // First, we specify the size of the canvas containing // the visualization (size of the <div> element). var width = 800, height = 600; // We create a color scale. var color = d3.scale.category20(); // We create a force-directed dynamic graph layout. var force = d3.layout.force().charge(-300).linkDistance(100).size([width, height]); // In the <div> element, we create a <svg> graphic // that will contain our interactive visualization. var svg = d3.select("#d3-example").select("svg") if (svg.empty()) { svg = d3.select("#d3-example").append("svg").attr("width", width).attr("height", height); } // We load the JSON graph we generated from iPython input var graph = window.jsonGraph; plotGraph(graph); // Graph Plot function function plotGraph(graph) { // We load the nodes and links in the force-directed graph. force.nodes(graph.nodes).links(graph.links).start(); // We create a <line> SVG element for each link in the graph. var link = svg.selectAll(".link").data(graph.links).enter().append("line").attr("class", "link").attr("stroke-width", 7); // Link Value link.append("title").text(function(d) { return d.value; }); // We create a <circle> SVG element for each node // in the graph, and we specify a few attributes. var node = svg.selectAll(".node").data(graph.nodes).enter().append("circle").attr("class", "node").attr("r", 16) //radius .style("fill", function(d) { // The node color depends on the club. return color(d.group); }).call(force.drag); // The name of each node is the node number. node.append("title").text(function(d) { var info = "Name: " + d.name + "\n" + "Country: " + d.group; return info; }); // Text Over Nodes var text = svg.append("g").selectAll("text").data(force.nodes()).enter().append("text").attr("x", function(d) { return -10 }).attr("y", 0).style("font-size","10px").text(function(d) { if (d.name.length > 15) { return d.name.substring(0, 15) + "..."; } return d.name; }); // We bind the positions of the SVG elements // to the positions of the dynamic force-directed graph, // at each time step. force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }).attr("y1", function(d) { return d.source.y; }).attr("x2", function(d) { return d.target.x; }).attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; }); text.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); }); } });
前述のすべての手順を実行した場合、次のようなイメージがHTML領域に表示されます。