這世上充斥著各種人事物以及其中錯綜複雜的關係。以公司為例子來看好了,有內部組織的上下(左右)關係,部門與部門間的合作關係,業務間的交流關係,甚至是與外部其他公司之間的競合關係。這些「關係」本身都是相當重要的資料,如果今天我想要快速的取得我想要的資料並了解他們之間的關係,該怎麼樣呈現一個這樣的概念呢?
今天想跟大家一起看一個有趣的資料庫類型,叫做Graph Database(圖形資料庫)。
首先,資料庫有分幾種。譬如說一般我們較常見的大概會是Relational Database(一般俗稱SQL資料庫),資料儲存的方式是有Columns跟Rows(就像表格)。相對的另外還有所謂的NoSQL (Not Only SQL)的資料庫,資料可以以Key/Value pair(就像Python的dictionary)形成一個document(譬如說關於單一User的各種資料是一個document)的方式儲存。
今天要來看的Graph Database也是屬於NoSQL的資料庫,但是儲存資料的方式跟上述的很不同。
舉個例來說,我們有看過連續劇中經常會出現的人物關係圖吧👇?
每個人物可能會跟其他的人物有某種的關係存在(譬如說兄妹關係,小老婆關係😅等等...)。
基本上Graph Database就是這樣的一個概念。
除了資料(在這個例子中就是人物)本身,Graph Databse同時也儲存資料跟資料之間的關係。重點就是,資料跟資料之間的關係跟資料本身有同等的重要性!
今天假設在上面的人物關係圖中,我想要知道誰跟誰有【臉互換】的關係🧑↔👨,由於我們已經將該關係儲存在資料庫中,想像我可以利用下面的方式來做一個Query(資料庫的查詢):
(人)<- [臉互換] -> (人)
找出符合上述的「人」
然後就可以拿到「織田健司」跟「高志龍」😎 的話應該很酷吧?
Graph Database其實是最直覺,且接近現實生活的一種資料的呈現。往往我們在白板上做討論時是不是也會畫箭頭畫來畫去出類似的圖呢?因為我們真的很在意「關係」!
OK,大概對Graph Database有個基本的概念,接下來我們要介紹一個Graph Database的工具,名為:Neo4j。透過一些實際的操作讓我們更能理解Graph Database的優點。
Neo4j
Neo4j是一個Graph Database管理系統,開發這套系統的公司的名字也叫Neo4j。
桌機版的安裝請參考:
也有雲端版的可以使用:
當然今天主要我們還是著重在概念,所以就不做介面的詳細介紹。有興趣可以參照官網。
接下來的部分我們要來看一些例子。這裡附上一份產生原始資料的指令檔案。在程式中執行這些指令就可以產生我們要的資料。或是將檔案名改成.cypher(譬如init.cypher)就可以在介面上直接執行整個檔案的指令。
檔案裡的資料是關於電影跟演員。譬如某某人演出某某電影,或是導演某某電影等。
現在我有一個這樣的query:
MATCH (p:Person)-[]->(m:Movie) RETURN p,m LIMIT 10
在Neo4j的介面執行後就會跳出下面的結果:
是不是蠻美的?這個是Neo4j的資料視覺呈現,跟一般我們看到的資料很不一樣吧?
這裡可以清楚的看到,譬如說在The Matrix(駭客任務)及The Matrix Reloaded(駭客任務:重裝上陣)這兩部電影中,Lana Wachowski 跟Andy Wachowski都具有Directed(執導)的關係。而Keanu Reeves(基諾李維)則是都具有Acted in(演出)的關係。
Neo4j用的query格式叫做Cypher Query Language,或稱CQL。
MATCH (p:Person)-[]->(m:Movie) RETURN p, m LIMIT 10
剛剛看到的這個query的意思是說「給我任何十筆關於人跟電影的資料以及他們所有的相關性」。稍微詳細看每個部分:
MATCH:找出符合的資料
(p:Person) :p是variable,Person是資料的類型。
-[]-> :代表的是任何關係
(m:Movie):m是variable,Movie是資料類型。
RETURN p, m:回傳p跟m這兩個variable,也就是給我人(Person)跟電影(Movie)
LIMIT 10:回傳上限是十筆資料
在Neo4j中,最重要的要素有三個:
Node:代表資料本身,在剛剛的圖中我們看到的各個圓型圖(人物跟電影)就是Node。而至於是Person還是Movie,這部分稱之為Node Label。
Relationships:箭頭的部分就是Relationships(注意它是單向的)。例子中我們看到幾種不同的關係像是ACTED_IN, DIRECTED, PRODUCED...代表該人物跟電影之間的關聯。
Properties:資料的內容。譬如說Person可以有name, age這些properties。Movie可以有title(電影名),released date(上演日期)等等。另外,Relationships也是可以有Property的。譬如在ACTED_IN的關係上可以有出演的角色(Role)。
Cypher Query使用的語法相當直覺,不用刻意去記也大致上讀的出來它的意思。參考下面例子:
MATCH (nineties:Movie)<-[rel:ACTED_IN]-(actors:Person)
WHERE nineties.released >= 1990 AND nineties.released < 2000
RETURN nineties, actors
LIMIT 50
乍看之下好像很複雜...但是仔細看的話就會發現其實蠻單純的。這個Query的意思:「找出所有90年代的電影跟它們的演員,上限50。」
產生出來的圖像:
到這裡,大家應該感受到Graph Database的魅力了吧?Graph Database具有相當大的自由度讓我們可以儲存並搜尋資料之間的複雜關聯。
Python與Neo4j互動
除了在Neo4j的介面上執行Query之外,我們也可以利用Python來跟Graph Database的server做程式間(programmatically)的互動。Neo4j提供了Python的library讓我們方便的做到這一點。
安裝如下:
pip install neo4j
當我們啟動桌上機的Neo4j時,就可以用網址(neo4j://localhost:7687)連到在我們本機上的server,並利用幾行簡單的code來執行資料庫的操作,參考下面的Code:
這裡簡單來說:
建立一個Graph Database的driver物件(Driver物件負責與Database連結溝通,較詳細的說明可以參考這裡)。
定義CQL的query字串。例子中是要找出10筆演員跟演出的電影。
接著利用driver物件產生一個Session,並執行Query。
用for loop將取得的結果一一印出。
小結
今天快速的跟大家介紹了一下:
什麼是Graph Database
Neo4j Graph Database的工具
Cypher Query Language的寫法
如何利用Python來執行Neo4j的Query
直覺易懂,以及極大的靈活度是Graph Database的強項。相信我們在日常生活中多多少少都有應用到類似(把事物連來連去)的概念吧?如果今後有需要資料庫來儲存這一類資料的時候,或許可以參考一下Graph Database,應該是一個蠻有趣的選項喔 😉。
Comments