排解 Spanner Graph 問題

本文說明您在使用 Spanner Graph 時可能會遇到的錯誤。並提供錯誤示例和建議的修正方式。

如果您在參閱本疑難排解指南後仍需要進一步支援,請參閱「取得支援」一文。

結構定義錯誤

結構定義結果會根據「設定及查詢 Spanner Graph」一文中使用的資料集。

元素鍵必須保證唯一性

錯誤訊息

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 陳述式中描述的模式新增額外限制。這不是比對完成後的篩選器。

在第二個範例中,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 中,沒有 Account 節點的 id 同時是 716。因此,系統會傳回空白結果。

在範例 2 中,系統不會從前一個陳述式傳回名稱 n (只會傳回 id)。因此,第二個 MATCH 會找出 Account 節點,其 id16

問題範例

由於不同變數會在各個陳述式之間傳播,因此以下範例的輸出結果不同。

範例 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 中,LIMIT 並未緊接在 ORDER BY 後方,最終 LIMIT 會分開。也就是說,引擎會忽略 ORDER BY

在範例 2 中,ORDER BY 適用於 LIMIT 緊接在 ORDER BY 後方。

問題範例

在範例 1 中,如果未搭配 LIMIT 使用 ORDER BY 陳述式,系統會忽略該陳述式,因此以下範例的輸出結果會有所不同。

範例 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 邊緣配對兩次。

在範例 1 中,從 Account(id=x)Account(id=y)Transfers 邊緣可比對兩次,如下所示:

  • 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 中的查詢會傳回 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_TransferToForeignKey 參照 Accounttable。如要建立 Transfer 邊緣,所參照的尾端節點 Account 節點必須已存在。

錯誤示例

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

請先建立尾隨帳戶節點,再建立 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 節點。或者,您也可以為 INTERLEAVE 定義 ON 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 節點。或者,您也可以為 ForeignKey 定義 ON DELETE CASCADE,讓 Spanner 自動刪除這些邊緣。