9 プロパティ・グラフ・ビューを使用するためのクイック・スタート

この章では、プロパティ・グラフ・ビューの操作を開始する際に役立つクイック・スタート・チュートリアルおよびその他のリソースについて説明します。

9.1 グラフ分析のサンプルデータの使用

グラフ・サーバーのrpmインストールでは、/opt/oracle/graph/dataディレクトリにサンプル・グラフ・データが提供されます。

bank_graphフォルダには、bank_nodes.csvファイルおよびbank_edges_amt.csvファイル内のグラフの頂点とエッジを表すデータがそれぞれ格納されます。これらの.csvファイルからデータベースにグラフ・データをインポートできます。その後、問合せおよび分析用のグラフを作成できます。

9.1.1 CSVファイルからのデータのインポート

Oracle SQL DeveloperまたはOracle Databaseユーティリティ(SQL*Loaderや外部表など)を使用して、CSVファイルのデータをデータベースにインポートできます。

次に、Oracle SQL Loaderを使用してデータをデータベース表にロードする手順を示します。

前提条件として、次のSQL文を実行して、データベースで頂点(bank_accounts)表およびエッジ(bank_txns)表を作成する必要があります。
CREATE TABLE bank_accounts(id NUMBER, name VARCHAR2(10));
CREATE TABLE bank_txns(from_acct_id NUMBER, to_acct_id NUMBER, description VARCHAR2(10), amount NUMBER);

次に、次のステップを実行してデータをロードします。

  1. 次に示すように、bank_nodes.csvから頂点をロードするSQL*Loader制御ファイルを作成します。
    load data
    infile '<path_to_bank_nodes.csv>'
    into table bank_accounts
    fields terminated by "," optionally enclosed by '"'
    ( id, name )
  2. 次に示すように、コマンドラインからSQL*Loaderを起動して、前述の構成ファイルを使用してbank_accounts表の頂点をロードします。
    sqlldr <dbuser>/<password> CONTROL=<path_to_vertex_loader.ctl>

    bank_accounts表に1000行が正常にロードされました。

  3. 次に示すように、bank_edges_amt.csvからエッジをロードするSQL*Loader制御ファイルを作成します。
    load data
    infile '<path_to_bank_edges_amt.csv>'
    into table bank_txns
    fields terminated by "," optionally enclosed by '"'
    (from_acct_id,to_acct_id,description,amount)
  4. 次に示すように、コマンドラインからSQL*Loaderを起動して、前述の構成ファイルを使用してbank_txns表のエッジをロードします。
    sqlldr <dbuser>/<password> CONTROL=<path_to_edge_loader.ctl>

    bank_txns表に4996行が正常にロードされました。

  5. 次のSQL文を実行して、bank_accounts表に主キー制約を追加します。
    ALTER TABLE bank_accounts ADD PRIMARY KEY (id);
  6. 次のSQL文を実行して、主キー列をbank_txns表に追加し、ROWNUM値を移入してから、主キー制約を定義します。
    ALTER TABLE bank_txns ADD txn_id NUMBER;
    UPDATE bank_txns SET txn_id = ROWNUM;
    COMMIT;
    ALTER TABLE bank_txns ADD PRIMARY KEY (txn_id);
  7. 次のSQL文を実行して、bank_txns表に外部キー制約を追加します。
    ALTER TABLE bank_txns MODIFY from_acct_id REFERENCES bank_accounts(id);
    ALTER TABLE bank_txns MODIFY to_acct_id REFERENCES bank_accounts(id);
    
サンプルの銀行グラフ・データがデータベース表で使用できるようになりました。

9.2 クイック・スタート: プロパティ・グラフ・ビューの操作

このチュートリアルは、プロパティ・グラフ・ビューでのグラフ・アルゴリズムの作成、問合せおよび実行を開始するのに役立ちます。

この手順では、グラフ・サーバーのインストールに付属しているサンプルの銀行グラフ・データをデータベース表にロードしたことを想定しています。詳細は、グラフ分析のサンプル・データの使用を参照してください。
次の手順は、OPG4J JavaシェルまたはOPG4PY Pythonシェルで実行することも、PGX APIを使用してJavaプログラムを通じて実行することもできる例でサポートされています。
  1. 対話型グラフ・シェルのCLIを起動します。
    cd /opt/oracle/graph
    ./bin/opg4j --no_connect
    Oracle Graph Server Shell 23.1.0
    cd /opt/oracle/graph
    ./bin/opg4py --no_connect
    Oracle Graph Server Shell 23.1.0
  2. OPG4JシェルまたはJavaプログラムを使用する場合は、JDBCデータベース接続を取得します。
    opg4j> var jdbcUrl="jdbc:oracle:thin:@<host>:<port>/<sid>"
    jdbcUrl ==> "jdbc:oracle:thin:@localhost:1521/orclpdb"
    opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>")
    conn ==> oracle.jdbc.driver.T4CConnection@7d463c9f
    opg4j> conn.setAutoCommit(false);
    import java.sql.DriverManager;
    import java.sql.Connection;
    import java.sql.Statement;
    import oracle.pg.rdbms.pgql.PgqlConnection;
    import oracle.pg.rdbms.pgql.PgqlStatement;
    import oracle.pg.rdbms.pgql.PgqlResultSet;
    import oracle.pgx.api.*;
    import oracle.pg.rdbms.GraphServer;
    import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
    …
    …
    // Get a jdbc connection
    DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
    String jdbcUrl="jdbc:oracle:thin:@"+<host>+":"+<port>+"/"+<sid>;
    conn = DriverManager.getConnection(jdbcUrl, <username>, <password>);
    conn.setAutoCommit(false);
  3. PGQL接続を作成します。
    opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
    pgqlConn ==> oracle.pg.rdbms.pgql.PgqlConnection@5c5c784c
    PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
    >>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "jdbc:oracle:thin:@<host>:<port>/<sid>")
  4. PGQL問合せを実行するためのPGQL文を作成します。
    opg4j> var pgqlStmt = pgqlConn.createStatement()
    pgqlStmt ==> oracle.pg.rdbms.pgql.PgqlExecution@29e3c28
    PgqlStatement pgqlStmt = pgqlConn.createStatement();
    >>> pgql_statement = pgql_conn.create_statement()
  5. CREATE PROPERTY GRAPH文を使用して、プロパティ・グラフ・ビューを作成します。
    opg4j> String pgql =
    ...> "CREATE PROPERTY GRAPH bank_graph_view "
    ...> + "VERTEX TABLES ( BANK_ACCOUNTS AS ACCOUNTS "
    ...> + "KEY (ID) "
    ...> + "LABEL ACCOUNTS "
    ...> + "PROPERTIES (ID, NAME) "
    ...> + ") "
    ...> + "EDGE TABLES ( BANK_TXNS AS TRANSFERS "
    ...> + "KEY (FROM_ACCT_ID, TO_ACCT_ID, AMOUNT) "
    ...> + "SOURCE KEY (FROM_ACCT_ID) REFERENCES ACCOUNTS (ID) "
    ...> + "DESTINATION KEY (TO_ACCT_ID) REFERENCES ACCOUNTS (ID) "
    ...> + "LABEL TRANSFERS "
    ...> + "PROPERTIES (FROM_ACCT_ID, TO_ACCT_ID, AMOUNT, DESCRIPTION) "
    ...> + ") OPTIONS (PG_VIEW) "
    opg4j> pgqlStmt.execute(pgql)
    String pgql = 
            "CREATE PROPERTY GRAPH " + graph + " " +
            "VERTEX TABLES ( BANK_ACCOUNTS AS ACCOUNTS " +
            "KEY (ID) " +
            "LABEL ACCOUNTS " +
            "PROPERTIES (ID, NAME)" +
            ") " +
            "EDGE TABLES ( BANK_TXNS AS TRANSFERS " +
            "KEY (FROM_ACCT_ID, TO_ACCT_ID, AMOUNT) " +
            "SOURCE KEY (FROM_ACCT_ID) REFERENCES ACCOUNTS (ID) " +
            "DESTINATION KEY (TO_ACCT_ID) REFERENCES ACCOUNTS (ID) " +
            "LABEL TRANSFERS " +
            "PROPERTIES (FROM_ACCT_ID, TO_ACCT_ID, AMOUNT, DESCRIPTION)" +
            ") OPTIONS(PG_VIEW)";
    
          pgqlStmt.execute(pgql);
    >>> pgql = """
    ...         CREATE PROPERTY GRAPH bank_graph_view
    ...         VERTEX TABLES (
    ...           BANK_ACCOUNTS
    ...           LABEL ACCOUNTS
    ...           PROPERTIES (ID, NAME)
    ...         )
    ...         EDGE TABLES (
    ...           BANK_TXNS
    ...             SOURCE KEY (FROM_ACCT_ID) REFERENCES BANK_ACCOUNTS (ID)
    ...             DESTINATION KEY (TO_ACCT_ID) REFERENCES BANK_ACCOUNTS (ID)
    ...             LABEL TRANSFERS
    ...             PROPERTIES (FROM_ACCT_ID, TO_ACCT_ID, AMOUNT, DESCRIPTION)
    ...         ) OPTIONS(PG_VIEW)
    ... """
    >>> pgql_statement.execute(pgql)
    False
    プロパティ・グラフ・ビューbank_graph_viewが正常に作成されます。
  6. 次の問合せを実行して、次のように、グラフの最初の10要素を取得します。
    opg4j> String pgqlQuery =
    ...> "SELECT e.from_acct_id, e.to_acct_id, e.amount FROM "
    ...> + "MATCH (n:ACCOUNTS) -[e:TRANSFERS]-> (m:ACCOUNTS) ON BANK_GRAPH_VIEW "
    ...> + "LIMIT 10"
    opg4j> var rs = pgqlStmt.executeQuery(pgqlQuery)
    rs ==> oracle.pg.rdbms.pgql.pgview.PgViewResultSet@1e368085
    opg4j> rs.print()
    +------------------------------------+
    | FROM_ACCT_ID | TO_ACCT_ID | AMOUNT |
    +------------------------------------+
    | 121          | 94         | 1000   |
    | 121          | 255        | 1000   |
    | 121          | 221        | 1000   |
    | 122          | 27         | 1000   |
    | 122          | 606        | 1000   |
    | 122          | 495        | 1000   |
    | 122          | 640        | 1000   |
    | 122          | 140        | 1000   |
    | 123          | 95         | 1000   |
    | 123          | 130        | 1000   |
    +------------------------------------+
    $16 ==> oracle.pg.rdbms.pgql.pgview.PgViewResultSet@1e368085
    String pgqlQuery = 
            "SELECT e.from_acct_id, e.to_acct_id, e.amount FROM " +
            "MATCH (n:ACCOUNTS) -[e:TRANSFERS]-> (m:ACCOUNTS) ON BANK_GRAPH_VIEW " +
            "LIMIT 10";
    PgqlResultSet rs = pgqlStmt.executeQuery(pgqlQuery);
    rs.print();
    >>> pgql = """
    ... SELECT e.from_acct_id, e.to_acct_id, e.amount FROM
    ... MATCH (n:ACCOUNTS) -[e:TRANSFERS]-> (m:ACCOUNTS) on BANK_GRAPH_VIEW
    ... limit 10
    ... """
    >>> pgql_statement.execute_query(pgql).print()
    +------------------------------------+
    | FROM_ACCT_ID | TO_ACCT_ID | AMOUNT |
    +------------------------------------+
    | 121          | 94         | 1000   |
    | 121          | 255        | 1000   |
    | 121          | 221        | 1000   |
    | 122          | 27         | 1000   |
    | 122          | 606        | 1000   |
    | 122          | 495        | 1000   |
    | 122          | 640        | 1000   |
    | 122          | 140        | 1000   |
    | 123          | 95         | 1000   |
    | 123          | 130        | 1000   |
    +------------------------------------+
  7. グラフをグラフ・サーバー(PGX)にロードします。これにより、様々な種類の組込みアルゴリズムをグラフで実行できるようになり、より大きなグラフの問合せパフォーマンスも改善されます。
    opg4j> var instance = GraphServer.getInstance("https://localhost:7007", "<username>", "<password>".toCharArray())
    instance ==> ServerInstance[embedded=false,baseUrl=https://localhost:7007]
    opg4j> var session = instance.createSession("mySession")
    session ==> PgxSession[ID=43653128-59cd-4e69-992c-1a2beac05857,source=mySession]
    opg4j> var graph = session.readGraphByName("BANK_GRAPH_VIEW",GraphSource.PG_VIEW)
    graph ==> PgxGraph[name=BANK_GRAPH_VIEW,N=1000,E=4996,created=1643308582055]
    ServerInstance instance = GraphServer.getInstance("https://localhost:7007", "<username>", "<password>".toCharArray());
    PgxSession session = instance.createSession("my-session");
    PgxGraph graph = session.readGraphByName("BANK_GRAPH_VIEW",GraphSource.PG_VIEW);
    >>> instance = graph_server.get_instance("https://localhost:7007","<username>","<password>")
    >>> session = instance.create_session("my_session")
    >>> graph = session.read_graph_by_name('BANK_GRAPH_VIEW', 'pg_view')
    >>> graph
    PgxGraph(name: BG_PY_VIEW, v: 1000, e: 4996, directed: True, memory(Mb): 0)
  8. 次のように、PageRankアルゴリズムを実行します。
    opg4j> var analyst = session.createAnalyst()
    analyst ==> NamedArgumentAnalyst[session=3f0a9a71-f349-4aac-b75f-a7c4ae50851b]
    opg4j> analyst.pagerank(graph)
    $10 ==> VertexProperty[name=pagerank,type=double,graph=BANK_GRAPH_VIEW]
    Analyst analyst = session.createAnalyst();
    analyst.pagerank(graphView);
    >>> analyst = session.create_analyst()
    >>> analyst.pagerank(graph)
    VertexProperty(name: pagerank, type: double, graph: BANK_GRAPH_VIEW)
  9. グラフを問い合せて、ページ・ランク別に上位10件のアカウントをリストします。
    opg4j> String pgql ==> "SELECT a.id, a.pagerank FROM MATCH (a) ON BANK_GRAPH_VIEW ORDER BY a.pagerank DESC LIMIT 10"
    opg4j> session.queryPgql(pgql).print()
    +-----------------------------+
    | id  | pagerank              |
    +-----------------------------+
    | 387 | 0.007292323575404966  |
    | 406 | 0.0067300944623203615 |
    | 135 | 0.0067205459831892545 |
    | 934 | 0.00663484385036358   |
    | 397 | 0.005693569761570973  |
    | 559 | 0.0052584383114609844 |
    | 352 | 0.005216329599236731  |
    | 330 | 0.005093350408942336  |
    | 222 | 0.004682551613749817  |
    | 4   | 0.004569682370461633  |
    +-----------------------------+
    $18 ==> PgqlResultSetImpl[graph=BANK_GRAPH_VIEW,numResults=10]
    
    String pgQuery = "SELECT a.id, a.pagerank FROM MATCH (a) ON BANK_GRAPH_VIEW ORDER BY a.pagerank DESC LIMIT 10";
    session.queryPgql(pgQuery).print();
    >>> pgql = "SELECT a.id, a.pagerank FROM MATCH (a) ON BANK_GRAPH_VIEW ORDER BY a.pagerank DESC LIMIT 10"
    >>> session.query_pgql(pgql).print()
    +-----------------------------+
    | id  | pagerank              |
    +-----------------------------+
    | 387 | 0.007292323575404966  |
    | 406 | 0.0067300944623203615 |
    | 135 | 0.0067205459831892545 |
    | 934 | 0.00663484385036358   |
    | 397 | 0.005693569761570973  |
    | 559 | 0.0052584383114609844 |
    | 352 | 0.005216329599236731  |
    | 330 | 0.005093350408942336  |
    | 222 | 0.004682551613749817  |
    | 4   | 0.004569682370461633  |
    +-----------------------------+

9.3 クイック・スタート: Pythonクライアントをモジュールとして使用

このセクションでは、PythonクライアントをPythonアプリケーションでモジュールとして使用する方法について説明します。

リモート・サーバー

このモードで必要なのは、インストールするPythonクライアントのみです。Pythonプログラムでは、次の例に示すように、セッションを作成する前にリモート・サーバーで認証する必要があります。base_urljdbc_urlusernameおよびpasswordの値を、環境の詳細と一致する値で置き換える必要があることに注意してください。

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 (from_acct_id) REFERENCES bank_accounts
            DESTINATION KEY (to_acct_id) REFERENCES bank_accounts
            LABEL TRANSFERS
            PROPERTIES (FROM_ACCT_ID, TO_ACCT_ID, AMOUNT, DESCRIPTION)
        ) OPTIONS(PG_VIEW)
"""
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_view')
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 リファレンスを参照してください。

組込みサーバー

このモードでは、PythonクライアントとGraph Server RPMパッケージを同じマシンにインストールする必要があります。

import os
os.environ["PGX_CLASSPATH"] = "/opt/oracle/graph/lib/*"
instance = graph_server.get_embedded_instance()
session = instance.create_session("python_pgx_client")
print(session)

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

python3 program.py

ログインに成功すると、PGXセッションが作成されたことを示す次のようなメッセージが表示されます:

PgxSession(id: 32fc7037-18f1-4381-ba94-107e5f63aec2, name: python_pgx_client)

ノート:

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

9.4 グラフに関するOracle LiveLabsワークショップ

Oracle LiveLabsのグラフ・ワークショップを使用して、Oracleプロパティ・グラフの機能を探索することもできます。

無償枠のAutonomous Databaseインスタンスに格納されているデータを使用したグラフの問合せ、分析および視覚化に関する完全な例は、Oracle Livelabsワークショップを参照してください。新しい無償枠のAutonomous Databaseインスタンスをプロビジョニングし、そこにデータをロードして、グラフを作成した後、グラフの問合せ、分析および視覚化を行います。