全部產品
Search
文件中心

PolarDB:PolarDB圖資料庫快速入門

更新時間:Jul 18, 2025

圖資料庫(Graph Database)用於儲存圖資料,適合處理社交網路、知識圖譜等複雜關係。使用圖查詢語言(如Cypher、Gremlin)進行操作。PolarDB相容OpenCypher文法,支援建立、查詢、更新和刪除圖資料,包括模式比對、過濾、MERGE避免重複、視覺化檢視等功能,簡化圖資料的管理和應用。

前提條件

支援的PolarDB PostgreSQL版的版本如下:

  • PostgreSQL 16(核心小版本2.0.16.8.3.0及以上)

  • PostgreSQL 15(核心小版本2.0.15.12.4.0及以上)

  • PostgreSQL 14(核心小版本2.0.14.12.24.0及以上)

說明

您可在控制台查看核心小版本號碼,也可以通過SHOW polardb_version;語句查看。如未滿足核心小版本要求,請升級核心小版本

基本概念

  • 圖(Graph):圖是由節點和邊組成的資料結構。例如,社交網路就是一個典型的圖,其中每個人都是一個節點,他們之間的關係(如朋友、家人、同事等)就是邊。

    image

  • 節點(Node):節點是圖資料庫中的基本元素,表示資料庫中的實體。節點可以具有屬性,用於儲存與實體相關的資訊。例如,在一個社交網路中,節點可以表示使用者、公司、組織等實體。

  • 邊(Edge):邊是串連節點的關係。邊可以具有權重、方向等屬性,用於表示關係的強度和方向。例如,在一個社交網路中,邊可以表示使用者之間的關注、好友、粉絲等關係。

  • 標籤(Label):標籤是一種用於標識節點或邊的分類或屬性。標籤協助您語義化資料,以便更容易地進行查詢和理解。例如,在社交網路中,節點的分類可以是人(Person),或公司(Company),邊的標籤可以是認識(Knows)或工作與(WorkIn)等。

  • 屬性圖:如果節點包含屬性(包含有關主題的詳細資料)或邊包含屬性(關係的詳細資料),則稱為屬性圖。以下為一個同事關係的屬性圖,節點和邊上都帶有相關的屬性:

    image

  • 圖資料庫(Graph Database):是一種特殊的資料庫,使用圖來儲存資料,節點(Node)表示實體,邊(Edge)表示關係。非常適合處理複雜的關係資料,如社交網路、信任網路、知識圖譜等。

    圖資料庫使用圖查詢語言(Graph Query Language)查詢資料,如Cypher、Gremlin等。PolarDB相容OpenCypher文法。OpenCypher是Cypher的一個開源子集,其大部分特性可以認為等同於Cypher。

模式

屬性

在Cypher語言中,使用一對花括弧{}來表示屬性。屬性由索引值對(Key-Value)組成,類似於常見的JSON結構。鍵名為一個字串,屬性值可以是字串、數值,也可以是數組。例如,{name: 'Reeves'}表示名字叫Reeves

節點

在Cypher語言中,使用一對括弧()來表示節點。以下是一些節點表示的樣本:

()
(matrix)
(:Movie)
(matrix:Movie)
(matrix:Movie {title: 'The Matrix'})
(matrix:Movie {title: 'The Matrix', released: 1997})

其中:

  • 最簡單的形式(),表示一個匿名且未表徵的節點。

  • 若需在其他位置引用該節點,可以添加一個變數,例如:(matrix)。變數僅適用於單個語句,在其他語句中則可能具有不同或無意義的含義。

  • :Movie 模式聲明節點的標籤。這允許我們限制模式,從而防止其匹配其他標籤的節點。

  • {title: 'The Matrix'}聲明節點的屬性,例如,屬性可用於儲存資訊或限制模式。

在Cypher語言中,使用一對短劃線--表示無向邊,使用一端帶有箭頭 <---->表示有向邊。方括號運算式[...]可用於添加詳細資料,包括變數、屬性和類型資訊。以下是一些邊表示的樣本:

--
-->
-[role]->
-[:ACTED_IN]->
-[role:ACTED_IN]->
-[role:ACTED_IN {roles: ['Neo']}]->

其中:

  • --表示一個匿名的無向邊。

  • -->表示一個匿名的有向邊。

  • 可以定義一個變數(例如,role),以便在語句的其他地方使用。

  • 關係的標籤(例如,:ACTED_IN)類似於節點的標籤。

  • 屬性(例如,roles: ['Neo'])與節點屬性定義方法一致。

樣本

以下通過一個簡單的樣本展示PolarDB中圖的基本使用方法。樣本資料為一個基礎的電影資料庫,涵蓋了演員及電影的相關資訊。

建立外掛程式

請使用高許可權帳號執行如下語句,建立高許可權帳號請參考建立資料庫帳號

CREATE EXTENSION age;

設定資料庫

對於每次串連,都需要將ag_catalog添加到search_path以簡化查詢,並通過get_cypher_keywords函數實現外掛程式的載入:

說明

使用Data Management(Data Management)用戶端設定search_path時,可能會存在相容性問題,您可使用PolarDB-Tools執行相關語句。

SET search_path = ag_catalog, "$user", public;
SELECT * FROM get_cypher_keywords() limit 0;

強烈建議使用高許可權帳號設定資料庫參數,以永久載入外掛程式,從而在每次串連時無需重複執行上述操作,以簡化使用流程。

ALTER DATABASE <dbname> SET search_path = "$user", public, ag_catalog;
ALTER DATABASE <dbname> SET session_preload_libraries TO 'age';

允許普通使用者使用AGE

ag_catalog模式為普通使用者授予USAGE許可權。

GRANT USAGE ON SCHEMA ag_catalog TO <username>;

如普通使用者只是RW使用者,需要額外授予建立表的CREATE許可權。

GRANT CREATE ON DATABASE <dbname> TO <username>;

查詢結構

PolarDB中的Cypher查詢是通過調用ag_catalog中的一個名為cypher的函數構建的,該函數返回一個SETOF records。以下是一個典型的查詢樣本:

SELECT * FROM cypher('graph_name', $$
/* 在此處編寫 Cypher 查詢 */
$$) AS (result1 agtype, result2 agtype);

其中,graph_name是圖的名稱,/*  */內部分可使用實際Cypher查詢進行替代。

建立圖

在使用圖之前,首先需要進行圖的建立。建立圖使用位於ag_catalog命名空間中的create_graph函數。

文法如下

SELECT create_graph('<graph_name>');

樣本

建立一個名為moviedb的圖。

SELECT create_graph('moviedb');

插入資料

使用以下SQL語句向moviedb圖中插入樣本資料:

SELECT * FROM cypher('moviedb', $$
  CREATE (matrix:Movie {title: 'The Matrix', released: 1997})
  CREATE (cloudAtlas:Movie {title: 'Cloud Atlas', released: 2012})
  CREATE (forrestGump:Movie {title: 'Forrest Gump', released: 1994})
  CREATE (keanu:Person {name: 'Keanu Reeves', born: 1964})
  CREATE (robert:Person {name: 'Robert Zemeckis', born: 1951})
  CREATE (tom:Person {name: 'Tom Hanks', born: 1956})
  CREATE (tom)-[:ACTED_IN {roles: ['Forrest']}]->(forrestGump)
  CREATE (tom)-[:ACTED_IN {roles: ['Zachry']}]->(cloudAtlas)
  CREATE (robert)-[:DIRECTED]->(forrestGump)
$$) AS (result1 agtype);

其中,包含了6個節點,其中3個的標籤為電影(Movie),3個為人員(Person)。3條邊,其中2條邊的標籤為表演(ACTED_IN),一條邊為導演(DIRECTED)。關係圖如下所示:

image

查詢資料

資料查詢

在Cypher中,使用MATCH+RETURN這兩個關鍵字實現資料的查詢。其中:

  • MATCH實現模式比對,用於尋找與指定模式相同的內容。

  • RETURN關鍵字指定希望從Cypher查詢返回的值或結果。

文法如下

SELECT * FROM cypher('graph_name', $$
  MATCH <patterns>
  RETURN <variables>
$$) AS (result1 agtype);

樣本

  • 尋找包含Movie標籤的所有節點。

    SELECT * FROM cypher('moviedb', $$
      MATCH (m:Movie)
      RETURN m
    $$) AS (result1 agtype);
  • 尋找標籤為ACTED_IN的串連PersonMovie的邊。

    SELECT * FROM cypher('moviedb', $$
      MATCH (:Person)-[r:ACTED_IN]->(:Movie)
      RETURN r
    $$) AS (result1 agtype);

資料過濾

當在圖中進行模式比對並僅需返回感興趣的資料子集時,可以使用WHERE子句。該子句允許通過布林運算式對資料子集進行過濾。

樣本

  • 查詢標題為The Matrix的所有電影。

    SELECT * FROM cypher('moviedb', $$
      MATCH (m:Movie)
      WHERE m.title = 'The Matrix'
      RETURN m                     
    $$) AS (result1 agtype);
  • 查詢標題為Forrest Gump的所有演員。

    SELECT * FROM cypher('moviedb', $$
      MATCH (p:Person)-[:ACTED_IN]->(m)
      WHERE m.title = 'Forrest Gump'
      RETURN p
    $$) AS (result1 agtype);
  • 查詢發布時間晚於2000年的電影的演員。

    SELECT * FROM cypher('moviedb', $$
      MATCH (p:Person)-[:ACTED_IN]->(m)
      WHERE m.released > 2000
      RETURN p, m
    $$) AS (result1 agtype, result2 agtype);

建立節點或邊

在Cypher中,可以使用關鍵字CREATE建立一個全新的節點或邊。

文法如下

SELECT * FROM cypher('<graph_name>', $$
  CREATE <patterns>
$$) AS (result1 agtype);

樣本

  • 建立一個標籤為Person的節點,其中,屬性的名字叫Tom Tykwer,出生時間為1965

    SELECT * FROM cypher('moviedb', $$
      CREATE (:Person {name: 'Tom Tykwer', born: 1965})
    $$) AS (result1 agtype);
  • 建立一個Person Tom Tykwer和電影Cloud Atlas的邊,表示Tom Tykwer導演了電影Cloud Atlas

    SELECT * FROM cypher('moviedb', $$
      MATCH (p:Person), (m:Movie)
      WHERE p.name='Tom Tykwer' AND m.title='Cloud Atlas'                 
      CREATE (p)-[:DIRECTED]->(m)
    $$) AS (result1 agtype);

使用MERGE避免插入重複資料

當相同的CREATE 語句執行多次時,將插入多條重複的資料。為避免此類重複資料的產生,可使用MERGE關鍵字進行插入。MERGE進行選擇或插入操作,首先會檢查資料是否已存在於資料庫中。如果資料存在,則會原樣返回該資料,或者對現有的節點或關係進行相應的更新。如果資料不存在,Cypher將根據指定的資訊進行建立。

文法如下

SELECT * FROM cypher('<graph_name>', $$
  MERGE <patterns>
$$) AS (result1 agtype);

樣本

  • 建立一個標籤為Person的節點,其中,屬性的名字叫Tom Cruise,出生時間為1962

    SELECT * FROM cypher('moviedb', $$
      MERGE (:Person {name: 'Tom Cruise', born: 1962})
    $$) AS (result1 agtype);
  • 建立Tom HanksTom Cruise的邊,表示朋友關係。

    SELECT * FROM cypher('moviedb', $$
      MATCH (t1:Person),(t2:Person)
      WHERE t1.name='Tom Hanks' AND t2.name='Tom Cruise'                 
      MERGE (t1)-[:FRIEND]-(t2)
    $$) AS (result1 agtype);

更新

對於資料中已經存在節點或關係,可以通過匹配所需尋找的模式修改其屬性,並使用SET關鍵字來添加或更新屬性以完成此操作。

文法如下

SELECT * FROM cypher('<graph_name>', $$
  MATCH <patterns>
  SET <property>
  RETURN <variable>
$$) AS (result1 agtype);

樣本

  • 將Person Tom Tykwer出生年份改為1970年。

    SELECT * FROM cypher('moviedb', $$
      MATCH (p:Person {name: 'Tom Tykwer', born: 1965})
      SET p.born = 1970
      RETURN p
    $$) AS (result1 agtype);
  • 為Person Tom Tykwer添加一個性別屬性為male

    SELECT * FROM cypher('moviedb', $$
      MATCH (p:Person {name: 'Tom Tykwer', born: 1970})
      SET p.gender = 'male'
      RETURN p
    $$) AS (result1 agtype);

刪除

在Cypher中,使用DELETE關鍵字來刪除節點和邊。

刪除邊

刪除邊需要使用MATCH關鍵字找到符合模式的邊,然後使用DELETE關鍵字進行刪除。

文法

SELECT * FROM cypher('<graph_name>', $$
  MATCH <patterns>
  DELETE <variable>
$$) AS (result1 agtype);

樣本

刪除Person Tom Tykwer和電影Cloud Atlas的導演邊關係。

SELECT * FROM cypher('moviedb', $$
  MATCH (p:Person)-[r:DIRECTED]->(m:Movie)
  WHERE p.name='Tom Tykwer' AND m.title='Cloud Atlas'                 
  DELETE r
$$) AS (result1 agtype);

刪除節點

刪除節點,同樣需要使用MATCH關鍵字找到合格節點,然後使用DELETE關鍵字進行刪除。

文法

SELECT * FROM cypher('<graph_name>', $$
  MATCH <patterns>
  DELETE <variable>
$$) AS (result1 agtype);

樣本

刪除Person Tom Tykwer

SELECT * FROM cypher('moviedb', $$
  MATCH (p:Person {name: 'Tom Tykwer', born: 1970})              
  DELETE p
$$) AS (result1 agtype);

刪除節點及邊

當節點存在相應的邊時,不允許直接刪除該節點。可以使用DETACH DELETE文法刪除該節點的邊關係,並刪除當前節點。

文法

SELECT * FROM cypher('<graph_name>', $$
  MATCH <patterns>
  DETACH DELETE <variable>
$$) AS (result1 agtype);

樣本

刪除Person Tom Hanks以及其關聯的邊。

SELECT * FROM cypher('moviedb', $$
  MATCH (p:Person {name: 'Tom Hanks', born: 1956})              
  DETACH DELETE p
$$) AS (result1 agtype);

刪除屬性

當不再需要節點或邊的屬性時,可以使用REMOVE關鍵字刪除該屬性。

文法

SELECT * FROM cypher('<graph_name>', $$
  MATCH <match_pattern>
  REMOVE <property>
$$) AS (result1 agtype);

樣本

刪除電影Cloud Atlasreleased屬性。

SELECT * FROM cypher('moviedb', $$
  MATCH (m:Movie {title: 'Cloud Atlas', released: 2012})              
  REMOVE m.released
  RETURN m
$$) AS (result1 agtype);

視覺化檢視

使用AGE專案提供圖資料視覺化工具,可將查詢結果進行圖形化的表達。詳情請參考視覺化檢視

image