Spanner Graph のトラブルシューティング

このドキュメントでは、Spanner Graph の使用時に発生する可能性のあるエラーについて説明します。エラーの例と推奨される修正方法も示されます。

スキーマのエラー

スキーマの結果は、Spanner グラフを設定してクエリを実行するで使用したデータセットに基づいています。

要素キーは一意である必要があります

エラー メッセージ

Neither the primary keys nor any unique index defined on the property graph element source table `Person` provides the uniqueness guarantee for graph element `Person` belonging to the graph `FinGraph`. You want to redefine the element key columns (`name`) based on the source table's primary keys, or create a unique index on the element's key columns.

エラーの例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (name)
  );

要素キー列に一意のインデックスを作成し、ソーステーブルの主キーに基づいて要素キー列を再定義します。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (id)
  );

または、要素キー列に一意のインデックスを作成します。

CREATE UNIQUE INDEX PersonNameIndex ON Person(name);
CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person KEY (name)
  );

要素の定義の名前は一意である必要があります

エラー メッセージ

Account is defined more than once; use a unique name.

エラーの例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account,
    Person
  )
  EDGE TABLES (
    Account
      SOURCE KEY(owner_id) REFERENCES Person
      DESTINATION KEY(account_id) REFERENCES Account
  );

エッジ定義には一意の名前を使用します。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Account,
    Person
  )
  EDGE TABLES (
    Account AS Owns
      SOURCE KEY(owner_id) REFERENCES Person
      DESTINATION KEY(account_id) REFERENCES Account
  );

ラベル定義はプロパティで一貫している必要があります

エラー メッセージ

The label Entity is defined with different property declarations. There is one instance of this label defined with properties of [id]. Another instance is defined with properties of [name].

エラーの例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person LABEL Entity PROPERTIES (name),
    Account LABEL Entity PROPERTIES (id)
  );

同じラベルで同じプロパティ名のセットを使用する必要があります。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person LABEL Entity PROPERTIES (id, name),
    Account LABEL Entity PROPERTIES (id, name)
  );

プロパティの宣言はプロパティタイプと一致している必要があります

エラー メッセージ

The property declaration of name has type conflicts. There is an existing declaration of type INT64. There is a conflicting one of type STRING.

エラーの例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person PROPERTIES (name),
    Account PROPERTIES (id AS name)
  );
CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person PROPERTIES (name),
    Account PROPERTIES (CAST(id AS STRING) AS name)
  );

プロパティ定義をサブクエリにすることはできません

エラー メッセージ

Property value expression of count cannot contain a subquery.

エラーの例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person PROPERTIES ((SELECT COUNT(*) FROM Person) AS count)
  );

なし。この条件は許可されません。

プロパティの定義は、同じ要素定義内で一貫している必要があります

エラー メッセージ

Property location has more than one definition in the element table Person

エラーの例

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person
      LABEL Person PROPERTIES (country AS location)
      LABEL Entity PROPERTIES (city AS location)
  );

同じプロパティ定義を使用します。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person
      LABEL Person PROPERTIES (country AS location)
      LABEL Entity PROPERTIES (country AS location)
  );

または、別のプロパティ名を割り当てます。

CREATE OR REPLACE PROPERTY GRAPH FinGraph
  NODE TABLES (
    Person
      LABEL Person PROPERTIES (country AS location)
      LABEL Entity PROPERTIES (city AS city)
  );

クエリエラー

クエリ結果は、Spanner Graph の設定とクエリで使用したデータセットに基づいています。

グラフ要素をクエリ結果として返すことはできません

エラー メッセージ

Returning expressions of type GRAPH_ELEMENT is not allowed

エラーの例

GRAPH FinGraph
MATCH (n:Account)
RETURN n;
GRAPH FinGraph
MATCH (n:Account)
RETURN TO_JSON(n) AS n;

プロパティ指定は WHERE 句では使用できません

エラー メッセージ

WHERE clause cannot be used together with property specification

エラーの例

GRAPH FinGraph
MATCH (n:Account {id: 1} WHERE n.is_blocked)
RETURN n.id;

次のいずれかの推奨される修正方法を使用できます。

GRAPH FinGraph
MATCH (n:Account {id: 1})
WHERE n.is_blocked
RETURN n.id;
GRAPH FinGraph
MATCH (n:Account WHERE n.id = 1 AND n.is_blocked )
RETURN n.id;
GRAPH FinGraph
MATCH (n:Account {id: 1, is_blocked: TRUE})
RETURN n.id;

前のステートメントで定義された変数への参照は許可されません

エラー メッセージ

Name 'account_id', defined in the previous statement, can only be referenced in the outermost WHERE clause of MATCH

説明

MATCH パターン内では、前のステートメントで定義された変数への参照は許可されません。グラフクエリでは、前のステートメントで定義された名前は MATCH の最も外側の WHERE 句でのみ使用できます。

エラーの例
GRAPH FinGraph
LET account_id = 1
MATCH (n:Account {id: account_id})
RETURN n.id;
GRAPH FinGraph
LET account_id = 1
MATCH (n:Account)
WHERE n.id = account_id
RETURN n.id;

相関グラフ変数の再定義は許可されません

エラー メッセージ

The name account is already defined; redefining graph element variables in a subquery is not allowed. To refer to the same graph element, use a different name and add an explicit filter that checks for equality.

説明

グラフクエリでは、内部グラフのサブクエリでグラフ要素名を再定義することはできません。このシナリオは、外側のスコープと同じグラフ要素を参照しているか、外側のスコープ名をシャドウする新しいグラフ要素へのバインディングとして解釈される可能性があります。再定義することはできません。

エラーの例

GRAPH FinGraph
MATCH (account:Account)
RETURN account.id AS account_id, VALUE {
  MATCH (account:Account)-[transfer:Transfers]->(:Account)
  RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;
GRAPH FinGraph
MATCH (account:Account)
RETURN account.id AS account_id, VALUE {
  MATCH (a:Account)-[transfer:Transfers]->(:Account)
  WHERE a = account
  RETURN SUM(transfer.amount) AS total_transfer
} AS total_transfer;

クエリのセマンティクスの問題

クエリ結果は、Spanner Graph の設定とクエリで使用するデータセットに基づきます。

WHEREFILTER が異なると、出力結果も異なります

説明

FILTER はステートメントです。 WHERE は、MATCHOPTIONAL MATCH ステートメントの一部として、句です。

最初の例では、WHERE 句で、OPTIONAL MATCH ステートメントに記載されているパターンに制約を追加しています。これは、マッチングが完了した後のフィルタではありません。

2 番目の例では、FILTER ステートメントは一致が完了した後のフィルタです。

問題の例

次の例では、WHEREFILTER が異なるため、出力も異なります。

例 1

GRAPH FinGraph
MATCH (n:Account {id: 7})
OPTIONAL MATCH (m:Account)
WHERE FALSE
RETURN n.id AS n_id, m.id AS m_id;
n_id m_id
7 null

例 2

GRAPH FinGraph
MATCH (n:Account {id: 7})
OPTIONAL MATCH (m:Account)
FILTER FALSE
RETURN n.id AS n_id, m.id AS m_id;

空の結果。

ステートメント間で異なる変数が伝播されると、出力が異なる

説明

グラフクエリ言語では、複数回宣言された変数は、すべての出現で同じグラフ要素を参照します。

例 1 では、id716 の両方の Account ノードはありません。このため、空の結果が返されます。

例 2 では、前のステートメントから名前 n が返されません(id のみが返されます)。したがって、2 番目の MATCH は、id16 である Account ノードを見つけます。

問題の例

次の例では、ステートメント間で異なる変数が伝播されるため、出力が異なります。

例 1

GRAPH FinGraph
MATCH (n:Account {id: 7})
RETURN n

NEXT

MATCH (n:Account {id: 16})
RETURN n.id AS n_id;

空の結果。

例 2

GRAPH FinGraph
MATCH (n:Account {id: 7})
RETURN n.id AS id

NEXT

MATCH (n:Account {id: 16})
RETURN n.id AS n_id;
n_id
16

LIMIT 以外のステートメントが続く場合、ORDER BY は無視されます。

説明

グラフクエリ言語では、次のいずれかに該当しない限り、ORDER BY ステートメントは無視されます。

  • ORDER BY は最後のステートメントです。
  • ORDER BY の直後は LIMIT です。

例 1 では、LIMITORDER BY の直後に配置されていません。最後の LIMIT は分離されます。つまり、ORDER BY はエンジンによって無視されます。

例 2 では、LIMITORDER BY の直後に続くため、ORDER BY が適用されます。

問題の例

以下の例では、出力が異なるため、ORDER BY ステートメントは、指定されていない場合は無視されます。LIMIT

例 1

GRAPH FinGraph
MATCH (n:Account)
ORDER BY n.id DESC
RETURN n.id
LIMIT 3;
n_id
7

例 2

GRAPH FinGraph
MATCH (n:Account)
ORDER BY n.id DESC
LIMIT 3
RETURN n.id;
n_id
20

エッジパターンが異なると出力が異なる

説明

エラーの例で使用されているデータセットでは、ANY 方向エッジ パターンがグラフ内の各 Transfers エッジと 2 回一致しています。

例 1 では、Account(id=x) から Account(id=y) への Transfers エッジが、次のように 2 回一致できます。

  • n= Account(id=x), m= Account(id=y)
  • n= Account(id=y), m= Account(id=x)

例 2 では、n=Account(id=x)、m=Account(id=y) で、一致は 1 つだけです。

その結果、例 1 のクエリは 10 を返し、例 2 のクエリは 5 を返します。

問題の例

次の例では、異なるエッジパターンが使用されているため、出力が異なります。

例 1

GRAPH FinGraph
MATCH (n:Account)-[:Transfers]-(m:Account)
RETURN COUNT(*) AS num_transfer_edges;
num_transfer_edges
10

例 2

GRAPH FinGraph
MATCH (n:Account)-[:Transfers]->(m:Account)
RETURN COUNT(*) AS num_transfer_edges;
num_transfer_edges
5

ミューテーション エラー

ミューテーション結果は、Spanner Graph の設定とクエリに使用したデータセットに基づきます。

ソースノードが見つからず、外部キー制約に違反している

エラー メッセージ

Parent row for row [...] in table AccountTransferAccount is missing. Row cannot be written.

説明

AccountTransferAccount エッジテーブルは INTERLEAVED INTO PARENT Account node テーブルです。Transfer エッジを作成するには、その親 Account ノードがすでに存在している必要があります。

エラーの例

INSERT INTO AccountTransferAccount (id, to_id, create_time, amount)
VALUES (100, 1, PENDING_COMMIT_TIMESTAMP(), 200);

まず先頭の Account ノードを作成してから、Transfer エッジを作成します。

宛先ノードが外部キー制約に違反している

エラー メッセージ

Foreign key constraint FK_TransferTo is violated on table AccountTransferAccount. Cannot find referenced values in Account(id)

説明

AccountTransferAccount テーブルは、FK_TransferTo という ForeignKey を介して Accounttable を参照します。Transfer エッジを作成するには、参照されるテーリング ノード Account ノードがすでに存在している必要があります。

エラーの例

INSERT INTO AccountTransferAccount (id, to_id, create_time, amount)
VALUES (1, 100, PENDING_COMMIT_TIMESTAMP(), 200);

最初に末尾の Account ノードを作成し、次に Transfer エッジを作成します。

親のないアウトバウンド エッジが親子関係に違反している

エラー メッセージ

Integrity constraint violation during DELETE/REPLACE. Found child row [...] in table AccountTransferAccount

説明

AccountTransferAccount エッジテーブルは INTERLEAVED INTO PARENT Account ノードテーブルであり、削除する Account ノードには送信エッジが接続されています。

エラーの例

DELETE FROM Account WHERE id = 1;

まずすべての送信 Transfer エッジを削除してから、Account ノードを削除します。または、INTERLEAVEON DELETE CASCADE を定義し、Spanner でエッジを自動的に削除します。

親のないインバウンド エッジが親子関係に違反しています

エラー メッセージ

Foreign key constraint violation when deleting or updating referenced row(s): referencing row(s) found in table AccountTransferAccount

説明

AccountTransferAccount エッジ テーブルは ForeignKey を介して Account ノード テーブルを参照し、削除する Account ノードには引き続き受信エッジが接続されています。

エラーの例

DELETE FROM Account WHERE id = 1;

まず、受信側の Transfer エッジをすべて削除してから、Account ノードを削除します。または、ForeignKeyON DELETE CASCADE を定義し、Spanner でエッジを自動的に削除します。