17.2 グラフ・サーバー(PGX)への接続

このセクションでは、リモート・モードで実行されているか、WebアプリケーションとしてApache TomcatまたはOracle WebLogic Serverにデプロイされているグラフ・サーバー(PGX)に接続する方法について説明します。

グラフ・サーバーに接続するための前提条件として、グラフ・サーバー(PGX)を起動および実行する必要があります。グラフ・サーバーを起動するコマンドの詳細は、コマンドラインを使用したグラフ・サーバー(PGX)の起動と停止を参照してください。

ノート:

グラフ・サーバー(PGX)をライブラリとして使用している場合は、ライブラリとしてのグラフ・サーバー(PGX)の使用を参照してください。

17.2.1 グラフ・クライアントCLIによる接続

リモート・グラフ・サーバー(PGX)インスタンスに接続する最も簡単な方法は、次のように、サーバーのベースURLをグラフ・サーバー(PGX)認証に必要なデータベース・ユーザー名とともに指定することです。

cd /opt/oracle/graph
./bin/opg4j --base_url https://<host>:<port> --username <graphuser>
cd /opt/oracle/graph
./bin/opg4py --base_url https://<host>:<port> --username <graphuser>
説明:
  • <host>: サーバー・ホスト名
  • <port>: サーバー・ポート
  • <graphuser>: データベース・ユーザー

    データベース・パスワードの入力を要求されます。

関連項目:

HTTPリクエストのロギングについて

グラフ・シェルでは、デフォルトでデバッグ・メッセージがすべて非表示になります。どのHTTPリクエストが実行されたかを確認するには、この例に示すように、oracle.pgxのログ・レベルをDEBUGに設定します。

ノート:

これらのログを有効にすると、パスワードなどの機密情報が画面に出力されます。
opg4j> loglevel("oracle.pgx","DEBUG")
===> Log level of oracle.pgx logger set to DEBUG
opg4j> var g = session.readGraphByName("BANK_GRAPH_PGQL", GraphSource.PG_PGQL)
10:29:11,832+0000 DEBUG o.p.c.RemoteUtils - create session cookie (session ID = 3848d346-0372-44df-9050-bd24dfb8f8fd)
10:29:11,836+0000 DEBUG o.p.c.RemoteUtils - no value for the sticky cookie given
10:29:11,836+0000 DEBUG o.p.c.RemoteUtils - create csrf token cookie (token = c4669906-59bd-4289-96bc-299926e4aab9)
10:29:11,886+0000 DEBUG o.p.c.HttpRequestExecutor - Requesting POST https://localhost:7007/core/v3/describe
10:29:11,937+0000 DEBUG o.p.c.HttpRequestExecutor - received HTTP status 202
10:29:11,938+0000 DEBUG o.p.c.HttpRequestExecutor - {"futureId":"c5aedabb-40c2-49bf-810f-90eaa2983dd8"}
10:29:11,945+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/status
10:29:12,349+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/value
10:29:12,358+0000 DEBUG o.p.c.RemoteUtils - received HTTP status 201
10:29:12,358+0000 DEBUG o.p.c.RemoteUtils - {"error_handling":{"on_missing_vertex":"ERROR"},"loading":{"snapshots_source":"CHANGE_SET"},"vertex_id_strategy":"PARTITIONED_IDS","vertex_id_type":"string","vertex_providers":[{"label":"ACCOUNTS","loading":{"create_key_mapping":true},"parallel_hint_degree":-1,"key_column":"ID","props":[{"column":"ID","name":"ID","type":"long","dimension":0},{"column":"NAME","name":"NAME","type":"string","dimension":0}],"format":"rdbms","database_table_name":"BANK_ACCOUNTS","attributes":{},"schema":"GRAPHUSER","key_type":"long","name":"ACCOUNTS","error_handling":{}}],"source_type":"PG_PGQL","edge_providers":[{"label":"TRANSFERS","loading":{"create_key_mapping":true},"parallel_hint_degree":-1,"key_column":"TXN_ID","props":[{"column":"SRC_ACCT_ID","name":"SRC_ACCT_ID","type":"long","dimension":0},{"column":"DST_ACCT_ID","name":"DST_ACCT_ID","type":"long","dimension":0},{"column":"AMOUNT","name":"AMOUNT","type":"double","dimension":0},{"column":"DESCRIPTION","name":"DESCRIPTION","type":"string","dimension":0}],"format":"rdbms","database_table_name":"BANK_TRANSFERS","source_column":"SRC_ACCT_ID","attributes":{},"schema":"GRAPHUSER","key_type":"long","destination_column":"DST_ACCT_ID","name":"TRANSFERS","error_handling":{},"source_vertex_provider":"ACCOUNTS","destination_vertex_provider":"ACCOUNTS"}],"attributes":{},"name":"BANK_GRAPH_PGQL","edge_id_type":"string","source_name":"BANK_GRAPH_PGQL","edge_id_strategy":"PARTITIONED_IDS","num_connections":64,"optimized_for":"UPDATES","schema":"GRAPHUSER"}
10:29:12,561+0000 DEBUG o.p.c.RemoteUtils - create session cookie (session ID = 3848d346-0372-44df-9050-bd24dfb8f8fd)
10:29:12,566+0000 DEBUG o.p.c.RemoteUtils - no value for the sticky cookie given
10:29:12,568+0000 DEBUG o.p.c.RemoteUtils - create csrf token cookie (token = c4669906-59bd-4289-96bc-299926e4aab9)
10:29:12,677+0000 DEBUG o.p.c.HttpRequestExecutor - Requesting POST https://localhost:7007/core/v2/loadGraph
10:29:12,723+0000 DEBUG o.p.c.HttpRequestExecutor - received HTTP status 202
10:29:12,723+0000 DEBUG o.p.c.HttpRequestExecutor - {"futureId":"642709b7-dfdc-4973-885d-38e1e468b4e8"}
10:29:12,733+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/status
10:29:14,873+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/value
10:29:14,890+0000 DEBUG o.p.c.RemoteUtils - received HTTP status 201
10:29:14,892+0000 DEBUG o.p.c.RemoteUtils - {"id":"C0B94E89-BD4E-4A26-9573-B05193BE0CE1","links":[{"href":"core/v1/graphs/x-graph-id","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id","rel":"canonical","method":"GET","interaction":["async-polling"]}],"graphName":"BANK_GRAPH_PGQL","vertexTables":{"ACCOUNTS":{"name":"ACCOUNTS","metaData":{"name":"ACCOUNTS","labels":["ACCOUNTS"],"properties":[{"name":"ID","id":null,"propertyType":"long","dimension":0,"transient":true,"links":null,"propertyId":"0BB854DF-CAC5-440E-B2CB-705665959B83"},{"name":"NAME","id":null,"propertyType":"string","dimension":0,"transient":true,"links":null,"propertyId":"A523DDE1-0D1B-499C-AA1E-16BD5FDF39B0"}],"edgeProviderNamesWhereSource":["TRANSFERS"],"edgeProviderNamesWhereDestination":["TRANSFERS"],"id":null,"links":null,"keyColumns":[{"name":"ID","type":"long"}]},"providerLabels":["ACCOUNTS"],"keyPropertyName":"ID","entityKeyType":"long","isIdentityKeyMapping":false,"vertexLabels":{"id":"A73520D5-ACD6-46D1-A4F8-642BC18D781A","links":[{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":-1,"propertyId":"A73520D5-ACD6-46D1-A4F8-642BC18D781A","name":"__vertex_labels__","entityType":"vertex","type":"ro_string_set","namespace":"2C17C639-3771-3E30-88AE-34D6B380C5EC","transient":false},"vertexProperties":{"CEA03F3F-E070-4E56-838D-4262CB2AE7C7":{"id":"CEA03F3F-E070-4E56-838D-4262CB2AE7C7","links":[{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"propertyId":"CEA03F3F-E070-4E56-838D-4262CB2AE7C7","name":"ID","entityType":"vertex","type":"long","namespace":"2C17C639-3771-3E30-88AE-34D6B380C5EC","transient":false},"F14428F3-83EF-416C-A6ED-5674FD622F32":{"id":"F14428F3-83EF-416C-A6ED-5674FD622F32","links":[{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"propertyId":"F14428F3-83EF-416C-A6ED-5674FD622F32","name":"NAME","entityType":"vertex","type":"string",
10:29:15,021+0000 DEBUG o.p.a.i.LoadingUtils - ==> change sets as snapshot source. Returning graph loaded by the engine
g ==> PgxGraph[name=BANK_GRAPH_PGQL,N=1000,E=4996,created=1752056953946]
>>>setloglevel("oracle.pgx","DEBUG")
>>> graph = session.read_graph_by_name('BANK_GRAPH_PGQL', 'pg_pgql')
10:31:46,774+0000 DEBUG o.p.c.RemoteUtils - create session cookie (session ID = 7ed17ed7-eaa8-405b-94d0-37e8ad31d2b7)
10:31:46,780+0000 DEBUG o.p.c.RemoteUtils - no value for the sticky cookie given
10:31:46,780+0000 DEBUG o.p.c.RemoteUtils - create csrf token cookie (token = e527ec88-631f-4d51-bdd6-72628c6b69c5)
10:31:46,827+0000 DEBUG o.p.c.HttpRequestExecutor - Requesting POST https://localhost:7007/core/v3/describe
10:31:46,877+0000 DEBUG o.p.c.HttpRequestExecutor - received HTTP status 202
10:31:46,879+0000 DEBUG o.p.c.HttpRequestExecutor - {"futureId":"86faf1ee-8fcd-4d92-aa98-a5e832c55e58"}
10:31:46,883+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/status
10:31:46,930+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/value
10:31:46,944+0000 DEBUG o.p.c.RemoteUtils - received HTTP status 201
10:31:46,945+0000 DEBUG o.p.c.RemoteUtils - {"error_handling":{"on_missing_vertex":"ERROR"},"loading":{"snapshots_source":"CHANGE_SET"},"vertex_id_strategy":"PARTITIONED_IDS","vertex_id_type":"string","vertex_providers":[{"label":"ACCOUNTS","loading":{"create_key_mapping":true},"parallel_hint_degree":-1,"key_column":"ID","props":[{"column":"ID","name":"ID","type":"long","dimension":0},{"column":"NAME","name":"NAME","type":"string","dimension":0}],"format":"rdbms","database_table_name":"BANK_ACCOUNTS","attributes":{},"schema":"GRAPHUSER","key_type":"long","name":"ACCOUNTS","error_handling":{}}],"source_type":"PG_PGQL","edge_providers":[{"label":"TRANSFERS","loading":{"create_key_mapping":true},"parallel_hint_degree":-1,"key_column":"TXN_ID","props":[{"column":"SRC_ACCT_ID","name":"SRC_ACCT_ID","type":"long","dimension":0},{"column":"DST_ACCT_ID","name":"DST_ACCT_ID","type":"long","dimension":0},{"column":"AMOUNT","name":"AMOUNT","type":"double","dimension":0},{"column":"DESCRIPTION","name":"DESCRIPTION","type":"string","dimension":0}],"format":"rdbms","database_table_name":"BANK_TRANSFERS","source_column":"SRC_ACCT_ID","attributes":{},"schema":"GRAPHUSER","key_type":"long","destination_column":"DST_ACCT_ID","name":"TRANSFERS","error_handling":{},"source_vertex_provider":"ACCOUNTS","destination_vertex_provider":"ACCOUNTS"}],"attributes":{},"name":"BANK_GRAPH_PGQL","edge_id_type":"string","source_name":"BANK_GRAPH_PGQL","edge_id_strategy":"PARTITIONED_IDS","num_connections":64,"optimized_for":"UPDATES","schema":"GRAPHUSER"}
10:31:47,098+0000 DEBUG o.p.c.RemoteUtils - create session cookie (session ID = 7ed17ed7-eaa8-405b-94d0-37e8ad31d2b7)
10:31:47,099+0000 DEBUG o.p.c.RemoteUtils - no value for the sticky cookie given
10:31:47,100+0000 DEBUG o.p.c.RemoteUtils - create csrf token cookie (token = e527ec88-631f-4d51-bdd6-72628c6b69c5)
10:31:47,192+0000 DEBUG o.p.c.HttpRequestExecutor - Requesting POST https://localhost:7007/core/v2/loadGraph
10:31:47,212+0000 DEBUG o.p.c.HttpRequestExecutor - received HTTP status 202
10:31:47,213+0000 DEBUG o.p.c.HttpRequestExecutor - {"futureId":"cc045b69-d4dc-43a3-85fe-7ff4670c145e"}
10:31:47,216+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/status
10:31:48,381+0000 DEBUG o.p.c.PgxRemoteFuture - Requesting GET https://localhost:7007/core/v1/futures/x-future-id/value
10:31:48,403+0000 DEBUG o.p.c.RemoteUtils - received HTTP status 201
10:31:48,404+0000 DEBUG o.p.c.RemoteUtils - {"id":"732F212C-2A28-4619-A28B-6F39214F0BAB","links":[{"href":"core/v1/graphs/x-graph-id","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id","rel":"canonical","method":"GET","interaction":["async-polling"]}],"graphName":"BANK_GRAPH_PGQL","vertexTables":{"ACCOUNTS":{"name":"ACCOUNTS","metaData":{"name":"ACCOUNTS","labels":["ACCOUNTS"],"properties":[{"name":"ID","id":null,"propertyType":"long","dimension":0,"transient":true,"links":null,"propertyId":"9E85201E-9EF2-44FB-BF8B-E8CAE5EDF1A2"},{"name":"NAME","id":null,"propertyType":"string","dimension":0,"transient":true,"links":null,"propertyId":"23D72E74-9A61-42A6-9DE6-DFC995A2DAC6"}],"edgeProviderNamesWhereSource":["TRANSFERS"],"edgeProviderNamesWhereDestination":["TRANSFERS"],"id":null,"links":null,"keyColumns":[{"name":"ID","type":"long"}]},"providerLabels":["ACCOUNTS"],"keyPropertyName":"ID","entityKeyType":"long","isIdentityKeyMapping":false,"vertexLabels":{"id":"B7409C30-0FD6-418C-B847-C31898BB2A00","links":[{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":-1,"propertyId":"B7409C30-0FD6-418C-B847-C31898BB2A00","name":"__vertex_labels__","entityType":"vertex","type":"ro_string_set","namespace":"2C17C639-3771-3E30-88AE-34D6B380C5EC","transient":false},"vertexProperties":{"8C73E3E3-AB9A-41F8-BBD4-F8B53192809D":{"id":"8C73E3E3-AB9A-41F8-BBD4-F8B53192809D","links":[{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"propertyId":"8C73E3E3-AB9A-41F8-BBD4-F8B53192809D","name":"ID","entityType":"vertex","type":"long","namespace":"2C17C639-3771-3E30-88AE-34D6B380C5EC","transient":false},"3075BCCB-4A4B-4F1E-B7DD-A5BDEA491D75":{"id":"3075BCCB-4A4B-4F1E-B7DD-A5BDEA491D75","links":[{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"core/v1/graphs/x-graph-id/properties/x-property-name","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"propertyId":"3075BCCB-4A4B-4F1E-B7DD-A5BDEA491D75","name":"NAME","entityType":"vertex","type":"string",
10:31:48,516+0000 DEBUG o.p.a.i.LoadingUtils - ==> change sets as snapshot source. Returning graph loaded by the engine

17.2.2 Javaによる接続

リモート・グラフ・サーバー(PGX)インスタンスへの接続を取得するには、単にリモートPGXインスタンスのベースURLをgetInstance()メソッドに渡します。これにより、アプリケーションは自動的にPGXクライアント・ライブラリを使用してリモートに配置されたグラフ・サーバー(PGX)に接続します。

Javaを使用してグラフ・サーバー(PGX)インスタンスを初期化する場合、ベースURLを指定できます。この例は次のようになります。グラフ・サーバー(PGX)へのURLがgetInMemAnalyst APIコールに提供されます。

import oracle.pgx.api.*;
import oracle.pg.rdbms.*;
ServerInstance instance = GraphServer.getInstance("https://<hostname>:<port>","<username>","<password>".toCharArray());
PgxSession session = instance.createSession("my-session");

ノート:

Java APIの詳細は、Java APIリファレンスを参照してください。

17.2.2.1 PGXエンジンの起動と停止

アプリケーションからグラフ・サーバー(PGX)を起動するには、PGX構成の引数としてJSONオブジェクトを使用するinstance.startEngine()をコールします。

ノート:

PGXエンジンの停止

次のいずれかのAPIを使用して、PGXエンジンを停止できます。

instance.shutdownEngineNow(); // cancels pending tasks, throws exception if engine is not running
instance.shutdownEngineNowIfRunning(); // cancels pending tasks, only tries to shut down if engine is running
if (instance.shutdownEngine(30, TimeUnit.SECONDS) == false) { 
  // doesn't accept new tasks but finishes up remaining tasks
  // pending tasks didn't finish after 30 seconds
}

ノート:

PGXエンジンをシャットダウンすると、Apache Tomcatサーバーは存続しますが、新しいセッションは作成できません。また、現在のすべてのセッションおよびタスクが取り消され、終了します。

17.2.3 Pythonによる接続

Pythonプログラムでリモート・グラフ・サーバー(PGX)インスタンスに接続できます。次の例に示すように、セッションを作成するには、まずリモート・サーバーで認証する必要があります。

import pypgx
import opg4py
import opg4py.graph_server as graph_server
pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "<jdbc_url>")
pgql_statement = pgql_conn.create_statement()
pgql = """
        CREATE PROPERTY GRAPH bank_graph
        VERTEX TABLES (
          bank_accounts
            LABEL ACCOUNTS
            PROPERTIES (ID, NAME)
        )
        EDGE TABLES (
          bank_txns
            SOURCE KEY (SRC_ACCT_ID) REFERENCES bank_accounts (ID)
            DESTINATION KEY (DST_ACCT_ID) REFERENCES bank_accounts (ID)
            LABEL TRANSFERS
            PROPERTIES (SRC_ACCT_ID, DST_ACCT_ID, AMOUNT, DESCRIPTION)
        ) OPTIONS(PG_PGQL)
"""
pgql_statement.execute(pgql)
instance = graph_server.get_instance("<base_url>", "<username>", "<password>")
session = instance.create_session("my_session")
graph = session.read_graph_by_name('BANK_GRAPH', 'pg_pgql')
analyst = session.create_analyst()
analyst.pagerank(graph)
rs = graph.query_pgql("SELECT id(x), x.pagerank FROM MATCH (x) LIMIT 5")
rs.print()

実行するには、前述のプログラムをprogram.pyという名前のファイルに保存し、次のコマンドを実行します。

python3 program.py

次の出力が表示されます。

+-------------------------------------------+
| id(x)             | pagerank              |
+-------------------------------------------+
| BANK_ACCOUNTS(2)  | 9.749447313256548E-4  |
| BANK_ACCOUNTS(4)  | 0.004584001759076056  |
| BANK_ACCOUNTS(6)  | 5.358461393401424E-4  |
| BANK_ACCOUNTS(8)  | 0.0013051552434930175 |
| BANK_ACCOUNTS(10) | 0.0015040122009364232 |
+-------------------------------------------+

PGQL結果セットからPandasデータフレームへの変換

さらに、to_pandas()メソッドを使用して、PGQL結果セットをpandas.DataFrameオブジェクトに変換することもできます。これによって、結果セットに対して様々なデータ・フィルタリング操作をより簡単に実行できるようになるとともに、それをラムダ関数で使用することもできます。たとえば、
example_query = (
    "SELECT n.name AS name, n.age AS age "
    "WHERE (n)"
)
result_set = sample_graph.query_pgql(example_query)
result_df = result_set.to_pandas()

result_df['age_bin'] = result_df['age'].apply(lambda x: int(x)/20) # create age bins based on age ranges

ノート:

使用可能なPython APIの完全なセットを確認するには、OPG4PY Python API リファレンスを参照してください。