13.7 PGQLプロパティ・グラフに対するPGQL問合せの実行
このトピックでは、Oracle Database表のPGQLプロパティ・グラフに対してPGQL問合せを直接実行する方法について説明します。
PGQL問合せの実行フローを次の図に示します。
基本的な実行フローは次のとおりです。
- PGQL問合せはJava APIを介してRDBMS上のPGQLに送信されます。
- PGQLプロパティ・グラフの内部メタデータ表を使用してPGQL問合せがSQL文に変換されます。
- 変換されたSQLは、JDBCによってOracle Databaseに送信されます。
- SQL結果セットは、PGQL結果セットとしてラップされてコール元に返されます。
- PGQLプロパティ・グラフでサポートされているPGQL機能および制限事項
PGQLプロパティ・グラフでサポートされているPGQL機能および制限事項について学習します。 - PGQL問合せのSQL変換
PgqlStatement
およびPgqlPreparedStatement
のtranslateQuery()
メソッドとgetSqlTranslation()
メソッドを介してPGQL問合せのSQL変換を取得できます。 - PGQL問合せでのパフォーマンスの考慮事項
- JavaおよびPython APIを使用したPGQL問合せの実行
親トピック: プロパティ・グラフ問合せ言語(PGQL)
13.7.1 PGQLプロパティ・グラフでサポートされているPGQL機能および制限事項
PGQLプロパティ・グラフでサポートされているPGQL機能および制限事項について学習します。
次の表に、PGQLプロパティ・グラフでサポートされているPGQL機能およびサポートされていないPGQL機能の完全なリストを示します。
表13-2 PGQLプロパティ・グラフでサポートされているPGQLの機能および制限事項
機能 | PGQLプロパティ・グラフ上のPGQL |
---|---|
CREATE PROPERTY GRAPH |
サポート対象 |
DROP PROPERTY GRAPH |
サポート対象 |
固定長パターン一致 | サポート対象 |
可変長パターン一致の目標 | サポート対象:
制限事項:
|
可変長パターン一致の数量詞 | サポート対象:
|
可変長パスのネスト解除 | サポート対象:
サポート対象外:
|
GROUP BY |
サポート対象 |
HAVING |
サポート対象 |
集計 | サポート対象:
制限事項:
|
DISTINCT
|
サポート対象 |
SELECT v.* |
サポート対象 |
ORDER BY (+ASC/DESC)、LIMIT、OFFSET |
サポート対象 |
データ型 | 使用可能なすべてのOracle RDBMSデータ型がサポートされています |
JSON | サポート対象:
|
演算子 | サポート対象:
|
関数および述語 |
サポート対象は、オプションのスキーマおよびパッケージ修飾子が指定された サポートされているPGQL関数/述語:
制限事項:
|
ユーザー定義関数 | サポート対象:
|
副問合せ:
|
サポート対象:
|
GRAPH_TABLE 演算子
|
サポート対象
拡張機能:
|
INSERT/UPDATE/DELETE |
Oracle Database 19c以降でサポート |
INTERVAL リテラルおよび操作
|
サポート対象外 |
13.7.1.1 例でサポートされているPGQL機能に関する追加情報
PGQLプロパティ・グラフでは、次のPGQL機能がサポートされています。
- 再帰的問合せは、次の可変長パス検索の目標でサポートされています。
- 到達可能性
- ANY
- ANY SHORTEST
- TOP k SHORTEST
- 再帰的問合せは、次の水平集計でサポートされています。
- LISTAGG
SELECT LISTAGG(src.first_name || ' ' || src.last_name, ',') FROM MATCH TOP 2 SHORTEST ( (n:Person) ((src)-[e:knows]->)* (m:Person) ) WHERE n.id = 1234
- SUM
SELECT SUM(e.weight + 3) FROM MATCH TOP 2 SHORTEST ( (n:Person) -[e:knows]->* (m:Person) ) WHERE n.id = 1234
- COUNT
SELECT COUNT(e) FROM MATCH TOP 2 SHORTEST ( (n:Person) -[e:knows]->* (m:Person) ) WHERE n.id = 1234
- AVG
SELECT AVG(dst.age) FROM MATCH TOP 2 SHORTEST ( (n:Person) (-[e:knows]->(dst))* (m:Person) ) WHERE n.id = 1234
- MIN (プロパティ値または
CAST
式の場合のみ)SELECT MIN(CAST(dst.age + 5 AS INTEGER)) FROM MATCH TOP 2 SHORTEST ( (n:Person) (-[e:knows]->(dst))* (m:Person) ) WHERE n.id = 1234
- MAX (プロパティ値または
CAST
式の場合のみ)SELECT MAX(dst.birthday) FROM MATCH TOP 2 SHORTEST ( (n:Person) (-[e:knows]->(dst))* (m:Person) ) WHERE n.id = 1234
- LISTAGG
- 再帰的問合せでは、次の数量詞がサポートされています。
表13-3 PGQL SELECT問合せでサポートされている数量詞
構文 説明 *
0 (ゼロ)以上 +
1以上 ?
0 (ゼロ)または1 {n}
nに等しい {n,}
n以上 {n,m}
nとmの間(両端を含む) {,m}
0からmの間(両端を含む) - 精度とスケールによるデータ型キャストがサポートされています。
SELECT CAST(v.id AS VARCHAR2(10)) || '→' || CAST(w.id AS VARCHAR2(10)) AS friendOf FROM MATCH (v) -[:friendOf]->(w)
SELECT CAST(e.mval AS NUMBER(5,2)) AS mval FROM MATCH () -[e:knows]->() WHERE e.mval = '342.5'
- Oracle Databaseの組込み関数とユーザー定義関数(UDF)が両方ともサポートされています。
たとえば:
- 表に、
{"name":"John", "age": 43}
などの値が含まれているJSON列があると仮定します。SELECT JSON_VALUE(p.attributes, '$.name') AS name FROM MATCH (p:Person) WHERE JSON_VALUE(p.attributes, '$.age') > 35
- Oracle Text索引が表内のテキスト列に存在すると仮定します。
SELECT n.text FROM MATCH (n) WHERE CONTAINS(n.text, 'cat', 1) > 0
- UDFの
updated_id
がグラフ・サーバー(PGX)に登録されていると仮定します。SELECT my.updated_id(n.ID) FROM MATCH(n) LIMIT 10
- 表に、
SELECT v.*
句では、頂点またはエッジのすべてのプロパティの選択がサポートされています。v
は、プロパティが選択されている変数です。次の例では、グラフのすべてのエッジ・プロパティを取得します。SELECT label(e), e.* FROM MATCH (n)-[e]->(m) ON bank_graph LIMIT 3
実行時に、前述の問合せが、次のように変数
e
にバインドされているすべてのプロパティを取得します。+--------------------------------------------------------------+ | label(e) | AMOUNT | DESCRIPTION | FROM_ACCT_ID | TO_ACCT_ID | +--------------------------------------------------------------+ | TRANSFERS | 1000 | transfer | 178 | 921 | | TRANSFERS | 1000 | transfer | 178 | 462 | | TRANSFERS | 1000 | transfer | 179 | 688 | +--------------------------------------------------------------+
複数の変数を使用してすべてのプロパティを選択した場合に、列名が重複しないように
PREFIX
を指定できます。たとえば:SELECT n.* PREFIX 'n_', e.* PREFIX 'e_', m.* PREFIX 'm_' FROM MATCH (n:Accounts) -[e:transfers]-> (m:Accounts) ON bank_graph LIMIT 3
問合せ出力は次のようになります。
+--------------------------------------------------------------------------------------------+ | n_ID | n_NAME | e_AMOUNT | e_DESCRIPTION | e_FROM_ACCT_ID | e_TO_ACCT_ID | m_ID | m_NAME | +--------------------------------------------------------------------------------------------+ | 178 | Account | 1000 | transfer | 178 | 921 | 921 | Account | | 178 | Account | 1000 | transfer | 178 | 462 | 462 | Account | | 179 | Account | 1000 | transfer | 179 | 688 | 688 | Account | +--------------------------------------------------------------------------------------------+
ラベル式を使用すると、指定した頂点またはエッジ・ラベルに属するプロパティのみを選択できます。
SELECT LABEL(n), n.* FROM MATCH (n:Accounts) ON bank_graph LIMIT 3
前述の問合せ出力は次のようになります。
+-----------------------+ | LABEL(n) | ID | NAME | +-----------------------+ | ACCOUNTS | 1 | User1 | | ACCOUNTS | 2 | User2 | | ACCOUNTS | 3 | User3 | +-----------------------+
- 頂点ペア間のすべてのパスを戻す
ALL
パス検索の目標がサポートされています。ただし、無限サイクルを回避するために、次の数量詞のみがサポートされています。- ?
- {n}
- {n.m}
- {,m}
たとえば、次のPGQL問合せでは、アカウント
284
からアカウント616
へのすべてのトランザクション・パスを検索します。SELECT LISTAGG(e.amount, ' + ') || ' = ', SUM(e.amount) AS total_amount FROM MATCH ALL (a:Accounts) -[e:Transfers]->{1,4}(b:Accounts) WHERE a.id = 284 AND b.id = 616 ORDER BY total_amount
実行すると、問合せによって次の結果が生成されます。
+--------------------------------------------------+ | LISTAGG(e.amount, ' + ') || ' = ' | TOTAL_AMOUNT | +--------------------------------------------------+ | 1000 + 1000 + 1000 = | 3000 | | 1000 + 1500 + 1000 = | 3500 | | 1000 + 1000 + 1000 + 1000 = | 4000 | +--------------------------------------------------+ $16 ==> oracle.pg.rdbms.pgql.pgview.PgViewResultSet@4f38acf
- 1列1行のみを戻すスカラー副問合せがサポートされています。
たとえば:
SELECT p.name AS name , ( SELECT SUM(t.amount) FROM MATCH (a) <-[t:transaction]- (:Account) ) AS sum_incoming , ( SELECT SUM(t.amount) FROM MATCH (a) -[t:transaction]-> (:Account) ) AS sum_outgoing , ( SELECT COUNT(DISTINCT p2) FROM MATCH (a) -[t:transaction]- (:Account) -[:owner]-> (p2:Person) WHERE p2 <> p ) AS num_persons_transacted_with , ( SELECT COUNT(DISTINCT c) FROM MATCH (a) -[t:transaction]- (:Account) -[:owner]-> (c:Company) ) AS num_companies_transacted_with FROM MATCH (p:Person) <-[:owner]- (a:Account) ORDER BY sum_outgoing + sum_incoming DESC
EXISTS
およびNOT EXISTS
副問合せがサポートされています。このような問合せでは、外部問合せのバインディングが指定された場合に問合せで1つ以上の結果が生成されるかどうかに応じて、TRUE
またはFALSE
になります。たとえば:
SELECT fof.name, COUNT(friend) AS num_common_friends FROM MATCH (p:Person) -[:knows]-> (friend:Person) -[:knows]-> (fof:Person) WHERE NOT EXISTS ( SELECT * FROM MATCH (p) -[:knows]-> (fof) )
- PGQL
LATERAL
副問合せがサポートされています。たとえば:SELECT recipient, COUNT(*) AS num_large_transactions FROM LATERAL ( SELECT m.id AS recipient FROM MATCH (n IS accounts) -[e IS transfers]-> (m IS accounts) WHERE n.id = 772 ORDER BY e.amount DESC ) GROUP BY recipient ORDER BY num_large_transactions DESC
- PGQL
GRAPH_TABLE
演算子がサポートされています。たとえば:SELECT * FROM GRAPH_TABLE ( bank_graph MATCH (a IS accounts) -[e IS transfers]-> (b IS accounts) COLUMNS ( a.id as from_ac, e.amount as amount, b.id as to_ac ) ) FETCH FIRST FIVE ROWS ONLY
- 頂点がエッジのソースまたは宛先かどうかを検証するソース(
IS [NOT] SOURCE OF
)述語および宛先(IS [NOT] DESTINATION OF
)述語がサポートされます。これは、エッジが任意の方向エッジ・パターン(-[e]-
)を介して一致する場合に便利です。このPGQL機能はOracle Database 23aiでのみサポートされていることに注意してください。たとえば:SELECT e.amount, CASE WHEN n IS SOURCE OF e THEN 'Outgoing transaction' ELSE 'Incoming transaction' END AS type FROM MATCH (n:Accounts) -[e:transfers]- (m:Accounts) WHERE n.id = 284 ORDER BY type, e.amount
この問合せの結果は次のようになります:+-------------------------------+ | AMOUNT | TYPE | +-------------------------------+ | 1000 | Incoming transaction | | 1200 | Outgoing transaction | | 1300 | Outgoing transaction | +-------------------------------+
- 値をJSON配列に集計するための
JSON_ARRAYAGG
関数(『Oracle Database SQL言語リファレンス』のJSON_ARRAYAGGを参照)がサポートされています。SELECT JSON_ARRAY_AGG(n.id) AS txn_from FROM MATCH (n:Accounts) -[e:transfers]- (m:Accounts) WHERE m.id = 616
実行すると、問合せによって次の結果が生成されます。
+-------------------------------------------+ | TXN_FROM | +-------------------------------------------+ | [202,582,650,108,744,756,801,674,710,764] | +-------------------------------------------+
- 頂点キーとエッジ・キーが一意かどうか、およびエッジのソースと宛先が存在するかどうかを確認する組込みグラフ検証関数
pg.validate()
。
次のように、頂点がない無効なキーまたはエッジの場合、例外が発生します:pgqlStmt.execute("CALL pg.validate('BANK_TXN_GRAPH')") $1 ==> false
pgqlStmt.execute("CALL pg.validate('COUNTRIES')") opg4j> pgqlStmt.execute("CALL pg.validate('COUNTRIES')") | Exception oracle.pg.rdbms.pgql.PgqlToSqlException: Invalid vertex key 60 for edge NO in edge table CTY_REG with destination key column(s) "REGION_ID" referencing REGIONS ( "REGION_ID" )
ONE ROW PER STEP
句を使用したパスのネスト解除は、PGQLGRAPH_TABLE
演算子問合せでサポートされています。SELECT * FROM GRAPH_TABLE ( financial_transactions MATCH (a IS account) -[IS transaction]->+ (a) KEEP SHORTEST 5 SIMPLE PATHS WHERE a.number = 10039 ONE ROW PER STEP ( v1, e, v2 ) COLUMNS( MATCHNUM() AS matchnum, ELEMENT_NUMBER(e) AS elemnum, v1.number AS account1, v2.number AS account2, e.amount)) ORDER BY matchnum, elemnum
前述の例に示すように、
ONE ROW PER STEP
句は、イテレータの頂点変数、イテレータのエッジ変数および別のイテレータの頂点変数を宣言します。問合せでは、次に示すように、ステップごとに1行(ステップは頂点-エッジ-頂点トリプル)が生成されます:+---------------------------------------------------+ | matchnum | elemnum | account1 | account2 | amount | +---------------------------------------------------+ | 0 | 2 | 10039 | 8021 | 1000.0 | | 0 | 4 | 8021 | 1001 | 1500.3 | | 0 | 6 | 1001 | 2090 | 9999.5 | | 0 | 8 | 2090 | 10039 | 9900.0 | | 1 | 2 | 10039 | 8021 | 1000.0 | | 1 | 4 | 8021 | 1001 | 3000.7 | | 1 | 6 | 1001 | 2090 | 9999.5 | | 1 | 8 | 2090 | 10039 | 9900.0 | +---------------------------------------------------+
前述の出力には、それぞれ4つのエッジを持つ2つのパスが示されています。
- PGQLの次の
SELECT
機能はサポートされていません。- パス式でのバインド変数の使用。
バインド変数を使用しようとすると、次のようなエラーになります。
opg4j> String s = "SELECT id(a) FROM MATCH ANY SHORTEST (a) -[e]->* (b) WHERE id(a) = ?"; s ==> "SELECT id(a) FROM MATCH ANY SHORTEST (a) -[e]->* (b) WHERE id(a) = ?" opg4j> PgqlPreparedStatement ps = pgqlConn.prepareStatement(s); ps ==> oracle.pg.rdbms.pgql.PgqlExecution@7806db3f opg4j> ps.setString(1, "PERSON(3)"); opg4j> ps.executeQuery(); | Exception java.lang.UnsupportedOperationException: Use of bind variables for path queries is not supported
in_degree
関数とout_degree
関数
- パス式でのバインド変数の使用。
ノート:
- PGQLプロパティ・グラフでサポートされているPGQL機能およびサポートされていないPGQL機能の完全なリストは、PGQLプロパティ・グラフでサポートされているPGQL機能および制限事項を参照してください。
- 再帰的問合せの問合せパフォーマンスを向上させるための推奨プラクティスの詳細は、PGQL問合せでのパフォーマンスの考慮事項を参照してください。
13.7.2 PGQL問合せのSQL変換
PgqlStatement
およびPgqlPreparedStatement
のtranslateQuery()
メソッドとgetSqlTranslation()
メソッドを介してPGQL問合せのSQL変換を取得できます。
PGQL問合せに未加工のSQLを使用すると、次のことができます。
- 他のSQLベースのツールまたはインタフェース(たとえば、SQL*PlusやSQL Developer)を使用してデータベースに対してSQLを直接実行する。
- 生成されたSQLをカスタマイズおよびチューニングして、パフォーマンスを最適化し、アプリケーションの特定要件を達成する。
- PGQL副問合せを、Oracle Databaseに格納されている他のデータ(リレーショナル表、空間データ、およびJSONデータなど)と結合する大規模なSQL問合せを作成する。
PGQL問合せの変換および実行に影響を与える複数のオプションがあります。問合せオプションを設定する主な方法は次のとおりです。
executeQuery
、translateQuery
、およびPgqlConnection.prepareStatement
メソッドに対して明示的引数を使用するexecuteQuery
およびtranslateQuery
のoptions
文字列引数でフラグを使用する-
Java JVM引数を使用する
次の表に、PGQLの変換と実行に使用できる問合せ引数をまとめています。
表13-4 PGQLの変換および実行のオプション
オプション | デフォルト | 明示的引数 | オプション・フラグ | JVM引数 |
---|---|---|---|---|
並列度 |
0 |
parallel |
なし |
なし |
タイムアウト |
無制限 |
timeout |
なし |
なし |
動的サンプリング |
2 |
dynamicSampling |
なし |
なし |
結果の最大数 |
無制限 |
maxResults |
なし |
なし |
逆パス最適化 | True | なし | REVERSE_PATH=F |
oracle.pg.rdbms.pgql.reversePath=false |
ソース・フィルタ最適化のプッシュ | True | なし | PUSH_SRC_HOPS=F |
oracle.pg.rdbms.pgql.pushSrcHops=false |
宛先フィルタ最適化のプッシュ | False | なし | PUSH_DST_HOPS=T |
oracle.pg.rdbms.pgql.pushDstHops=true |
最短パス変換でのビューの作成 | False | なし | SP_CREATE_VIEW=T |
oracle.pg.rdbms.pgql.spCreateView=true |
最短パス変換での表の作成 | True | なし | SP_CREATE_TABLE=F |
oracle.pg.rdbms.pgql.spCreateTable=false |
親トピック: PGQLプロパティ・グラフに対するPGQL問合せの実行
13.7.3 PGQL問合せでのパフォーマンスの考慮事項
次の項では、問合せのパフォーマンスに関するいくつかの推奨プラクティスについて説明します。
13.7.3.1 再帰的問合せ
再帰的問合せの実行を高速化するために、次の索引をお薦めします。
- 再帰パターンの基礎となるVERTEX表の場合、キー列の索引
- 再帰パターンの基礎となるEDGE表の場合、ソース・キー列の索引
ノート:
(ソース・キー, 宛先キー)に索引を作成することもできます。
たとえば、次のCREATE PROPERTY GRAPH文について考えてみます。
CREATE PROPERTY GRAPH people
VERTEX TABLES(
person
KEY ( id )
LABEL person
PROPERTIES( name, age )
)
EDGE TABLES(
knows
key (person1, person2)
SOURCE KEY ( person1 ) REFERENCES person (id)
DESTINATION KEY ( person2 ) REFERENCES person (id)
NO PROPERTIES
)
OPTIONS ( PG_PGQL )
また、次の問合せも考えてみます。
SELECT COUNT(*)
FROM MATCH ANY SHORTEST ( (n:Person) -[e:knows]->* (m:Person) )
WHERE n.id = 1234
前述の問合せの再帰的部分のパフォーマンスを向上させるには、次の索引が存在する必要があります。
CREATE INDEX <INDEX_NAME> ON PERSON(ID)
CREATE INDEX <INDEX_NAME> ON KNOWS(PERSON1)
またはCREATE INDEX <INDEX_NAME> ON KNOWS(PERSON1, PERSON2)
コンポジット頂点キー
コンポジット頂点キーの場合、キー列にファンクション索引を作成することで、問合せの実行を最適化できます。
- 再帰パターンの基礎となるVERTEX表の場合、カンマ区切りのキー列の連結に対するファンクション索引
- 再帰パターンの基礎となるEDGE表の場合、カンマ区切りのソース・キー列の連結に対するファンクション索引
ノート:
(ソース・キー列, 宛先キー列)に索引を作成することもできます。
たとえば、次のCREATE PROPERTY GRAPH文について考えてみます。
CREATE PROPERTY GRAPH people
VERTEX TABLES(
person
KEY ( id1, id2 )
LABEL person
PROPERTIES( name, age )
)
EDGE TABLES(
knows
key (id)
SOURCE KEY ( id1person1, id2person1 ) REFERENCES person (id1,id2)
DESTINATION KEY ( id1person2, id2person2 ) REFERENCES person (id1,id2)
NO PROPERTIES
)
OPTIONS ( PG_PGQL )
また、次の問合せも考えてみます。
SELECT COUNT(*)
FROM MATCH ANY SHORTEST ( (n:Person) -[e:knows]->* (m:Person) )
WHERE n.id = 1234
前述の問合せの再帰的部分のパフォーマンスを向上させるには、次の索引が存在する必要があります。
CREATE INDEX <INDEX_NAME> ON PERSON (ID1 || ',' || ID2)
CREATE INDEX <INDEX_NAME> ON KNOWS (ID1PERSON1 || ',' || ID2PERSON1)
またはCREATE INDEX <INDEX_NAME> ON KNOWS (ID1PERSON1 || ',' || ID2PERSON1, ID1PERSON2 || ',' || ID2PERSON2)
コンポジット頂点キーの一部の列が文字列列である場合、その列は、ファンクション索引の作成でカンマをエスケープする必要があります。
たとえば、前述の例の表PERSON
の列ID1
の型がVARCHAR2(10)
の場合、次のように列のカンマをエスケープする必要があります。
replace(ID1, ',', '\,')
そのため、パフォーマンスを向上させるための索引は次のようになります。
CREATE INDEX <INDEX_NAME> ON PERSON (replace(ID1, ',', '\,') || ',' || ID2)
CREATE INDEX <INDEX_NAME> ON KNOWS (replace(ID1PERSON1, ',', '\,') || ',' || ID2PERSON1)
親トピック: PGQL問合せでのパフォーマンスの考慮事項
13.7.3.2 問合せオプティマイザ・ヒントの使用
次のヒントを使用すると、PGQL可変長パス・パターンのSQLへの変換に影響を与えることができます。
REVERSE_PATH
: 逆パス最適化のオンとオフを切り替えます(デフォルトではON
)。ON
の場合、指定されたフィルタ述語に基づいて、パターンを最適に評価できるは、ソースから宛先なのか宛先からソースなのかを自動的に判断します。PUSH_SRC_HOPS
: ソース・フィルタ最適化の強要のオンとオフを切り替えます(デフォルトではON
)。ON
の場合、フィルタ述語を使用して、ソース頂点(パス評価が逆の場合は宛先頂点)の数を制限し、それによって可変長パス・パターン評価の検索領域を制限します。PUSH_DST_HOPS
: 宛先フィルタ最適化の強要のオンとオフを切り替えます(デフォルトではOFF
)。ON
の場合、フィルタ述語を使用して、宛先頂点(パス評価が逆の場合はソース頂点)の数を制限し、それによって可変長パス・パターン評価の検索領域を制限します。
前述のヒントは、次のJava APIメソッドでoptions
パラメータとして構成できます。
executeQuery(String pgql, String options)
translateQuery(String pgql, String options)
execute(String pgql, String matchOptions, String options)
たとえば、次のPGQL問合せについて考えます。
SELECT v1.name AS v1, v2.name AS v2, v3.name As v3
FROM MATCH (v1:Person)-[e1:friendOf]->(v2:Person),
MATCH ANY (v2:Person)-[e2:friendOf]->*(v3:Person)
WHERE v1.name= 'Bob'
PUSH_SRC_HOPS
のデフォルト・オプションを使用して前述の問合せを実行すると、次のようにstart_nodes_translation
の出力にフィルタ式が表示されます。
System.out.println(pgqlStatement.translateQuery(pgql).getSqlTranslation())
...
...
start_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "src_table", e1.person_b AS "src_key"
FROM "GRAPHUSER"."PERSONS" "V1", "GRAPHUSER"."FRIENDSHIPS" "E1"
WHERE (((e1.person_a = v1.person_id) AND NOT(e1.person_b IS NULL)) AND (v1.name = ''Bob''))')),
end_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "dst_table", v3.person_id AS "dst_key"
FROM "GRAPHUSER"."PERSONS" "V3"')),
...
...
ヒントPUSH_SRC_HOPS=F
を指定して前述の問合せを実行すると、次のように問合せはSQLに変換されます。
System.out.println(pgqlStatement.translateQuery(pgql,"PUSH_SRC_HOPS=F").getSqlTranslation())
...
...start_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "src_table", v2.person_id AS "src_key"
FROM "GRAPHUSER"."PERSONS" "V2"')),
end_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "dst_table", v3.person_id AS "dst_key"
FROM "GRAPHUSER"."PERSONS" "V3"')),
...
...
親トピック: PGQL問合せでのパフォーマンスの考慮事項
13.7.3.3 グラフ・メタデータ・キャッシュおよび変換キャッシュを使用した問合せ変換の高速化
次のグローバル・キャッシュは、PGQL問合せ変換の高速化に役立ちます。
- グラフ・メタデータ・キャッシュ: 表、ラベル、プロパティなどのグラフ・メタデータを格納します。
- 変換キャッシュ: PGQLからSQLへの変換を格納します。
次のJava APIを使用してキャッシュを構成できます。
clearTranslationCache()
disableTranslationCache()
enableTranslationCache()
setTranslationCacheMaxCapacity(int maxCapacity)
clearGraphMetadataCache()
disableGraphMetadataCache()
enableGraphMetadataCache()
setGraphMetadataCacheMaxCapacity(int maxCapacity)
setGraphMetadataRefreshInterval(long interval)
前述のこれらのメソッドは、PgqlConnection
クラスに属します。個々のキャッシュはデータベース・ユーザーごとに保持されるため、キャッシュされたオブジェクトは、接続URLとその下のユーザーが同じである場合に、異なるPgqlConnection
オブジェクト間で共有されます。
デフォルトでは、メタデータ・キャッシュと変換キャッシュの両方が有効になっている場合は、1000ms
(デフォルト値)ごとにリフレッシュされます。これにより、複数のJVMを介して1つのグラフを変更する場合に、メタデータ・キャッシュを簡単に同期できます。また、setGraphMetadataRefreshInterval (long interval)
関数をコールして、キャッシュのリフレッシュにかかる時間をミリ秒単位で増やすこともできます。
親トピック: PGQL問合せでのパフォーマンスの考慮事項
13.7.4 JavaおよびPython APIを使用したPGQL問合せの実行
oracle.pg.rdbms.pgql
パッケージのJava APIを使用して、PGQLプロパティ・グラフに対してPGQL問合せを実行できます。また、Python OPG4Pyパッケージを使用して、Oracle Databaseのグラフ・データに対してPGQL問合せを実行できます。このパッケージには、oracle.pg.rdbms.pgql
パッケージのJava APIをラップする1つ以上のモジュールを含むサブパッケージPgql
が含まれています。
親トピック: PGQLプロパティ・グラフに対するPGQL問合せの実行
13.7.4.1 PGQLプロパティ・グラフの作成
CREATE PROPERTY GRAPH
文を使用してPGQLプロパティ・グラフを作成できます。
例13-1 PGQLプロパティ・グラフの作成
次の例では、PGQLプロパティ・グラフの作成について説明します。
opg4j> var jdbcUrl="jdbc:oracle:thin:@<host_name>:<port>/<db_service>"
opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>");
opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
opg4j> var pgqlStmt = pgqlConn.createStatement() //create a PGQL Statement
opg4j> conn.setAutoCommit(false)
opg4j> var pgql =
...> "CREATE PROPERTY GRAPH bank_graph "
...> + "VERTEX TABLES ( bank_accounts AS Accounts "
...> + "KEY (id) "
...> + "LABEL Accounts "
...> + "PROPERTIES (id, name) "
...> + ") "
...> + "EDGE TABLES ( bank_txns AS Transfers "
...> + "KEY (txn_id) "
...> + "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_PGQL) "
opg4j> pgqlStmt.execute(pgql)
import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
import oracle.pg.rdbms.pgql.PgqlConnection;
import oracle.pg.rdbms.pgql.PgqlStatement;
/*
* This example shows how to create a PGQL property graph.
*/
public class PgqlCreate
{
public static void main(String[] args) throws Exception
{
int idx=0;
String jdbcUrl = args[idx++];
String username = args[idx++];
String password = args[idx++];
String graph = args[idx++];
Connection conn = null;
PgqlStatement pgqlStmt = null;
try {
//Get a jdbc connection
DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
conn = DriverManager.getConnection(jdbcUrl, username, password);
conn.setAutoCommit(false);
// Get a PGQL connection
PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
// Create a PGQL Statement
pgqlStmt = pgqlConn.createStatement();
// Execute PGQL Query
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 (txn_id) " +
"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_PGQL) ";
// Print the results
pgqlStmt.execute(pgql);
}
finally {
// close the statement
if (pgqlStmt != null) {
pgqlStmt.close();
}
// close the connection
if (conn != null) {
conn.close();
}
}
}
}
>>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "jdbc:oracle:thin:@localhost:1521/orclpdb")
>>> pgql_statement = pgql_conn.create_statement()
>>> pgql = """
... CREATE PROPERTY GRAPH bank_graph
... VERTEX TABLES (
... bank_accounts as Accounts
... LABEL Accounts
... PROPERTIES (id, name)
... )
... EDGE TABLES (
... bank_txns as Transfers
... KEY (txn_id)
... 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_PGQL)
... """
>>> pgql_statement.execute(pgql)
False
PGQLプロパティ・グラフの作成を確認するには、データベースで作成されるメタデータ表を確認します。
13.7.4.2 PGQL SELECT問合せの実行
次の例で説明するように、PGQL SELECT
問合せを実行できます。
例13-2 PgqlStatement
およびPgqlResultSet
を使用した単純なSELECT
問合せの実行
次の例では、PgqlConnection
を使用してPgqlStatement
を取得します。次に、PgqlStatement
のexecuteQuery
メソッドをコールし、これにより、PgqlResultSet
オブジェクトが返されます。PgqlResultSet
には、表形式モードで結果を表示するprint()
メソッドがあります。
opg4j> var jdbcUrl="jdbc:oracle:thin:@<host_name>:<port>/<db_service>"
opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>");
opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
opg4j> pgqlConn.setGraph("BANK_GRAPH")
opg4j> var pgqlStmt = pgqlConn.createStatement() //create a PGQL Statement
opg4j> String s = "SELECT n.* FROM MATCH (n:Accounts) LIMIT 3"
opg4j> var resultSet = pgqlStmt.executeQuery(s)
opg4j> resultSet.print() //Prints the query result set
+---------------+
| ID | NAME |
+---------------+
| 1 | Account1 |
| 2 | Account2 |
| 3 | Account3 |
+---------------+
import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
import oracle.pg.rdbms.pgql.PgqlConnection;
import oracle.pg.rdbms.pgql.PgqlResultSet;
import oracle.pg.rdbms.pgql.PgqlStatement;
/*
* This example shows how to execute a SELECT query on a PGQL property graph.
*/
public class PgqlExample1
{
public static void main(String[] args) throws Exception
{
int idx=0;
String jdbcUrl = args[idx++];
String username = args[idx++];
String password = args[idx++];
String graph = args[idx++];
Connection conn = null;
PgqlStatement pgqlStmt = null;
PgqlResultSet rs = null;
try {
//Get a jdbc connection
DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
conn = DriverManager.getConnection(jdbcUrl, username, password);
conn.setAutoCommit(false);
// Get a PGQL connection
PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
pgqlConn.setGraph(graph);
// Create a PGQL Statement
pgqlStmt = pgqlConn.createStatement();
// Execute PGQL Query
String query = "SELECT n.* FROM MATCH (n:Accounts) LIMIT 5";
rs = pgqlStmt.executeQuery(query);
// Print the results
rs.print();
}
finally {
// close the result set
if (rs != null) {
rs.close();
}
// close the statement
if (pgqlStmt != null) {
pgqlStmt.close();
}
// close the connection
if (conn != null) {
conn.close();
}
}
}
}
>>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "<jdbcUrl>")
>>> pgql_statement = pgql_conn.create_statement()
>>> pgql_conn.set_graph("BANK_GRAPH")
>>> s = "SELECT n.* FROM MATCH (n:Accounts) LIMIT 3"
>>> pgql_statement.execute_query(s)
>>> pgql_result_set = pgql_statement.execute_query(s)
>>> pgql_result_set.print()
+---------------+
| ID | NAME |
+---------------+
| 1 | Account1 |
| 2 | Account2 |
| 3 | Account3 |
+---------------+
>>> pgql_result_set
PgqlResultSet(java_pgql_result_set: oracle.pg.rdbms.pgql.PgqlResultSet, # of results: 3)
また、to_pandas()
メソッドを使用して、前述のコードで取得したPGQL結果セットをPandasデータフレームに変換できます。
ノート:
to_pandas()
のコールを正常に実行するには、システムにpandas
パッケージをインストールする必要があります。このパッケージは、バージョンPython 3.8およびPython 3.9のPythonクライアントのインストール時に自動的にインストールされます。ただし、to_pandas()
のコールに失敗した場合は、pandas
モジュールがシステムにインストールされているかどうかを確認してください。モジュールが見つからないか、Pythonのバージョンが前述のバージョンと異なる場合は、pandas
パッケージを手動でインストールします。
例13-3 PgqlPreparedStatement
を使用したSELECT
問合せの実行
opg4j> var jdbcUrl="jdbc:oracle:thin:@<host_name>:<port>/<db_service>"
opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>");
opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
opg4j> pgqlConn.setGraph("BANK_GRAPH");
opg4j> String s = "SELECT n.* FROM MATCH (n:Accounts) LIMIT ?"
opg4j> var ps = pgqlConn.prepareStatement(s, 0 /* timeout */, 4 /* parallel */, 2 /* dynamic sampling */, -1 /* max results */, null /* match options */, null /* options */)
opg4j> ps.setInt(1, 3)
opg4j> var rs = ps.executeQuery()
opg4j> rs.print() //Prints the query result set
+---------------+
| ID | NAME |
+---------------+
| 1 | Account1 |
| 2 | Account2 |
| 3 | Account3 |
+---------------+
import java.sql.Statement;
import java.sql.DriverManager;
import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
import oracle.pg.rdbms.pgql.*;
public class PgqlExample2
{
public static void main(String[] args) throws Exception
{
int idx=0;
String jdbcUrl = args[idx++];
String username = args[idx++];
String password = args[idx++];
String graph = args[idx++];
Connection conn = null;
PgqlStatement pgqlStmt = null;
PgqlResultSet rs = null;
try {
//Get a jdbc connection
DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
conn = DriverManager.getConnection(jdbcUrl, username, password);
conn.setAutoCommit(false);
// Get a PGQL connection
PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
pgqlConn.setGraph(graph);
// Execute PGQL Query
String s = "SELECT n.* FROM MATCH (n:Accounts) LIMIT ?";
PgqlPreparedStatement pStmt = pgqlConn.prepareStatement(s, 0, 4 , 2 , -1 , null , null);
pStmt.setInt(1,3);
rs = pStmt.executeQuery();
// Print the results
rs.print();
}
finally {
// close the result set
if (rs != null) {
rs.close();
}
// close the statement
if (pgqlStmt != null) {
pgqlStmt.close();
}
// close the connection
if (conn != null) {
conn.close();
}
}
}
}
>>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "<jdbcUrl>")
>>> pgql_statement = pgql_conn.create_statement()
>>> pgql_conn.set_graph("BANK_GRAPH")
>>> s = "SELECT n.* FROM MATCH (n:Accounts) LIMIT ?"
>>> ps = pgql_conn.prepare_statement(s, timeout=0, parallel=4, dynamicSampling=2, maxResults=-1, matchOptions=None, options=None)
>>> ps.set_int(1,3)
>>> ps.execute_query().print()
+---------------+
| ID | NAME |
+---------------+
| 1 | Account1 |
| 2 | Account2 |
| 3 | Account3 |
+---------------+
例13-4 グループ化と集計を指定したSELECT
問合せの実行
opg4j> var jdbcUrl="jdbc:oracle:thin:@<host_name>:<port>/<db_service>"
opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>");
opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
opg4j> pgqlConn.setGraph("BANK_GRAPH")
opg4j> var pgqlStmt = pgqlConn.createStatement() //create a PGQL Statement
opg4j> String query = "SELECT v1.id, COUNT(v2) AS numTxns "+
...> "FROM MATCH (v1)-[e IS Transfers]->(v2) "+
...> "GROUP BY v1 "+
...> "ORDER BY numTxns DESC "+
...> "LIMIT 3"
opg4j> var resultSet = pgqlStmt.executeQuery(query)
opg4j> resultSet.print() //Prints the query result set
+---------------+
| ID | NUMTXNS |
+---------------+
| 687 | 6 |
| 195 | 5 |
| 192 | 5 |
+---------------+
import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
import oracle.pg.rdbms.pgql.PgqlConnection;
import oracle.pg.rdbms.pgql.PgqlResultSet;
import oracle.pg.rdbms.pgql.PgqlStatement;
/*
* This example shows how to execute a SELECT query with aggregation .*/
public class PgqlExample3
{
public static void main(String[] args) throws Exception
{
int idx=0;
String jdbcUrl = args[idx++];
String username = args[idx++];
String password = args[idx++];
String graph = args[idx++];
Connection conn = null;
PgqlStatement pgqlStmt = null;
PgqlResultSet rs = null;
try {
//Get a jdbc connection
DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
conn = DriverManager.getConnection(jdbcUrl, username, password);
conn.setAutoCommit(false);
// Get a PGQL connection
PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
pgqlConn.setGraph(graph);
// Create a PGQL Statement
pgqlStmt = pgqlConn.createStatement();
// Execute PGQL Query
String query =
"SELECT v1.id, COUNT(v2) AS numTxns "+
"FROM MATCH (v1)-[e IS Transfers]->(v2) "+
"GROUP BY v1 "+
"ORDER BY numTxns DESC";
rs = pgqlStmt.executeQuery(query);
// Print the results
rs.print();
}
finally {
// close the result set
if (rs != null) {
rs.close();
}
// close the statement
if (pgqlStmt != null) {
pgqlStmt.close();
}
// close the connection
if (conn != null) {
conn.close();
}
}
}
}
>>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "<jdbcUrl>")
>>> pgql_statement = pgql_conn.create_statement()
>>> pgql_conn.set_graph("BANK_GRAPH")
>>> query = """
... SELECT v1.id, COUNT(v2) AS numtxns
... FROM MATCH (v1)-[e IS Transfers]->(v2)
... GROUP BY v1
... ORDER BY numtxns DESC
... LIMIT 3
... """
>>> pgql_statement.execute_query(query).print()
+---------------+
| ID | NUMTXNS |
+---------------+
| 687 | 6 |
| 195 | 5 |
| 192 | 5 |
+---------------+
例13-5 PGQLパス問合せの表示
opg4j> var jdbcUrl="jdbc:oracle:thin:@<host_name>:<port>/<db_service>"
opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>");
opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
opg4j> pgqlConn.setGraph("BANK_GRAPH")
opg4j> var pgqlStmt = pgqlConn.createStatement() //create a PGQL Statement
opg4j> String query = "PATH onehop AS ()-[IS transfers]->() "+
...> "SELECT v1.id FROM MATCH (v1)-/:onehop/->(v2) "+
...> "WHERE v2.id = 365"
opg4j> var resultSet = pgqlStmt.executeQuery(query)
opg4j> resultSet.print() //Prints the query result set
+-----+
| ID |
+-----+
| 132 |
| 435 |
| 296 |
| 327 |
| 328 |
| 399 |
| 684 |
| 919 |
| 923 |
| 771 |
+-----+
import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
import oracle.pg.rdbms.pgql.PgqlConnection;
import oracle.pg.rdbms.pgql.PgqlResultSet;
import oracle.pg.rdbms.pgql.PgqlStatement;
/*
* This example shows how to execute a PGQL PATH query.*/
public class PgqlExample4
{
public static void main(String[] args) throws Exception
{
int idx=0;
String jdbcUrl = args[idx++];
String username = args[idx++];
String password = args[idx++];
String graph = args[idx++];
Connection conn = null;
PgqlStatement pgqlStmt = null;
PgqlResultSet rs = null;
try {
//Get a jdbc connection
DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
conn = DriverManager.getConnection(jdbcUrl, username, password);
conn.setAutoCommit(false);
// Get a PGQL connection
PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
pgqlConn.setGraph(graph);
// Create a PGQL Statement
pgqlStmt = pgqlConn.createStatement();
// Execute PGQL Query
String query =
"PATH onehop AS ()-[IS transfers]->() "+
"SELECT v1.id FROM MATCH (v1)-/:onehop/->(v2) "+
"WHERE v2.id = 365";
rs = pgqlStmt.executeQuery(query);
// Print the results
rs.print();
}
finally {
// close the result set
if (rs != null) {
rs.close();
}
// close the statement
if (pgqlStmt != null) {
pgqlStmt.close();
}
// close the connection
if (conn != null) {
conn.close();
}
}
}
}
>>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "<jdbcUrl>")
>>> pgql_statement = pgql_conn.create_statement()
>>> pgql_conn.set_graph("BANK_GRAPH")
>>> query = """
... PATH onehop AS ()-[IS transfers]->()
... SELECT v1.id FROM MATCH (v1)-/:onehop/->(v2)
... WHERE v2.id = 365
... """
>>> pgql_statement.execute_query(query).print()
+-----+
| ID |
+-----+
| 132 |
| 435 |
| 296 |
| 327 |
| 328 |
| 399 |
| 684 |
| 919 |
| 923 |
| 771 |
+-----+
13.7.4.3 PGQLプロパティ・グラフを変更するためのPGQL問合せの実行
PGQL INSERT
、UPDATE
およびDELETE
の各問合せをPGQLプロパティ・グラフに対して実行するには、OPG4J Javaシェル、OPG4Py Pythonシェルを使用するか、JavaまたはPythonアプリケーションを使用します。
グラフに頂点またはエッジを挿入する際に、一意のIDが自動生成されないことに注意してください。このため、キー列値がグラフ・プロパティに存在するか、データベースによって自動生成されるようにする(SEQUENCE
およびTRIGGERS
を使用するか、IDENTITY
列を使用して自動増分機能で実現する)必要があります。
次の例では、2つの新しい頂点を挿入し、2つの頂点間にエッジ関係も追加します。
opg4j> String pgql =
...> "INSERT VERTEX v1 LABELS (Person) PROPERTIES (v1.name= 'ABC', v1.height=1.6, v1.birthdate = to_date('13/06/1963', 'DD/MM/YYYY')) "+
...> " , VERTEX v2 LABELS (Person) PROPERTIES (v2.name= 'XYZ', v2.height=1.75, v2.birthdate = to_date('19/06/1963', 'DD/MM/YYYY')) "+
...> " , EDGE e BETWEEN v1 AND v2 LABELS (friendof) PROPERTIES ( e.meeting_date = to_date('19/06/2021', 'DD/MM/YYYY')) "
pgql ==> "INSERT VERTEX v1 LABELS (Person) PROPERTIES (v1.name= 'ABC', v1.height=1.6, v1.birthdate = to_date('13/06/1963', 'DD/MM/YYYY')) , VERTEX v2 LABELS (Person) PROPERTIES (v2.name= 'XYZ', v2.height=1.75, v2.birthdate = to_date('19/06/1963', 'DD/MM/YYYY')) , EDGE e BETWEEN v1 AND v2 LABELS (friendof) PROPERTIES ( e.meeting_date = to_date('19/06/2021', 'DD/MM/YYYY')) "
opg4j> pgqlStmt.execute(pgql)
$14 ==> false
String pgql =
...> "INSERT VERTEX v1 LABELS (Person) PROPERTIES (v1.name= 'ABC', v1.height=1.6, v1.birthdate = to_date('13/06/1963', 'DD/MM/YYYY')) "+
...> " , VERTEX v2 LABELS (Person) PROPERTIES (v2.name= 'XYZ', v2.height=1.75, v2.birthdate = to_date('19/06/1963', 'DD/MM/YYYY')) "+
...> " , EDGE e BETWEEN v1 AND v2 LABELS (friendof) PROPERTIES ( e.meeting_date = to_date('19/06/2021', 'DD/MM/YYYY')) ";
pgqlStmt.execute(pgql);
>>> pgql = """
... INSERT VERTEX v1 LABELS (Person) PROPERTIES (v1.name= 'ABC', v1.height=1.6, v1.birthdate = to_date('13/06/1963', 'DD/MM/YYYY'))
... , VERTEX v2 LABELS (Person) PROPERTIES (v2.name= 'XYZ', v2.height=1.75, v2.birthdate = to_date('19/06/1963', 'DD/MM/YYYY'))
... , EDGE e BETWEEN v1 AND v2 LABELS (friendof) PROPERTIES ( e.meeting_date = to_date('19/06/2021', 'DD/MM/YYYY'))
... """
>>> pgql_statement.execute(pgql)
False
次の例では、UPDATE
問合せを実行して前述の例で挿入されたエッジ・プロパティを変更してから、SELECT
問合せを使用して更新操作を検証します。
opg4j> String pgql = "UPDATE e SET (e.meeting_date = to_date('12/02/2022', 'DD/MM/YYYY')) "+
...> "FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) "+
...> "WHERE v1.person_id = 27 AND v2.person_id = 28"
pgql ==> "UPDATE e SET (e.meeting_date = to_date('12/02/2022', 'DD/MM/YYYY')) FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) WHERE v1.person_id = 27 AND v2.person_id = 28"
opg4j> pgqlStmt.execute(pgql)
$40 ==> false
opg4j>pgqlStmt.executeQuery("SELECT e.meeting_date FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) WHERE v1.person_id = 27").print()
+-----------------------+
| MEETING_DATE |
+-----------------------+
| 2022-02-12 00:00:00.0 |
+-----------------------+
String pgql ="UPDATE e SET (e.meeting_date = to_date('12/02/2022', 'DD/MM/YYYY')) "+
"FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) "+
"WHERE v1.person_id = 27 AND v2.person_id = 28";
pgqlStmt.execute(pgql);
>>> pgql = """
... UPDATE e SET (e.meeting_date = to_date('12/02/2022', 'DD/MM/YYYY'))
... FROM MATCH (v1:Person)-[e:friendof]->(v2:Person)
... WHERE v1.person_id = 27 AND v2.person_id = 28
... """
>>> pgql_statement.execute(pgql)
False
>>> pgql_statement.execute_query("SELECT e.meeting_date FROM MATCH(v1:Person)-[e:friendof]->(v2:Person) WHERE v1.person_id = 27").print()
+-----------------------+
| MEETING_DATE |
+-----------------------+
| 2022-02-12 00:00:00.0 |
+-----------------------+
DELETE
問合せを使用すると、グラフ内の頂点およびエッジを削除できます。次の例では、DELETE
問合せを実行してグラフのエッジを削除します。
opg4j> pgqlStmt.execute("DELETE e FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) WHERE v.person_id=27")
$14 ==> false
pgqlStmt.execute("DELETE e FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) WHERE v.person_id=27");
>>> pgql_statement.execute("DELETE e FROM MATCH (v1:Person)-[e:friendof]->(v2:Person) WHERE v1.person_id=27")
False
13.7.4.4 PGQLプロパティ・グラフの削除
PGQL DROP PROPERTY GRAPH
文を使用して、PGQLプロパティ・グラフを削除できます。PGQLプロパティ・グラフのすべてのメタデータ表が削除されることに注意してください。
例13-6 PGQLプロパティ・グラフの削除
opg4j> var jdbcUrl="jdbc:oracle:thin:@<host_name>:<port>/<db_service>"
opg4j> var conn = DriverManager.getConnection(jdbcUrl,"<username>","<password>")
opg4j> var pgqlConn = PgqlConnection.getConnection(conn)
opg4j> var pgqlStmt = pgqlConn.createStatement() //create a PGQL Statement
opg4j> pgqlStmt.execute("DROP PROPERTY GRAPH <graph>")
$9 ==> false
import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import oracle.pg.rdbms.pgql.jdbc.PgqlJdbcRdbmsDriver;
import oracle.pg.rdbms.pgql.PgqlConnection;
import oracle.pg.rdbms.pgql.PgqlStatement;
/**
* This example shows how to drop a PGQL property graph.
*/
public class DropPgqlGraph
{
public static void main(String[] args) throws Exception
{
int idx=0;
String jdbcUrl = args[idx++];
String username = args[idx++];
String password = args[idx++];
String graph = args[idx++];
Connection conn = null;
PgqlStatement pgqlStmt = null;
try {
//Get a jdbc connection
DriverManager.registerDriver(new PgqlJdbcRdbmsDriver());
conn = DriverManager.getConnection(jdbcUrl, username, password);
conn.setAutoCommit(false);
// Get a PGQL connection
PgqlConnection pgqlConn = PgqlConnection.getConnection(conn);
// Create PGQL Statement
pgqlStmt = pgqlConn.createStatement();
String query = "DROP PROPERTY GRAPH " +graph;
pgqlStmt.execute(query);
}
finally {
// close the statement
if (pgqlStmt != null) {
pgqlStmt.close();
}
// close the connection
if (conn != null) {
conn.close();
}
}
}
}
>>> pgql_conn = opg4py.pgql.get_connection("<username>","<password>", "jdbc:oracle:thin:@localhost:1521/orclpdb")
>>> pgql_statement = pgql_conn.create_statement()
>>> pgql = "DROP PROPERTY GRAPH <graph>"
>>> pgql_statement.execute(pgql)
False