8 グラフ・サーバー(PGX)へのPGビューのロード

プロパティ・グラフ・ビュー(PGビュー)をグラフ・サーバー(PGX)にロードするには、いくつかの方法があります。

8.1 readGraphByName APIを使用したPGビューのロード

プロパティ・グラフ・ビュー(PGビュー)からグラフ・サーバー(PGX)にグラフを名前でロードできます。

PgxSession#readGraphByName APIを使用して、PGビューからグラフをロードできます。

readGraphByName(String schemaName, String graphName, GraphSource source, ReadGraphOption options)

次の表に、メソッドで使用される引数を示します:

表8-1 readGraphByNameメソッドのパラメータ

パラメータ 説明 オプション
schemaName スキーマの所有者 はい
graphName PGビューの名前 いいえ
source グラフのソース形式(GraphSource.PG_VIEW) いいえ
options グラフ最適化オプションを表します はい

readGraphByName()メソッドは、PGビューのメタデータ表を読み取り、グラフをロードするためのグラフ構成を内部的に生成します。このAPIを使用するには、PGX_SESSION_NEW_GRAPH権限が必要です。

たとえば、次のように、プロパティ・グラフ・ビューからグラフをロードできます。

opg4j> var graph = session.readGraphByName("BANKDATAVIEW", GraphSource.PG_VIEW)
$12 ==> PgxGraph[name=bankdataview,N=1000,E=5001,created=1625730942294]
PgxGraph graph = session.readGraphByName("BANKDATAVIEW", GraphSource.PG_VIEW);
Graph: PgxGraph[name=bankdataview,N=1000,E=5001,created=1625732149262]
>>> graph = session.read_graph_by_name('BANKDATAVIEW', 'pg_view')
>>> graph
PgxGraph(name: bankdataview, v: 1000, e: 5001, directed: True, memory(Mb): 0)

8.1.1 readGraphByName APIのオプションの指定

readGraphByName APIを使用してプロパティ・グラフ・ビュー(PGビュー)をロードする場合は、グラフ最適化オプションまたはOnMissingVertexOption、あるいはその両方を指定できます。

PGビューを名前でロードする際、ReadGraphOptionインタフェースでは追加のoptionsパラメータがサポートされます。

次の各項では、ReadGraphOptionインタフェースでサポートされている様々なオプションについて説明します。

グラフ最適化オプションの使用

PGビューを名前でロードする際の読取りまたは更新のパフォーマンスを最適化するには、次のいずれかのoptionsを使用します。

  • ReadGraphOption.optimizeFor(GraphOptimizedFor.READ): ロードされるグラフをREAD用に最適化することを指定します。
  • ReadGraphOption.optimizeFor(GraphOptimizedFor.UPDATES): ロードされるグラフをUPDATE用に最適化することを指定します。
  • ReadGraphOption.synchronizable(): ロードされるグラフが同期できることを指定します。

次の点に注意してください。

  • synchronizable()オプションは、UPDATEおよびREADと組み合せて使用できます。ただし、UPDATEオプションとREADオプションは同時に使用できません。
  • SYNCHRONIZABLEオプションのPGビューをロードする場合は、頂点キーとエッジ・キーが数値であり、コンポジットではないことを確認します。

次の例では、READおよびSYNCHRONIZABLEオプションのPGビューをロードします:

opg4j> var graph = session.readGraphByName("BANK_GRAPH_VIEW", GraphSource.PG_VIEW,
...>                            ReadGraphOption.optimizeFor(GraphOptimizedFor.READ),
...>                            ReadGraphOption.synchronizable())
graph ==> PgxGraph[name=BANK_GRAPH_VIEW_2,N=1000,E=5001,created=1648457198462]
PgxGraph graph = session.readGraphByName("BANKDATAVIEW", GraphSource.PG_VIEW, "BANK_GRAPH_VIEW", GraphSource.PG_VIEW,
                                                  ReadGraphOption.optimizeFor(GraphOptimizedFor.READ),
                                                  ReadGraphOption.synchronizable());

OnMissingVertexオプションの使用

エッジのソース頂点または宛先頂点のいずれか、あるいはその両方が欠落している場合は、頂点が欠落しているエッジを処理するための動作を指定するOnMissingVertexOptionを使用できます。このオプションでは、次の値がサポートされています。

  • ReadGraphOption.onMissingVertex(OnMissingVertex.ERROR): これはデフォルト・オプションで、頂点が欠落しているエッジに対してエラーをスローする必要があることを指定します。
  • ReadGraphOption.onMissingVertex(OnMissingVertex.IGNORE_EDGE): 欠落した頂点のエッジを無視する必要があることを指定します。
  • ReadGraphOption.onMissingVertex(OnMissingVertex.IGNORE_EDGE_LOG): 欠落した頂点のエッジを無視し、無視されたすべてのエッジをログに記録する必要があることを指定します。
  • ReadGraphOption.onMissingVertex(OnMissingVertex.IGNORE_EDGE_LOG_ONCE): 欠落した頂点のエッジを無視し、最初の無視されたエッジのみをログに記録する必要があることを指定します。

次の例では、頂点が欠落しているエッジを無視し、最初の無視されたエッジのみをログに記録することによって、PGビューをロードします。ログを表示するには、/etc/oracle/graph/logback.xmlのデフォルトのLogback構成ファイルと、/etc/oracle/graph/logback-server.xmlのグラフ・サーバー(PGX)ロガー構成ファイルを更新して、DEBUGログを記録する必要があります。そのようにすると、無視されたエッジを/var/opt/log/pgx-server.logファイルで確認できます。

opg4j> session.readGraphByName("REGIONS", GraphSource.PG_VIEW,
...>                             ReadGraphOption.onMissingVertex(OnMissingVertex.IGNORE_EDGE_LOG_ONCE))
$7 ==> PgxGraph[name=REGIONVIEW_3,N=27,E=18,created=1655903219910]
PgxGraph graph = session.readGraphByName("REGIONS", GraphSource.PG_VIEW, ReadGraphOption.onMissingVertex(OnMissingVertex.IGNORE_EDGE_LOG_ONCE));

8.1.2 readGraphByName APIへのスキーマ名の指定

readGraphByName APIを使用してプロパティ・グラフ・ビュー(PGビュー)をロードするときにスキーマ名を指定できます。

この機能を使用すると、別のユーザー・スキーマからグラフ・サーバー(PGX)にPGビューをロードできます。ただし、別のスキーマからPGビューをロードする場合は、基礎となるすべてのメタデータおよびデータ表に対するREAD権限を持っていることを確認してください。

次の例では、GRAPHUSERスキーマからPGビューをロードします:

opg4j> var graph = session.readGraphByName("GRAPHUSER", "FRIENDS", GraphSource.PG_VIEW)
graph ==> PgxGraph[name=FRIENDS,N=6,E=4,created=1672743474212]
PgxGraph graph = session.readGraphByName("GRAPHUSER", "FRIENDS", GraphSource.PG_VIEW);

8.2 JSON構成ファイルを使用したグラフのロード

プロパティ・グラフ・ビューをグラフ・サーバー(PGX)にロードするために、ロードするグラフのメタデータが含まれるグラフ構成ファイルを作成できます。

JSON構成ファイルのサンプルを次に示します:

{
  "name": "BANK_GRAPH",
  "source_name": "BANK_GRAPH",
  "source_type": "pg_view",
  "jdbc_url":"jdbc:oracle:thin:@localhost:1521/orclpdb",
  "username":"graphuser",
  "keystore_alias":"database1",
  "vertex_providers":[
        {
            "name":"Accounts",
            "format":"rdbms",
            "database_table_name":"BANK_ACCOUNTS",
            "key_column":"ID",
            "key_type": "integer",
            "parallel_hint_degree": 3,
             "props":[
                {
                        "name":"ID",
                        "type":"integer"

                },
                 {
                        "name":"NAME",
                        "type":"string"
                 }

            ]


        }
    ],
    "edge_providers":[
        {
            "name":"Transfers",
            "format":"rdbms",
            "database_table_name":"BANK_TXNS",
            "key_column":"ID",
            "parallel_hint_degree": 3,
            "source_column":"FROM_ACCT_ID",
            "destination_column":"TO_ACCT_ID",
            "source_vertex_provider":"Accounts",
            "destination_vertex_provider":"Accounts",
            "props":[
                {
                        "name":"FROM_ACCT_ID",
                        "type":"integer"
                },
                {
                        "name":"TXN_AMOUNT",
                        "type":"float",
                        "column":"AMOUNT"
                },
                {
                        "name":"DESCRIPTION",
                        "type":"string"
                },
                {
                        "name":"TO_ACCT_ID",
                        "type":"integer"
                }
            ]
        }
    ]
}

前述の構成では、Javaキーストアの別名を使用して、キーストア・ファイルに格納されているデータベース・パスワードを参照します。詳細は、「キーストアへのデータベース・パスワードの格納」を参照してください。

また、エッジ・プロパティAMOUNTの名前もTXN_AMTに変更されます。これは、グラフをグラフ・サーバー(PGX)にロードするときに、必要に応じて頂点プロパティまたはエッジ・プロパティの名前を、データベースの基礎となる列の名前とは異なる名前に変更できることを意味します。

関連項目:

これで、次に示すように、グラフをグラフサーバーに読み込むことができます。

./bin/opg4j --secret_store /etc/oracle/graph/keystore.p12
enter password for keystore /etc/oracle/graph/keystore.p12:
For an introduction type: /help intro
Oracle Graph Server Shell 23.1.0
Variables instance, session, and analyst ready to use
opg4j> var g = session.readGraphWithProperties("<path_to_json_configuration>")
g ==> PgxGraph[name=BANK_GRAPH_NEW,N=999,E=4993,created=1675960224397]
ServerInstance instance = GraphServer.getInstance("https://localhost:7007", <username>, <password>.toCharArray());
PgxSession session = instance.createSession("my-session");
String keystorePath = "/etc/oracle/graph/keystore.p12";
char[] keystorePassword = "<keystore_password>".toCharArray();
session.registerKeystore(keystorePath, keystorePassword);
PgxGraph g = session.readGraphWithProperties("<path_to_json_configuration>");
System.out.println("Graph: " + g);

8.2.1 グラフのロード時のPARALLELヒントの構成

基礎となるSQL問合せで使用されるGraphConfigフィールドPARALLEL_HINT_DEGREEを使用して特定のパラレル・ヒント値を構成することで、グラフ・ロードのパフォーマンスを最適化することもできます。これは、JSON構成ファイルを使用するかGraphConfigBuilder APIを介して、グラフをロードするときに適用できます。

次の表に、指定されたPARALLEL_HINT_DEGREE値に基づいて内部問合せがどのように構成されるかを示します。

表8-2 PARALLEL_HINT_DEGREEの値

PARALLEL_HINT_DEGREEの値 SQL文で使用されるパラレル・ヒント
正の整数(n) 指定されたn度を使用します。

SELECT /*+ PARALLEL(n) */ ...

0 (ゼロ) プレーン・ヒントを使用します。

SELECT /*+ PARALLEL */ ...

負の整数

(デフォルト値: -1)

PARALLELヒントはありません:

SELECT ...

関連項目:

8.3 グラフ構成オブジェクトの定義によるグラフのロード

グラフをOracle Databaseからロードするには、まずGraphConfigBuilderクラスを使用してグラフ構成オブジェクトを定義してから、グラフをグラフ・サーバー(PGX)に読み込みます。

次の例では、データベースで<database user>/<database password>として認証してプロパティ・グラフ・ビューをメモリーにロードします。

opg4j> var vertexConfig = new RdbmsEntityProviderConfigBuilder().
...>                                         setName("Account").
...>                                         setKeyColumn("ID").
...>                                         setParallelHintDegree(3).
...>                                         setDatabaseTableName("BANK_ACCOUNTS").
...>                                         addProperty("ID", PropertyType.INTEGER).
...>                                         build()

opg4j> var edgeConfig = new RdbmsEntityProviderConfigBuilder().
...>                                    setName("Transfer").
...>                                    setKeyColumn("TXN_ID").
...>                                    setSourceColumn("FROM_ACCT_ID").
...>                                    setDestinationColumn("TO_ACCT_ID").
...>                                    setSourceVertexProvider("Account").
...>                                    setDestinationVertexProvider("Account").
...>                                    setParallelHintDegree(3).
...>                                    createKeyMapping(true).
...>                                    setDatabaseTableName("BANK_TXNS").
...>                                    addProperty("FROM_ACCT_ID", PropertyType.INTEGER).
...>                                    addProperty("TO_ACCT_ID", PropertyType.INTEGER).
...>                                    addProperty("AMOUNT", PropertyType.FLOAT).
...>                                    build()

opg4j> var cfg = GraphConfigBuilder.forPartitioned().
...>                  setJdbcUrl("jdbc:oracle:thin:@localhost:1521/orclpdb").
...>                  setUsername("graphuser").
...>                  setPassword("<password>").
...>                  setName("bank_graph").
...>                  setSourceName("bank_graph").
...>                  setSourceType(SourceType.PG_VIEW).
...>                  setVertexIdType(IdType.INTEGER).
...>                  addVertexProvider(vertexConfig).
...>                  addEdgeProvider(edgeConfig).
...>                  build()

opg4j> var g = session.readGraphWithProperties(cfg)
g ==> PgxGraph[name=bank_graph,N=999,E=4993,created=1676806306348]
// Build the vertex provider
RdbmsEntityProviderConfig vertexConfig = new RdbmsEntityProviderConfigBuilder()
                                              .setName("Account")
                                              .setKeyColumn("ID")
                                              .setParallelHintDegree(3)
                                              .setDatabaseTableName("BANK_ACCOUNTS")
                                              .addProperty("ID", PropertyType.INTEGER)
                                              .build();
// Build the edge provider
RdbmsEntityProviderConfig edgeConfig = new RdbmsEntityProviderConfigBuilder()
                                              .setName("Transfer")
                                              .setKeyColumn("TXN_ID")
                                              .setSourceColumn("FROM_ACCT_ID")
                                              .setDestinationColumn("TO_ACCT_ID")
                                              .setSourceVertexProvider("Account")
                                              .setDestinationVertexProvider("Account")
                                              .setParallelHintDegree(3)
                                              .createKeyMapping(true)
                                              .setDatabaseTableName("BANK_TXNS")
                                              .addProperty("FROM_ACCT_ID", PropertyType.INTEGER)
                                              .addProperty("TO_ACCT_ID", PropertyType.INTEGER)
                                              .addProperty("AMOUNT", PropertyType.FLOAT)
                                              .build();
// Build the graph 
GraphConfig cfg = GraphConfigBuilder.forPartitioned()
                           .setJdbcUrl("jdbc:oracle:thin:@localhost:1521/orclpdb")
                           .setUsername("graphuser")
                           .setPassword("<password>")
                           .setName("bank_graph")
                           .setSourceName("bank_graph")
                           .setSourceType(SourceType.PG_VIEW)
                           .setVertexIdType(IdType.INTEGER)
                           .addVertexProvider(vertexConfig)
                           .addEdgeProvider(edgeConfig)
                           .build();

PgxGraph g = session.readGraphWithProperties(cfg);

8.4 プロパティ・グラフ・ビューからのサブグラフのロード

プロパティ・グラフ・ビューからサブグラフを作成し、グラフ・サーバー(PGX)のメモリーにロードできます。

グラフ全体をメモリーにロードするかわりに、サブグラフをロードできます。これにより、消費されるメモリーが少なくなります。

次の各項では、サブグラフのロードおよび拡張について詳しく説明します。

8.4.1 PGQLベースのサブグラフのロード

PgViewSubgraphReader#fromPgView APIを使用し、一連のPGQL問合せを使用してプロパティ・グラフ・ビュー(PGビュー)からインメモリー・サブグラフを作成できます。

これらのPGQL問合せは、サブグラフにロードされる頂点およびエッジを定義します。複数のPGQL問合せを使用することもでき、結果の出力グラフはサブグラフを結合したものであり、それぞれが各PGQL問合せによって別々にロードされます。

ノート:

  • 非コンポジットの頂点およびエッジ・キーのみがサポートされています。
  • 数値エッジ・キーのみがサポートされています。
  • プロパティ・グラフ・ビューからのサブグラフのロードでは、GROUP BY句またはORDER BY句を指定したPGQL問合せはサポートされていません。

次の例では、複数のPGQL問合せを使用してPGビューからサブグラフを作成します。

opg4j> var graph = session.readSubgraph().
...>                    fromPgView("FRIENDS").
...>                    queryPgql("MATCH (v1:Person)-[e:FRIENDOF]->(v2:Person) WHERE id(v1) = 'PERSONS(1)'").
...>                    queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'").
...>                    load()
graph ==> PgxGraph[name=FRIENDS,N=3,E=1,created=1646726883194]
PgxGraph graph = session.readSubgraph()
                       .fromPgView("FRIENDS")
                       .queryPgql("MATCH (v1:Person)-[e:FRIENDOF]->(v2:Person) WHERE id(v1) = 'PERSONS(1)'")
                       .queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'")
                       .load();
>>> graph = session.read_subgraph_from_pg_view("FRIENDS", ["MATCH (v1:Person)-[e:FRIENDOF]->(v2:Person) WHERE id(v1) = 'PERSONS(1)'",
...                           "MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'"])
>>> graph
PgxGraph(name: FRIENDS, v: 3, e: 1, directed: True, memory(Mb): 0)

グラフ・ビジュアライゼーション・ツールを使用した前述のPGQL問合せの出力を次に示します。

図8-1 サブグラフ・ビジュアライゼーション

図8-1の説明が続きます
「図8-1 サブグラフ・ビジュアライゼーション」の説明

カスタム名によるサブグラフのロード

デフォルトでは、新しいサブグラフはPGビュー・グラフと同じ名前で作成されます。あるいは、カスタム名でサブグラフをロードする場合は、次のようにサブグラフ名を構成できます。

opg4j> var graph = session.readSubgraph().
...>                  fromPgView("FRIENDS").
...>                  queryPgql("MATCH (v1:Person)-[e:FRIENDOF]->(v2:Person) WHERE id(v1) = 'PERSONS(1)'").
...>                  queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'").
...>                  load("friends_network")
graph ==> PgxGraph[name=friends_network,N=3,E=1,created=1664458398090]
PgxGraph graph = session.readSubgraph()
                       .fromPgView("FRIENDS")
                       .queryPgql("MATCH (v1:Person)-[e:FRIENDOF]->(v2:Person) WHERE id(v1) = 'PERSONS(1)'")
                       .queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'")
                       .load("friends_network");
>>> graph = session.read_subgraph_from_pg_view("FRIENDS",
...                   ["MATCH (v1:Person)-[e:FRIENDOF]->(v2:Person) WHERE id(v1) = 'PERSONS(1)'",
...                    "MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'"],
...                   graph_name="friends_network")
>>> graph
PgxGraph(name: friends_network, v: 3, e: 1, directed: True, memory(Mb): 0)

スキーマ名の明示的な指定によるサブグラフのロード

別のスキーマからPGビューを読み取ることでサブグラフをロードする場合は、さらにPgViewSubgraphReader#fromPgView APIの引数としてスキーマ名を指定できます。また、PGビューの基礎となるすべてのメタデータおよびデータ表に対するREAD権限を持っていることも確認する必要があります。

たとえば:

opg4j> var graph = session.readSubgraph()
...> .fromPgView("GRAPHUSER", "FRIENDS")
...> .queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'")
...> .load()
graph ==> PgxGraph[name=FRIENDS,N=1,E=0,created=1672743755511]
PgxGraph graph = session.readSubgraph()
                       .fromPgView("GRAPHUSER", "FRIENDS")
                       .queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'")
                       .load();
>>> graph = session.read_subgraph_from_pg_view("FRIENDS",
...  ["MATCH (v:Person) WHERE id(v) = 'PERSONS(2)'"],
...  schema="GRAPHUSER")

8.4.2 準備済PGQL問合せ

プロパティ・グラフ・ビューからサブグラフをロードするときに、準備済問合せを使用することもできます。

準備済PGQL問合せを使用してバインド変数を渡すことができます。PreparedPgViewPgqlQuery#preparedPgqlQueryメソッドは、サブグラフをロードするために実行される問合せのリストに準備済問合せを追加します。PreparedPgViewPgqlQuery APIは、変数のバインディングを設定し、サブグラフのロードを続行します。

たとえば:

opg4j> var pgViewSubgraphReader = session.readSubgraph().
...>                                      fromPgView("FRIENDS")
pgViewSubgraphReader ==> oracle.pgx.api.subgraph.PgViewSubgraphReader@33bfe6d3
opg4j> var preparedPgqlQuery = pgViewSubgraphReader.preparedPgqlQuery("MATCH (v1:Person)-[e:FriendOf]->(v2:Person) WHERE id(v2)=?")
preparedPgqlQuery ==> oracle.pgx.api.subgraph.PreparedPgViewPgqlQuery@2e6b379c
opg4j> preparedPgqlQuery = preparedPgqlQuery.withStringArg(1, "PERSONS(3)")
preparedPgqlQuery ==> oracle.pgx.api.subgraph.PreparedPgViewPgqlQuery@2e6b379c
opg4j> var graph = preparedPgqlQuery.load()
graph ==> PgxGraph[name=FRIENDS_2,N=3,E=2,created=1648566047855]

import oracle.pgx.api.subgraph.*;
…
…
PgViewSubgraphReader pgViewSubgraphReader= session.readSubgraph().fromPgView("FRIENDS");
PreparedPgViewPgqlQuery preparedPgqlQuery = pgViewSubgraphReader.preparedPgqlQuery("MATCH (v1:Person)-[e:FriendOf]->(v2:Person) WHERE id(v2)=?");
preparedPgqlQuery = preparedPgqlQuery.withStringArg(1, "PERSONS(3)"); 
PgxGraph graph = preparedPgqlQuery.load(); 
>>> from pypgx.api import PreparedPgqlQuery
>>> from pypgx.api import PreparedPgqlQueryStringArgument
>>> graph = session.read_subgraph_from_pg_view("FRIENDS",
...   [PreparedPgqlQuery("MATCH (v1:Person)-[e:FriendOf]->(v2:Person) WHERE id(v2)=?", [PreparedPgqlQueryStringArgument("PERSONS(3)")])])
>>> graph
PgxGraph(name: FRIENDS, v: 3, e: 2, directed: True, memory(Mb): 0)

8.4.3 データベース接続資格証明の指定

現在のユーザーのデフォルト資格証明を使用するかわりに、PgViewSubgraphReader#fromPgView APIを使用してデータベース接続資格証明を指定できます。

次の例は、デフォルト以外のデータベース接続設定のサブグラフのロードを示しています。

opg4j> var graph = session.readSubgraph().
...>                     fromPgView("FRIENDS").
...>                     username("graphuser").
...>                     password("<password_for_graphuser>").
...>                     keystoreAlias("database1").
...>                     schema("graphuser").
...>                     jdbcUrl("jdbc:oracle:thin:@localhost:1521/orclpdb").
...>                     connections(12).
...>                     queryPgql("MATCH (a:Person)").
...>                     load()
graph ==> PgxGraph[name=FRIENDS,N=4,E=0,created=1648541234520] 
PgxGraph graph = session.readSubgraph()
                        .fromPgView("FRIENDS")
                        .username("graphuser")
                        .password("<password_for_graphuser>")
                        .keystoreAlias("database1")
                        .schema("graphuser")
                        .jdbcUrl("jdbc:oracle:thin:@localhost:1521/orclpdb")
                        .connections(12)
                        .queryPgql("MATCH (a:Person)")
                        .load();

8.4.4 サブグラフの動的な拡張

インメモリー・サブグラフを拡張するには、別のサブグラフをメモリーにロードし、現在のインメモリー・サブグラフとマージします。

PgxGraph.expandGraph()メソッドを使用すると、サブグラフを拡張できます。2つのグラフをマージする際、次のことが適用されます。

  • 両方のグラフに別々のプロバイダ・セットを含めることができます。
  • グラフには、他のグラフと同じプロバイダをいくつか含めることができます。この場合、次のようになります:
    • 同じ名前のプロバイダには、同じラベルが必要です。
    • マージ対象のグラフには、ベース・グラフと同じまたは共通のプロパティのサブセットが必要です。ただし、いずれか一方のグラフのプロパティ数が多くなる可能性があります。

次の例に、「PGQLベースのサブグラフのロード」で作成したサブグラフの拡張を示します。

opg4j> graph = graph.expandGraph().
...>          withPgql().
...>          fromPgView("FRIENDS").
...>          queryPgql("MATCH (v1:PERSON) -[e:FRIENDOF]-> (v2:PERSON) WHERE id(v1) = 'PERSONS(2)'").
...>          preparedPgqlQuery("MATCH (v:PERSON) WHERE id(v) in ?").withStringArg(1, "PERSONS(4)").
...>          expand()
graph ==> PgxGraph[name=anonymous_graph_152,N=4,E=3,created=1647347092964]
graph = graph.expandGraph()
             .withPgql()
             .fromPgView("FRIENDS")
             .queryPgql("MATCH (v1:PERSON) -[e:FRIENDOF]-> (v2:PERSON) WHERE id(v1) = 'PERSONS(2)'")
             .preparedPgqlQuery("MATCH (v:PERSON) WHERE id(v) in ?").withStringArg(1, "PERSONS(4)")
             .expand();
>>> from pypgx.api import PreparedPgqlQuery
>>> from pypgx.api import PreparedPgqlQueryStringArgument
>>> graph = graph.expand_with_pgql(["MATCH (v1:PERSON) -[e:FRIENDOF]-> (v2:PERSON) WHERE id(v1) = 'PERSONS(2)'",
...               PreparedPgqlQuery("MATCH (v:Person) WHERE id(v)=?", [PreparedPgqlQueryStringArgument("PERSONS(4)")])],
...               pg_view_name="FRIENDS")
>>> graph
PgxGraph(name: anonymous_graph_66, v: 4, e: 3, directed: True, memory(Mb): 0)

グラフ・ビジュアライゼーション・ツールを使用した前述のPGQL問合せの出力を次に示します。これで、サブグラフは拡張され、サブグラフにすでに存在していたPERSONS(1)に加えて、PERSONS(2)friendOf関係が含まれるようになります。

図8-2 サブグラフの拡張

図8-2の説明が続きます
「図8-2 サブグラフの拡張」の説明

スキーマ名の明示的な指定によるサブグラフの拡張

グラフを拡張するときに、別のスキーマからPGビューを読み取ることで、別のサブグラフをロードできます。このためには、PgqlViewGraphExpander#fromPgView APIの引数としてスキーマ名を指定する必要があります。また、PGビューの基礎となるすべてのメタデータおよびデータ表に対するREAD権限を持っていることも確認する必要があります。

たとえば:

opg4j> graph = graph.expandGraph().
...>           withPgql().
...>           fromPgView("GRAPHUSER", "FRIENDS").
...>           queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(1)'").
...>           expand()
graph ==> PgxGraph[name=anonymous_graph_18,N=1,E=0,created=1672848726308]
graph = graph.expandGraph()
             .withPgql()
             .fromPgView("GRAPHUSER", "FRIENDS")
             .queryPgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(1)'")
             .expand();
>>> graph = graph.expand_with_pgql("MATCH (v:Person) WHERE id(v) = 'PERSONS(1)'",
...  pg_view_name="FRIENDS", schema="GRAPHUSER")
>>> graph
PgxGraph(name: anonymous_graph_6, v: 2, e: 0, directed: True, memory(Mb): 0)

マージ戦略の使用

グラフの拡張時に、新しいグラフ・データにある頂点およびエッジの一部がすでにベース・グラフにロードされている場合があります。このような場合、頂点およびエッジのプロパティ値が、ベース・グラフとマージ対象となる新しいグラフの両方にあるすべての頂点およびエッジで異なる場合、次のことが適用されます。

  • マージ戦略がKEEP_CURRENT_VALUESの場合、新しいグラフからの頂点およびエッジのプロパティ値は無視されます。
  • マージ戦略がUPDATE_WITH_NEW_VALUESの場合、頂点およびエッジのプロパティ値は新しいグラフで検出された値で更新されます。

たとえば:

opg4j> import oracle.pgx.api.expansion.PropertyMergeStrategy
opg4j> graph = graph.expandGraph().
...>          withPgql().
...>          fromPgView("FRIENDS").
...>          queryPgql("MATCH (v1:PERSON) -[e:FRIENDOF]-> (v2:PERSON) WHERE id(v1) = 'PERSONS(2)'").
...>          preparedPgqlQuery("MATCH (v:PERSON) WHERE id(v) in ?").withStringArg(1, "PERSONS(4)").
...>          vertexPropertiesMergingStrategy(PropertyMergeStrategy.UPDATE_WITH_NEW_VALUES).
...>          expand()
import oracle.pgx.api.expansion.PropertyMergeStrategy;
graph = graph.expandGraph()
             .withPgql()
             .fromPgView("FRIENDS")
             .queryPgql("MATCH (v1:PERSON) -[e:FRIENDOF]-> (v2:PERSON) WHERE id(v1) = 'PERSONS(2)'")
             .preparedPgqlQuery("MATCH (v:PERSON) WHERE id(v) in ?").withStringArg(1, "PERSONS(4)")
             .vertexPropertiesMergingStrategy(PropertyMergeStrategy.UPDATE_WITH_NEW_VALUES)
             .expand();