一般情況下,我們使用數(shù)據(jù)庫(kù)查找事物間的聯(lián)系的時(shí)候,只需要短程關(guān)系的查詢(兩層以內(nèi)的關(guān)聯(lián))。當(dāng)需要進(jìn)行更長(zhǎng)程的,更廣范圍的關(guān)系查詢時(shí),就需要圖數(shù)據(jù)庫(kù)的功能。 而隨著社交、電商、金融、零售、物聯(lián)網(wǎng)等行業(yè)的快速發(fā)展,現(xiàn)實(shí)世界的事物之間織起了一張巨大復(fù)雜的關(guān)系網(wǎng),傳統(tǒng)數(shù)據(jù)庫(kù)面對(duì)這樣復(fù)雜關(guān)系往往束手無(wú)策。因此,圖數(shù)據(jù)庫(kù)應(yīng)運(yùn)而生。 圖數(shù)據(jù)庫(kù)(Graph database)指的是以圖數(shù)據(jù)結(jié)構(gòu)的形式來(lái)存儲(chǔ)和查詢數(shù)據(jù)的數(shù)據(jù)庫(kù)。 從 http:///en/ranking 可以發(fā)現(xiàn),Neo4j 是目前用的最多的圖數(shù)據(jù)庫(kù),世界數(shù)據(jù)庫(kù)排行榜上排名21位。 Neo4J屬于原生圖數(shù)據(jù)庫(kù),其使用的存儲(chǔ)后端專門為圖結(jié)構(gòu)數(shù)據(jù)的存儲(chǔ)和管理進(jìn)行定制和優(yōu)化的,在圖上互相關(guān)聯(lián)的節(jié)點(diǎn)在數(shù)據(jù)庫(kù)中的物理地址也指向彼此,因此更能發(fā)揮出圖結(jié)構(gòu)形式數(shù)據(jù)的優(yōu)勢(shì)。 知識(shí)圖譜中,知識(shí)的組織形式采用的就是圖結(jié)構(gòu),所以非常適合用neo4j進(jìn)行存儲(chǔ)。 圖數(shù)據(jù)庫(kù)的優(yōu)勢(shì)在于:
數(shù)據(jù)存儲(chǔ)形式neo4j的數(shù)據(jù)存儲(chǔ)形式 主要是 節(jié)點(diǎn)(node)和 邊(edge) 來(lái)組織數(shù)據(jù)。node可以代表知識(shí)圖譜中的實(shí)體,edge可以用來(lái)代表實(shí)體間的關(guān)系,關(guān)系可以有方向,兩端對(duì)應(yīng)開(kāi)始節(jié)點(diǎn)和結(jié)束節(jié)點(diǎn)。 查詢語(yǔ)言cypherneo4j采用自己設(shè)計(jì)的查詢語(yǔ)言cypher,其特點(diǎn)和sql有很多相似的地方。match、where、return是最常用到的關(guān)鍵詞:
安裝neo4j這里我們使用docker安裝neo4j,安裝命令行如下: docker run -d --name=Neo4j\ 根據(jù)配置參數(shù),我們將容器內(nèi)的7474端口掛載到外部宿主機(jī)的7474端口,并設(shè)置好文件夾的映射關(guān)系,注意/import文件夾下放的是將要導(dǎo)入數(shù)據(jù)庫(kù)的csv文件。 我們通過(guò)一個(gè)例子來(lái)說(shuō)明如何運(yùn)用neo4j數(shù)據(jù)庫(kù)。 1. 導(dǎo)入數(shù)據(jù)我們這里有兩個(gè)csv文件如下圖,左邊的nodes_companies.csv是一部分公司節(jié)點(diǎn),右邊的edges_director_duration.csv是這些公司互相之間的服務(wù)關(guān)系。 把這兩個(gè)文件放到neo4j根目錄下的import文件夾內(nèi),使用LOAD…AS row語(yǔ)句讀取,表示將csv文件按行讀取,每行的變量名為row。再使用MERGE指令創(chuàng)建節(jié)點(diǎn),將csv文件的第一列數(shù)據(jù)與第二列數(shù)據(jù)匯總為一個(gè)結(jié)點(diǎn)內(nèi)的兩條屬性信息。
這里提一下cypher中兩個(gè)用于創(chuàng)建新的數(shù)據(jù)的兩個(gè)關(guān)鍵詞: create 和 merge merge:在數(shù)據(jù)庫(kù)中可以匹配到模式相同的數(shù)據(jù)就返回,沒(méi)有則創(chuàng)建一條這樣的數(shù)據(jù)(有則返回,沒(méi)有則創(chuàng)建) 上面再LOAD文件時(shí)使用merge可以避免導(dǎo)入完全重復(fù)的數(shù)據(jù)。 通過(guò)第二個(gè)csv文件的START_ID和END_ID字段為第一個(gè)csv文件的company之間建立聯(lián)系,即不斷遍歷第二個(gè)文件的每一行,根據(jù)START_ID和END_ID使用where找到圖中相應(yīng)節(jié)點(diǎn),并為它們添加相應(yīng)的服務(wù)(INTERLOCK)關(guān)系,添加關(guān)系屬性為weight。 LOAD CSV WITH HEADERS FROM 'file:///edges_director_duration.csv' AS row 注意在cypher語(yǔ)句里,節(jié)點(diǎn)是用()括起來(lái)表示,關(guān)系則用 [] 括起來(lái)表示。 2.創(chuàng)建關(guān)系這里我們嘗試自己創(chuàng)建一條新的關(guān)系,比如在id = 281 和 id = 879 的兩個(gè)節(jié)點(diǎn)間創(chuàng)建一條標(biāo)簽為“INTERLOCK”的關(guān)系。 先match和where鎖定 id = 281 和 id = 879的兩個(gè)公司節(jié)點(diǎn),然后用create創(chuàng)建他們之間的關(guān)系,并添加特定關(guān)系屬性信息(例如weight為10)。 cypher語(yǔ)句如下:
這條語(yǔ)句的意思是,匹配類別標(biāo)簽為company,id分別等于281和879的兩個(gè)公司節(jié)點(diǎn),設(shè)置變量名為c1和c2,在他們之間創(chuàng)建關(guān)系,關(guān)系變量名為r,這里 ()-[]-() 代表無(wú)向邊,()-[]->() 代表有向邊。 返回結(jié)果 (c1)-[r]-(c2) 匹配到的子圖如下所示: 3.比較復(fù)雜的查詢下面這條語(yǔ)句會(huì)把所有公司中,指向其他公司的連接關(guān)系數(shù)超過(guò)75條的公司全部找出來(lái)。用空括號(hào)()代表任一節(jié)點(diǎn),函數(shù)count() 計(jì)算關(guān)系的數(shù)量。 MATCH (c:company)-[r:INTERLOCK]->() WITH c, count(r) as relaNum WHERE relaNum>=75 RETURN c,relaNum 4.最短路徑查詢neo4j還還內(nèi)置實(shí)現(xiàn)了一套圖搜索算法,并提供了相關(guān)函數(shù)接口,比如你想查詢兩個(gè)節(jié)點(diǎn)之間的最短路徑,就可以用下面的查詢語(yǔ)句:
直接調(diào)用函數(shù)shortestPath,傳入的參數(shù)為選定的關(guān)系,選取任意兩個(gè)節(jié)點(diǎn),<>表示id不相等,因?yàn)椴檎业膬蓚€(gè)點(diǎn)不能是同一個(gè)點(diǎn),*..10表示10度以內(nèi)的所有關(guān)系,返回降序排序的長(zhǎng)度,限制在1000個(gè)防止內(nèi)存溢出)
MATCH (c1:company), (c2:company), p = allshortestpaths((c1)-[r:INTERLOCK*]-(c2)) 語(yǔ)句中的pathLength是路徑的邊數(shù)(第一句return),pathDist是路徑上所有帶weight邊的加權(quán)總和(第二句return)。 |
|