基于PostgreSQL的圖數(shù)據(jù)庫(kù)AgensGraph簡(jiǎn)介

一 AgensGraph簡(jiǎn)介

AgensGraph 是一個(gè)基于 PostgreSQL 的新一代多模型圖數(shù)據(jù)庫(kù)。它提供圖形分析環(huán)境,用戶可以同時(shí)編寫(xiě)、編輯和執(zhí)行 SQL 和 Cypher 查詢。AgensGraph 帶有 PostgreSQL 兼容性和 PostgreSQL擴(kuò)展,能夠幫助PostgreSQL用戶擺脫數(shù)據(jù)遷移的痛苦,輕松開(kāi)發(fā)提供高級(jí)數(shù)據(jù)分析的服務(wù)。

1.1 AgensGraph特點(diǎn)

  • 1 萬(wàn)物互聯(lián),無(wú)論是蛋白網(wǎng)絡(luò)還是電網(wǎng),圖數(shù)據(jù)庫(kù)是必然需求,標(biāo)準(zhǔn)Cypher圖查詢。
  • 2 運(yùn)維配置同PostgreSQL幾乎一樣,熟悉PG的DBA和開(kāi)發(fā)人員上手容易,開(kāi)發(fā)效率高。
  • 3 支持sql和Cypher混合查詢。兩種查詢可以實(shí)現(xiàn)join操作,從而實(shí)現(xiàn)圖查詢結(jié)果匹配對(duì)應(yīng)業(yè)務(wù),整體結(jié)果輸出,減少后端開(kāi)發(fā)工作。
  • 4 支持csv導(dǎo)入導(dǎo)出,方便rdb數(shù)據(jù)遷移。
  • 5 可以使用PG庫(kù)豐富的其他特性,比如 圖+PotGIS,或者數(shù)據(jù)庫(kù)自己的事務(wù)隔離等等,分布式的話,可以參考pg的分布式方案(個(gè)人認(rèn)為是不改源碼的那種,比如fdw或者citus方案,其他pgxc/xl和gp不適合,因?yàn)檫@個(gè)agens不是插件,是單獨(dú)的改的pg的數(shù)據(jù)庫(kù),插件可以用)。

1.2 AgensGraph vs NoSQL

AgensGraph即支持圖模型,還支持關(guān)系模型,文檔模型,kv模型。


AgensGraph支持多種模型

二 AgnesGraph安裝

安裝和PostgreSQL幾乎一模一樣,詳情如下:

2.1 安裝依賴

 yum install gcc glibc glib-common readline readline-devel zlib zlib-devel flex bison

2.2 創(chuàng)建用戶

[root@zz ~]# useradd agens
[root@zz ~]# chown -R agens.agens /home/agens

2.3 源碼安裝

#下載release
[root@zz ~]#wget https://github.com/bitnine-oss/agensgraph/archive/v2.1.1.tar.gz
#解壓
[root@zz ~]# tar -zxvf v2.1.1.tar.gz
#進(jìn)入目錄安裝
[root@zz ~]# cd agensgraph-2.1.1
[root@zz agensgraph-2.1.1]# ./configure --prefix=/home/agens
[root@zz agensgraph-2.1.1]# make
[root@zz agensgraph-2.1.1]# make install
#安裝contrib的pg擴(kuò)展工具
[root@zz agensgraph-2.1.1]# cd contrib
[root@zz contrib]# make
[root@zz contrib]# make install

2.4 數(shù)據(jù)庫(kù)初始化

2.4.1 設(shè)置環(huán)境變量

[root@zz contrib]# su - agens
[agens@zz ~]$ vi .bashrc
#編輯內(nèi)如如下:
AGHOME=/home/agens
export AGHOME
AGDATA=$AGHOME/data
export AGDATA
PATH=$PATH:$HOME/.local/bin:$HOME/bin:$AGHOME/bin
export PATH

#保存啟用環(huán)境變量
[agens@zz ~]$ source .bashrc
#初始化數(shù)據(jù)庫(kù)
[agens@zz ~]$ initdb -D $AGDATA
#啟動(dòng)數(shù)據(jù)庫(kù)
[agens@zz ~]$ ag_ctl -D $AGDATA
#psql登錄數(shù)據(jù)庫(kù),進(jìn)入我們熟悉的psql環(huán)境
[agens@zz ~]$ psql -d postgres
psql (10.4)
Type "help" for help.

postgres=# 

結(jié)論:和postgresql安裝和操作一模一樣,其他的如登錄授權(quán)的pg_hba.conf和服務(wù)設(shè)置文件postgresql.conf設(shè)置和pg也是一樣的。

三 AgensGraph概念

3.1 AgensGraph數(shù)據(jù)庫(kù)架構(gòu)

AgensGraph是一個(gè)多模型數(shù)據(jù)庫(kù),既支持帶屬性的圖模型,也支持關(guān)系模型。


Agens數(shù)據(jù)庫(kù)

Agens是基于PostgreSQL數(shù)據(jù)庫(kù)的,通過(guò)schema,支持原生的關(guān)系模型,也就是普通的關(guān)系表等;通過(guò)graph,支持圖模型的vertice(頂點(diǎn))和edge(邊)。一句話,在Agens你可以操作關(guān)系表,也可以操作圖。

3.2 圖模型概念

帶屬性的圖模型

頂點(diǎn)(Vertices):一個(gè)實(shí)體一個(gè)頂點(diǎn)。一個(gè)實(shí)體可以有多個(gè)屬性。
邊(Edges):兩個(gè)實(shí)體之間的連接線。當(dāng)試圖刪除頂點(diǎn)時(shí),要先刪除連接該頂點(diǎn)的邊才行(AgensGraph中不允許存在斷邊,也就是邊一定會(huì)有連接的兩個(gè)頂點(diǎn))。
屬性:實(shí)體和邊都可以有多個(gè)屬性。形象舉個(gè)例子,一個(gè)實(shí)體對(duì)應(yīng)關(guān)系表中一行記錄,一個(gè)實(shí)體的屬性代表關(guān)系表中這行記錄的所有字段和值構(gòu)成的鍵值對(duì)。
標(biāo)簽:AgensGraph中有VLABEL ,ELABEL 兩個(gè)對(duì)象,分別定義頂點(diǎn),邊的分組。形象舉個(gè)例子,標(biāo)簽類似與關(guān)系表的表名稱,那么一個(gè)標(biāo)簽分組下的實(shí)體和邊,其屬性的鍵名稱和數(shù)量一致。(ps:理論上是可以不一致,屬性是nosql的json形式,但是,實(shí)際中的圖大部分是關(guān)系表導(dǎo)出,所以實(shí)際中幾乎一致)。

四 AgensGraph練習(xí)

方便后面描述,新建一個(gè)測(cè)試數(shù)據(jù)庫(kù)作圖數(shù)據(jù)庫(kù)的測(cè)試庫(kù)。

[agens@zz ~]$ psql -d postgres
psql (10.4)
Type "help" for help.
#新建測(cè)試庫(kù)
postgres=# create database agens_test;
#切換測(cè)試庫(kù)
postgres=# \c agens_test;

4.1 圖管理

4.1.1 創(chuàng)建

agens_test=# create graph dlxx;

4.1.2 查詢當(dāng)前應(yīng)用圖

agens_test=# SHOW graph_path; 
 graph_path 
------------
 dlxx
(1 row)

4.1.3 設(shè)置當(dāng)前應(yīng)用圖

假設(shè)當(dāng)前應(yīng)用圖為空,可以先設(shè)置一個(gè)應(yīng)用圖,如下:

agens_test=# SHOW graph_path; 
 graph_path 
------------
 
(1 row)

agens_test=# set graph_path='dlxx';
SET
agens_test=# SHOW graph_path; 
 graph_path 
------------
 dlxx
(1 row)

4.1.4 刪除圖

cacsade級(jí)聯(lián)刪除,會(huì)將該圖下的對(duì)象都刪除:

agens_test=# drop graph dlxx cascade;

4.2 標(biāo)簽(Lables)管理

4.2.1 標(biāo)簽創(chuàng)建

#創(chuàng)建頂點(diǎn)標(biāo)簽
agens_test=# CREATE VLABEL person;
CREATE VLABEL
#創(chuàng)建頂點(diǎn)標(biāo)簽,標(biāo)簽friend繼承標(biāo)簽person。
agens_test=# CREATE VLABEL friend inherits (person);
CREATE VLABEL

#創(chuàng)建邊標(biāo)簽
agens_test=# CREATE ELABEL knows;
CREATE ELABEL
agens_test=# CREATE ELABEL live_together;
CREATE ELABEL
#創(chuàng)建邊標(biāo)簽,標(biāo)簽room_mate繼承標(biāo)簽knows和live_together
agens_test=# CREATE ELABEL room_mate inherits (knows, live_together);
CREATE ELABEL

4.2.2 標(biāo)簽刪除

agens_test=# drop ELABEL knows;
ERROR:  cannot drop elabel knows because other objects depend on it
DETAIL:  elabel room_mate depends on elabel knows
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
# 因?yàn)镋LABEL room_mate繼承knows,所以刪除不了??梢酝ㄟ^(guò)兩個(gè)方式刪除
# 方式一
agens_test=# drop ELABEL room_mate;
agens_test=# drop ELABEL knows;
#方式二
agens_test=# drop ELABEL knows cascade;

這些操作其實(shí)都是pg的,一模一樣。

4.3 索引和約束

待補(bǔ)充

4.4 圖查詢

4.4.1 創(chuàng)建圖的連接性

頂點(diǎn)數(shù)據(jù)格式:(variable:label {property: value, ...})
邊數(shù)據(jù)格式:-[variable:label {property: value, ...}]-
最左邊的附加<或最右邊的>用于表示邊的方向

CREATE VLABEL person;
CREATE ELABEL knows;
#name=tom的頂點(diǎn),通過(guò)邊(knows),連接最右邊的name=summer的頂點(diǎn)
CREATE (:person {name: 'Tom'})-[:knows {fromdate:'2011-11-24'}]->(:person {name: 'Summer'});
CREATE (:person {name: 'Pat'})-[:knows {fromdate:'2013-12-25'}]->(:person {name: 'Nikki'});
CREATE (:person {name: 'Olive'})-[:knows {fromdate:'2015-01-26'}]->(:person {name: 'Todd'});
#使用MATCH命令,從Person的頂點(diǎn)標(biāo)簽 選擇name屬性為tom和pat的兩個(gè)頂點(diǎn)
#這兩個(gè)頂點(diǎn)分別設(shè)置代指p和k,創(chuàng)建p-edge-k的圖連接關(guān)系
MATCH (p:Person {name: 'Tom'}),(k:Person{name: 'Pat'}) 
CREATE (p)-[:KNOWS {fromdate:'2017-02-27'} ]->(k);

圖形如下:


示例圖

示例1:查詢與屬性name=‘Tom’的頂點(diǎn)有直接連接關(guān)系的其他標(biāo)簽為person的頂點(diǎn):

MATCH (n:person {name: 'Tom'})-[:knows]->(m:person) RETURN n.name AS n, m.name AS m;
   n   |    m
-------+----------
 "Tom" | "Summer"
 "Tom" | "Pat"
(2 rows)

示例2:查詢與屬性name=‘Tom’的頂點(diǎn)有兩層連接關(guān)系的其他標(biāo)簽為person的頂點(diǎn):

MATCH (p:person {name: 'Tom'})-[:knows]->()-[:knows]->(f:person) RETURN f.name;
  name   
---------
 "Nikki"
(1 row)

示例3:使用union將圖查詢結(jié)果合并輸出:

MATCH (p:person {name: 'Tom'})-[:knows]->(f:person) RETURN f.name
 UNION ALL
MATCH (p:person {name: 'Tom'})-[:knows]->()-[:knows]->(f:person) RETURN f.name;
   name   
----------
 "Summer"
 "Pat"
 "Nikki"
(3 rows)

以上語(yǔ)句可以使用以下等效,注意[r:knows*1..2]寫(xiě)法,1..2代表1級(jí)到2級(jí):

MATCH (p:person {name: 'Tom'})-[r:knows*1..2]->(f:person)
RETURN f.name, r[1].fromdate;
   name   |   fromdate   
----------+--------------
 "Summer" | 
 "Pat"    | 
 "Nikki"  | "2013-12-25"
(3 rows)

在圖數(shù)據(jù)庫(kù)中,典型的查詢是查找位于可變連接長(zhǎng)度的邊-頂點(diǎn)路徑之后的頂點(diǎn)。 邊中使用的* 1..2表示這樣的變長(zhǎng)邊。 其中1是邊的最小長(zhǎng)度,2是最大長(zhǎng)度。
不指定值,默認(rèn)值應(yīng)該是1,就是就一層連接(直接連接關(guān)系,有一個(gè)邊即可達(dá)):

MATCH (p:person {name: 'Tom'})-[r:knows]->(f:person) RETURN f.name;
   name   
----------
 "Summer"
 "Pat"
(2 rows)

指定*,就是有多個(gè)邊可達(dá),都屬于查詢要求:

MATCH (p:person {name: 'Tom'})-[r:knows*]->(f:person) RETURN f.name;
   name   
----------
 "Summer"
 "Pat"
 "Nikki"
(3 rows)

4.5 圖處理(增刪改)

4.5.1 create

CREATE (:person {name: 'Tom'})-[:knows {fromdate:'2011-11-24'}]->(:person {name: 'Summer'});

4.5.2 set

MATCH (:person {name: 'Tom'})-[r:knows]->(:person {name: 'Summer'})
SET r.since = '2009-01-08';

4.5.3 delete

MATCH (n:person {name: 'Pat'}) DETACH DELETE (n);

DETACH DELETE將相關(guān)的頂點(diǎn)和邊一次性全部刪除。類似sql的 cascade,級(jí)聯(lián)刪除,因?yàn)閍gens不允許斷邊存在,刪除了頂點(diǎn),這個(gè)頂點(diǎn)相關(guān)的邊都要?jiǎng)h了,使用DETACH DELETE更常用。

4.5.4 merge

這個(gè)和sql中的insert into on confict do很像,沒(méi)有就插入,有就更新,是個(gè)命令合并語(yǔ)法。
merge的意思是,如果圖中有查詢條件的數(shù)據(jù),等同于match,就是查找。如果圖中沒(méi)有查詢條件的數(shù)據(jù),等同于create,就是創(chuàng)建。
merge就是有就match,沒(méi)有就create的復(fù)合語(yǔ)法。

CREATE VLABEL customer;
CREATE VLABEL

CREATE VLABEL city;
CREATE VLABEL

CREATE (:customer {name:'Tom', city:'santa clara'}),
(:customer {name:'Summer ', city:'san jose'}),
(:customer {name:'Pat', city:'santa clara'}),
(:customer {name:'Nikki', city:'san jose'}),
(:customer {name:'Olive', city:'san francisco'});
GRAPH WRITE (INSERT VERTEX 5, INSERT EDGE 0)

#檢索所有的custome,將city屬性通過(guò)merge語(yǔ)法到city頂點(diǎn)標(biāo)簽。
MATCH (a:customer) MERGE (c:city {name:a.city});
GRAPH WRITE (INSERT VERTEX 3, INSERT EDGE 0)

#原來(lái)city標(biāo)簽是未賦值的,merge之后,屬性值發(fā)生變化。
MATCH (c:city) RETURN properties(c);
        properties         
---------------------------
 {"name": "santa clara"}
 {"name": "san jose"}
 {"name": "san francisco"}
(3 rows)

MERGE可以通過(guò) ON MATCH SET和 ON Create SET修改對(duì)應(yīng)圖中頂點(diǎn)或者邊的屬性。

CREATE (:customer {name:'Todd', city:'palo alto'});

MATCH (a:customer)
MERGE (c:city {name:a.city})
    ON MATCH SET c.matched = 'true'
    ON CREATE SET c.created = 'true';
    
#匹配到的是matched=true,未匹配的會(huì)create,設(shè)置created=true
MATCH (c:city) RETURN properties(c);
                  properties
----------------------------------------------
 {"name": "santa clara", "matched": "true"}
 {"name": "san jose", "matched": "true"}
 {"name": "san francisco", "matched": "true"}
 {"name": "palo alto", "created": "true"}
(4 rows)

4.5.5 事務(wù)隔離

BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
MATCH (a:customer)
MERGE (c:city {name:a.city});
COMMIT;

4.5.6 最短路徑

新建一個(gè)連接,tom指向olive:

MATCH (p:person {name:'Tom'}), (f:person {name:'Olive'}) CREATE (p)-[:knows]->(f);
GRAPH WRITE (INSERT VERTEX 0, INSERT EDGE 1)

新建后的圖更新如下:

示例圖更新

shortestpath方法用于查詢最短路徑,需要制定起點(diǎn),終點(diǎn)的頂點(diǎn),可以通過(guò)-[:knows*1..5]-這只edge的查找深度,比如1-5層連接關(guān)系:

MATCH (p1:person {name: 'Tom'}), (p2:person {name: 'Todd'}),
path=shortestpath((p1)-[:knows*1..5]->(p2)) RETURN path;
                                                                           path                                                                            
-----------------------------------------------------------------------------------------------------------------------------------------------------------
 [person[3.1]{"name": "Tom"},knows[5.5][3.1,3.5]{},person[3.5]{"name": "Olive"},knows[5.3][3.5,3.6]{"fromdate": "2015-01-26"},person[3.6]{"name": "Todd"}]
(1 row)

查詢結(jié)果是:tom到olive到todd,上圖示意符合一致。

4.5.7 sql和圖查詢的混合查詢

構(gòu)建下測(cè)試圖數(shù)據(jù)與關(guān)系表數(shù)據(jù):

CREATE GRAPH bitnine;
CREATE VLABEL dev;
CREATE (:dev {name: 'someone', year: 2015});
CREATE (:dev {name: 'somebody', year: 2016});

CREATE TABLE history (year, event)
AS VALUES (1996, 'PostgreSQL'), (2016, 'AgensGraph'),(2019, 'sssss');

執(zhí)行查詢,查詢圖中年份小于history的年份。圖在agens其實(shí)都是jsonb的nosql格式,可以通過(guò)->>等pg中json,jsonb格式根據(jù)鍵名稱獲取值等函數(shù),詳細(xì)查看pg的jsonb function文檔:
cypher in sql:

SELECT history.*,n->>'name' as name 
FROM history, (MATCH (n:dev) RETURN n) as dev 
WHERE history.year > (n->>'year')::int;
 year |   event    |   name   
------+------------+----------
 2016 | AgensGraph | someone
 2019 | sssss      | someone
 2019 | sssss      | somebody
(3 rows)

sql in cypher:

MATCH (n:dev) WHERE n.year < (SELECT year FROM history WHERE 
event = 'AgensGraph') RETURN properties(n) AS n;
                 n                 
-----------------------------------
 {"name": "someone", "year": 2015}
(1 row)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容