圖數據庫本身屬於NoSql數據庫中的一種,是基於數學中圖論實現的一種數據庫。不同於傳統的關系型數據庫將數據存在庫表字段中,圖數據庫將數據和數據之間的關系存在節點和邊中,在圖數據庫中這被稱作“節點”和“關系”。沒有了庫表字段的概念,相當於是把數據存在了一張大寬表中。傳統數據庫的一些特性如CRUD、處理事務的能力在圖數據庫中也都支持。
這里需要澄清一個概念:圖數據庫並不是前端展示用的數據庫,它不是用來畫圖的。相反,它是用來存儲數據用的,以圖的節點和邊的方式來存儲數據。而前端展現需要用一些前端展示工具,例如D3、ECharts等來實現。
本文將以neo4j為例來介紹圖數據庫的使用。neo4j是由Java實現的開源NoSql圖數據庫,是圖數據庫中較為流行的一款。它提供了完整的數據庫特性,包括ACID事務的支持、集群支持、備份與故障轉移等(部分功能例如集群支持只有在neo4j企業版中才有,社區版不支持)。
在筆者看來,圖數據庫最大的優勢是體現在對數據關系的檢索上。如果數據之間的關系很復雜,數據存在了多張表中,還有一些中間表的存在的話,傳統數據庫想要查詢一些數據得通過各種聯表操作才做得到,sql會寫得很復雜,不利於維護,同時性能也不高。而圖數據庫僅僅通過簡單的一句cypher語句便可實現查詢功能(cypher語句是neo4j的執行語句,類似於關系型數據庫中的SQL),同時執行速度也會快很多(書中所說是能夠實現毫秒級響應,但通過筆者實測其實並沒有這么誇張。neo4j是將數據存在內存中的,對硬件有一定要求。所以數據越來越多的情況下,同時也有事務的因素,查詢速度也會變慢)。
圖數據庫也支持查詢一些復雜的關系。例如某節點周圍一級的關系節點有哪些,二級的關系又有哪些。拿社交網絡來舉例,假如我現在要實現一個查詢某人可能認識的人有哪些的功能。那么這個功能翻譯成cypher就是:查詢這個人A的周圍一圈認識的人的集合B中,所有B周圍一圈人中和A沒有交集的人。這個用cypher語句是能寫出來的,同時也不會太復雜。
neo4j的下載安裝不做過多說明,官網上都可以下載,另外在微雲數聚網站上也可以下載(筆者學習所使用的參考書籍正是張幟老師主編的《Neo4j權威指南》,他所創辦的微雲數聚公司也一直專注於研究圖數據庫技術及其應用)。
啟動neo4j成功后,可用瀏覽器打開網址:http://localhost:7474/,就可以看到neo4j的操作界面了,如下圖所示。在最上面的輸入框就可以輸入cypher語句來操作數據了。
簡單的一些語法例如:<1>創建節點的語句:create(n:Person { name: 'Robert Hou', job: 'programmer'}),將會生成一個帶有標簽和屬性的節點。
<2>創建關系的語句:match (a {name:'RobertHou'}), (b {name:'Lenovo'}) create(a)-[:HAS]->(b),將會創建一條關系連接兩個節點。
同時cypher也支持sql中的一些關鍵字查詢,例如:order by、union、limit等;聚集函數也同樣支持。
比較有意思的語法是neo4j中支持搜索最短路徑和全部路徑的功能。只要輸入起止節點,調用shortestPath和allShortestPaths方法就可以得到想要的結果了。下圖是neo4j中一個電影的官方例子。節點有演員、導演和電影等。導演導演了某部電影,演員參演了某部電影。
<3>查詢兩點之間的全部路徑:match (Al:Person {name: 'Al Pacino'}),(Kevin:Person {name: 'Kevin Bacon'}), p = allShortestPaths((Al)-[*..15]-(Kevin))return p
可以看到Al節點到Kevin節點的全部路徑有兩條。
<4>查詢兩點之間的最短路徑:match (Al:Person {name: 'Al Pacino'}),(Kevin:Person {name: 'Kevin Bacon'}), p = shortestPath((Al)-[*..15]-(Kevin))return p
可以看到Al節點到Kevin節點的最短路徑變成了一條。
其他的語法可以參考其他文章。本文不做過多贅述。同時,neo4j和spring的集成可以參考筆者的另一篇文章《Neo4j+D3展現的應用實例》。需要注意的是Spring-Data-Neo4j庫不支持jdk8以前的版本,相關的jar包版本和neo4j的版本號也要兼容,同時也要注意包可能存在沖突的問題。
neo4j也支持事務,在java中的寫法大致類似於下面這樣:
-
try {
-
Tranction tx = graphDatabaseService.beginTx() {
-
//和圖數據庫的交互語句
-
tx.success();
-
}
-
}
這里需要注意的是如果有循環操作圖數據庫的情況,一定不要在循環體里面開啟關閉事務。應在循環體外開啟和關閉事務,即一次開閉事務,在事務里面進行循環。
筆者之前就吃了這個虧,在循環體里開啟關閉事務。如果循環了100次,則會有100次開閉事務,這個效率會有很大的問題。優化了代碼之后,執行效率有顯著提高。同樣的思想也可用在java和數據庫的交互上。像mybatis這樣的持久層框架也都支持foreach功能。我們應該盡量用起來,減少java和數據庫的交互次數。
最后想說的是neo4j社區版還是應該用在平時的學習中,用在項目中可能會有不穩定的情況出現(不確定是否是使用了社區版導致的原因)。例如筆者將neo4j用在了實際的項目開發中,項目部署后經常出現圖數據庫自己關閉的情況。具體原因也需進一步研究。
圖數據庫的前景很廣,值得你我去深入研究!
原文地址:https://blog.csdn.net/weixin_30342639/article/details/86477556