一、Neo4J相關介紹
1.為什麼需要圖資料庫
隨著社交、電商、金融、零售、物聯網等行業的快速發展,現實社會織起了了一張龐大而複雜的關係
網,傳統資料庫很難處理關係運算。大資料行業需要處理的資料之間的關係隨資料量呈幾何級數增長,
急需一種支援海量複雜資料關係運算的資料庫,圖資料庫應運而生。
世界上很多著名的公司都在使用圖資料庫,比如:
- 社交領域:Facebook, Twitter,Linkedin用它來管理社交關係,實現好友推薦
- 零售領域:eBay,沃爾瑪使用它實現商品實時推薦,給買家更好的購物體驗
- 金融領域:摩根大通,花旗和瑞銀等銀行在用圖資料庫做風控處理
- 汽車製造領域:沃爾沃,戴姆勒和豐田等頂級汽車製造商依靠圖資料庫推動創新制造解決方案
- 電信領域:Verizon, Orange和AT&T 等電信公司依靠圖資料庫來管理網路,控制訪問並支援客戶
360 - 酒店領域:萬豪和雅高酒店等頂級酒店公司依使用圖資料庫來管理複雜且快速變化的庫存
圖資料庫並非指儲存圖片的資料庫,而是以圖資料結構儲存和查詢資料。
圖資料庫是基於圖論實現的一種NoSQL資料庫,其資料儲存結構和資料查詢方式都是以圖論為基礎的,
圖資料庫主要用於儲存更多的連線資料.
圖論〔Graph Theory〕是數學的一個分支。它以圖為研究物件圖論中的圖是由若干給定的點及連
接兩點的線所構成的圖形,這種圖形通常用來描述某些事物之間的某種特定關係,用點代表事物,
用連線兩點的線表示相應兩個事物間具有這種關係。
方案1:Google+
使用 Google+(GooglePlus)應用程式來了解現實世界中 Graph 資料庫的需求。 觀察下面的圖表。
在這裡,我們用圓圈表示了 Google+應用個人資料。
在上圖中,輪廓“A”具有圓圈以連線到其他輪廓:家庭圈(B,C,D)和朋友圈(B,C)。
再次,如果我們開啟配置檔案“B”,我們可以觀察以下連線的資料。
像這樣,這些應用程式包含大量的結構化,半結構化和非結構化的連線資料。 在 RDBMS 資料庫中表示這種非結構化連線資料並不容易。
如果我們在 RDBMS 資料庫中儲存這種更多連線的資料,那麼檢索或遍歷是非常困難和緩慢的。
所以要表示或儲存這種更連線的資料,我們應該選擇一個流行的圖資料庫。
圖形DBMS非常容易地儲存這種更多連線的資料。 它將每個配置檔案資料作為節點儲存在內部,它與相鄰節點連線的節點,它們透過關係相互連線。
他們儲存這種連線的資料與上面的圖表中的相同,這樣檢索或遍歷是非常容易和更快的。
方案2:Facebook
利用 Facebook 應用程式瞭解現實世界中 Graph 資料庫的需求。
在上面的圖中,Facebook Profile“A”已經連線到他的朋友,喜歡他的一些朋友,傳送訊息給他的一些朋友,跟隨他喜歡的一些名人。
這意味著大量的連線資料配置檔案A.如果我們開啟其他配置檔案,如配置檔案B,我們將看到類似的大量的連線資料。
注- 透過觀察上述兩個應用程式,它們有很多更多的連線資料。 它是非常容易儲存和檢索,這種更連線的資料與圖形資料庫。
2.特定和優勢
關係查詢效能對比 在資料關係中心,圖形資料庫在查詢速度方面非常高效,即使對於深度和複雜的查詢
也是如此。在關係型資料庫和圖資料庫(Neo4j)之間進行了實驗:在一個社交網路裡找到最大深度為5的
朋友的朋友,他們的資料集包括100萬人,每人約有50個朋友。
實驗結果如下:
對比關係型資料庫
各種NOSQL對比
分類 | 資料模型 | 優勢 | 劣勢 | 舉例 |
---|---|---|---|---|
鍵值對資料庫 | 雜湊表 | 查詢速度快 | 資料無結構化,通常只被當作字串或者二進位制資料 | Redis |
列儲存資料庫 | 列式資料儲存 | 查詢速度快;支援分佈橫向擴充套件;資料壓縮率高 | 功能相對受限 | HBase |
文件型資料庫 | 鍵值對擴充套件 | 資料結構要求不嚴格;表結構可變;不需要預先定義表結構 | 查詢效能不高,缺乏統一的查詢語法 | MongoDB |
圖資料庫 | 節點和關係組成的圖 | 利用圖結構相關演算法(最短路徑、節點度關係查詢等) | 可能需要對整個圖做計算,不利於圖資料分佈儲存 | Neo4j |
3.什麼是Neo4j
Neo4j是一個開源的NoSQL圖形資料庫,2003 年開始開發,使用 scala和java 語言,2007年開始釋出。
- 是世界上最先進的圖資料庫之一,提供原生的圖資料儲存,檢索和處理;
- 採用屬性圖模型(Property graph model),極大的完善和豐富圖資料模型;
- 專屬查詢語言 Cypher,直觀,高效;
官網: https://neo4j.com/
Neo4j的特性:
- SQL就像簡單的查詢語言Neo4j CQL
- 它遵循屬性圖資料模型
- 它透過使用Apache Lucence支援索引
- 它支援UNIQUE約束
- 它包含一個用於執行CQL命令的UI:Neo4j資料瀏覽器
- 它支援完整的ACID(原子性,一致性,隔離性和永續性)規則
- 它採用原生圖形庫與本地GPE(圖形處理引擎)
- 它支援查詢的資料匯出到JSON和XLS格式
- 它提供了REST API,可以被任何程式語言(如Java,Spring,Scala等)訪問
- 它提供了可以透過任何UI MVC框架(如Node JS)訪問的Java指令碼
- 它支援兩種Java API:Cypher API和Native Java API來開發Java應用程式
Neo4j的優點:
- 它很容易表示連線的資料
- 檢索/遍歷/導航更多的連線資料是非常容易和快速的
- 它非常容易地表示半結構化資料
- Neo4j CQL查詢語言命令是人性化的可讀格式,非常容易學習
- 使用簡單而強大的資料模型
- 它不需要複雜的連線來檢索連線的/相關的資料,因為它很容易檢索它的相鄰節點或關係細節沒有
連線或索引
4.Neo4j資料模型
圖論基礎
圖是一組節點和連線這些節點的關係,圖形以屬性的形式將資料儲存在節點和關係中,屬性是用於表示
資料的鍵值對。
在圖論中,我們可以表示一個帶有圓的節點,節點之間的關係用一個箭頭標記表示。
最簡單的可能圖是單個節點:
我們可以使用節點表示社交網路(如Google+(GooglePlus)個人資料),它不包含任何屬性。向
Google+個人資料新增一些屬性:
在兩個節點之間建立關係:
此處在兩個配置檔案之間建立關係名稱“跟隨”。 這意味著 Profile-I 遵循 Profile-II。
屬性圖模型
Neo4j圖資料庫遵循屬性圖模型來儲存和管理其資料。
- 屬性圖模型規則
- 表示節點,關係和屬性中的資料
- 節點和關係都包含屬性
- 關係連線節點
- 屬性是鍵值對
- 節點用圓圈表示,關係用方向鍵表示。
- 關係具有方向:單向和雙向。
- 每個關係包含“開始節點”或“從節點”和“到節點”或“結束節點”
在屬性圖資料模型中,關係應該是定向的。如果我們嘗試建立沒有方向的關係,那麼它將丟擲一個錯誤
訊息。在Neo4j中,關係也應該是有方向性的。如果我們嘗試建立沒有方向的關係,那麼Neo4j會丟擲一
個錯誤訊息,“關係應該是方向性的”。
Neo4j圖資料庫將其所有資料儲存在節點和關係中,我們不需要任何額外的RDBMS資料庫或NoSQL資料
庫來儲存Neo4j資料庫資料,它以圖的形式儲存資料。Neo4j使用本機GPE(圖形處理引擎)來使用它的
本機圖儲存格式。
圖資料庫資料模型的主要構建塊是:
- 節點
- 關係
- 屬性
簡單的屬性圖的例子:
這裡我們使用圓圈表示節點。 使用箭頭表示關係,關係是有方向性的。 我們可以用Properties(鍵值
對)來表示Node的資料。 在這個例子中,我們在Node的Circle中表示了每個Node的Id屬性。
Neo4j的構建元素
Neo4j圖資料庫主要有以下構建元素:
- 節點
- 屬性
- 關係
- 標籤
- 資料瀏覽器
有一個或多個標籤,用於描述其在圖表中的作用
屬性
屬性(Property)是用於描述圖節點和關係的鍵值對。其中Key是一個字串,值可以透過使用任何
- Neo4j資料型別來表示
- 屬性是命名值,其中名稱(或鍵)是字串
- 屬性可以被索引和約束
- 可以從多個屬性建立複合索引
關係
關係(Relationship)同樣是圖資料庫的基本元素。當資料庫中已經存在節點後,需要將節點連線起來
構成圖。關係就是用來連線兩個節點,關係也稱為圖論的邊(Edge) ,其始端和末端都必須是節點,關係不
能指向空也不能從空發起。關係和節點一樣可以包含多個屬性,但關係只能有一個型別(Type) 。
關係連線兩個節點
關係是方向性的
節點可以有多個甚至遞迴的關係
關係可以有一個或多個屬性(即儲存為鍵/值對的屬性)
基於方向性,Neo4j關係被分為兩種主要型別:
- 單向關係
- 雙向關係
標籤
標籤(Label)將一個公共名稱與一組節點或關係相關聯, 節點或關係可以包含一個或多個標籤。 我們
可以為現有節點或關係建立新標籤, 我們可以從現有節點或關係中刪除標籤。
標籤用於將節點分組
一個節點可以具有多個標籤
對標籤進行索引以加速在圖中查詢節點
本機標籤索引針對速度進行了最佳化
Neo4j Browser
一旦我們安裝Neo4j,我們就可以訪問Neo4j資料瀏覽器
5.軟體安裝
下載地址:https://neo4j.com/download-center/
安裝方式:
- Neo4j Enterprise Server
- Neo4j Community Server
- Neo4j Desktop
下載相關軟體
解壓縮即可
相關的指令
console: 直接啟動 neo4j 伺服器
install-service | uninstall-service | update-service : 安裝/解除安裝/更新 neo4j 服務
start/stop/restart/status: 啟動/停止/重啟/狀態
-V 輸出更多資訊
進入到bin目錄,執行
neo4j console
在瀏覽器中訪問http://localhost:7474
使用使用者名稱neo4j和預設密碼neo4j進行連線,然後會提示更改密碼。
Neo4j Browser是開發人員用來探索Neo4j資料庫、執行Cypher查詢並以表格或圖形形式檢視結果的工
具。
當然也可以透過 Docker 來安裝
拉取映象
docker pull neo4j:3.5.22-community
執行映象
docker run -d -p 7474:7474 -p 7687:7687 --name neo4j \
-e "NEO4J_AUTH=neo4j/123456" \
-v /usr/local/soft/neo4j/data:/data \
-v /usr/local/soft/neo4j/logs:/logs \
-v /usr/local/soft/neo4j/conf:/var/lib/neo4j/conf \
-v /usr/local/soft/neo4j/import:/var/lib/neo4j/import \
neo4j:3.5.22-community
二、CQL語句
1.CQL簡介
Neo4j的Cypher語言是為處理圖形資料而構建的,CQL代表Cypher查詢語言。像Oracle資料庫具有查詢
語言SQL,Neo4j具有CQL作為查詢語言。
- 它是Neo4j圖形資料庫的查詢語言。
- 它是一種宣告性模式匹配語言
- 它遵循SQL語法。
- 它的語法是非常簡單且人性化、可讀的格式。
2.CREATE 命令
Neo4j使用CQL“CREATE”命令
- 建立沒有屬性的節點
- 使用屬性建立節點
- 在沒有屬性的節點之間建立關係
- 使用屬性建立節點之間的關係
- 為節點或關係建立單個或多個標籤
語法命令
CREATE (<node-name>:<label-name>)
語法說明
注意事項 -
1、Neo4j資料庫伺服器使用此<node-name>將此節點詳細資訊儲存在Database.As中作為Neo4j DBA或Developer,我們不能使用它來訪問節點詳細資訊。
2、Neo4j資料庫伺服器建立一個<label-name>作為內部節點名稱的別名。作為Neo4j DBA或Developer,我們應該使用此標籤名稱來訪問節點詳細資訊。
3.MATCH 命令
Neo4j CQL MATCH 命令用於
- 從資料庫獲取有關節點和屬性的資料
- 從資料庫獲取有關節點,關係和屬性的資料
語法格式:
MATCH
(
<node-name>:<label-name>
)
語法說明:
4.RETURN 子句
Neo4j CQL RETURN子句用於 -
- 檢索節點的某些屬性
- 檢索節點的所有屬性
- 檢索節點和關聯關係的某些屬性
- 檢索節點和關聯關係的所有屬性
語法結構
RETURN
<node-name>.<property1-name>,
........
<node-name>.<propertyn-name>
語法說明:
5.MATCH和RETURN
在Neo4j CQL中,我們不能單獨使用MATCH或RETURN命令,因此我們應該合併這兩個命令以從資料庫檢索資料。
Neo4j使用CQL MATCH + RETURN命令 -
- 檢索節點的某些屬性
- 檢索節點的所有屬性
- 檢索節點和關聯關係的某些屬性
- 檢索節點和關聯關係的所有屬性
語法結構
MATCH Command
RETURN Command
語法說明
6.CREATE+MATCH+RETURN命令
先建立一個客戶
create (e:Customer {id:"1001",name:"boge",location:"cs"})
建立一個信用卡節點
create (cc:CreditCard {id:"9999",number:"1234567890",cvv:"888",expiredate:"22/17"})
然後我們可以查詢對應的資訊
match (k:customer) return k.name,k.location,k.id
還可以查詢信用卡的資訊
match (m:CreditCard) return m.number,m.cvv,m.id,m.expiredate
7.關係基礎
Neo4j圖資料庫遵循屬性圖模型來儲存和管理其資料。
根據屬性圖模型,關係應該是定向的。 否則,Neo4j將丟擲一個錯誤訊息。
基於方向性,Neo4j關係被分為兩種主要型別。
- 單向關係
- 雙向關係
在以下場景中,我們可以使用Neo4j CQL CREATE命令來建立兩個節點之間的關係。 這些情況適用於Uni和雙向關係。
- 在兩個現有節點之間建立無屬性的關係
- 在兩個現有節點之間建立有屬性的關係
- 在兩個新節點之間建立無屬性的關係
- 在兩個新節點之間建立有屬性的關係
- 在具有WHERE子句的兩個退出節點之間建立/不使用屬性的關係
注意 -
我們將建立客戶和CreditCard之間的關係,如下所示:
8.CREATE建立標籤
CREATE標籤可以建立單個標籤或者多個標籤
CREATE(node-name:lable-name1:lable-name2)
還有就是可以根據CREATE語句來建立標籤之間的關係
CREATE (node1-name:lable1-name) - [relationship-name:relationship-lable-name]->(node2-name:lable2-name)
案例:
create (p1:Profile1)-[r1:喜歡]->(p2:Profile2)
9.WHERE子句
像SQL一樣,Neo4j CQL在CQL MATCH命令中提供了WHERE子句來過濾MATCH查詢的結果。
語法結構
WHERE <condition>
複雜的語法結構
WHERE <condition> <boolean-operator> <condition>
Neo4j支援以下布林運算子在Neo4j CQL WHERE子句中使用以支援多個條件。
Neo4j 支援以下的比較運算子,在 Neo4j CQL WHERE 子句中使用來支援條件。
案例:
match (m:Employee) where m.age > 18 or m.id = 1002 return m
多個節點關聯查詢
where子句也可以建立關係
語法結構
MATCH (<node1-label-name>:<node1-name>),(<node2-label-name>:<node2-name>)
WHERE <condition>
CREATE (<node1-label-name>)-[<relationship-label-name>:<relationship-name>
{<relationship-properties>}]->(<node2-label-name>)
案例
match (c:customer) , (d:CreditCard) where c.id = "1001" and d.id = "9999" create (c)-[r:消費{shopdate:"2022/09/28",price:6000}]->(d) return r
10.DELETE命令
Neo4j使用CQL DELETE子句
- 刪除節點。
- 刪除節點及相關節點和關係。
對應的語法結構
DELETE <node-name-list>
注意 -
我們應該使用逗號(,)運算子來分隔節點名。
11.REMOVE命令
有時基於我們的客戶端要求,我們需要向現有節點或關係新增或刪除屬性。
我們使用Neo4j CQL SET子句向現有節點或關係新增新屬性。
我們使用Neo4j CQL REMOVE子句來刪除節點或關係的現有屬性。
Neo4j CQL REMOVE命令用於
- 刪除節點或關係的標籤
- 刪除節點或關係的屬性
Neo4j CQL DELETE和REMOVE命令之間的主要區別 -
- DELETE操作用於刪除節點和關聯關係。
- REMOVE操作用於刪除標籤和屬性。
Neo4j CQL DELETE和REMOVE命令之間的相似性 -
- 這兩個命令不應單獨使用。
- 兩個命令都應該與MATCH命令一起使用。
透過remove來移除標籤
match (d:`電影`) remove d:Movie
12.SET子句
有時,根據我們的客戶端要求,我們需要向現有節點或關係新增新屬性。
要做到這一點,Neo4j CQL 提供了一個SET子句。
Neo4j CQL 已提供 SET 子句來執行以下操作。
- 向現有節點或關係新增新屬性
- 新增或更新屬性值
語法結構
SET <property-name-list>
新增屬性:
MATCH (book:Book)
SET book.title = 'superstar'
RETURN book
13.ORDER BY排序
Neo4j CQL在MATCH命令中提供了“ORDER BY”子句,對MATCH查詢返回的結果進行排序。
我們可以按升序或降序對行進行排序。
預設情況下,它按升序對行進行排序。 如果我們要按降序對它們進行排序,我們需要使用DESC子句。
語法結構
ORDER BY <property-name-list> [DESC]
舉例:
MATCH (emp:Employee)
RETURN emp.empid,emp.name,emp.salary,emp.deptno
ORDER BY emp.name
14.UNION合併
與SQL一樣,Neo4j CQL有兩個子句,將兩個不同的結果合併成一組結果
- UNION
- UNION ALL
UNION子句
它將兩組結果中的公共行組合並返回到一組結果中。 它不從兩個節點返回重複的行。
限制:
結果列型別和來自兩組結果的名稱必須匹配,這意味著列名稱應該相同,列的資料型別應該相同。
語法結構
<MATCH Command1>
UNION
<MATCH Command2>
注意 -
如果這兩個查詢不返回相同的列名和資料型別,那麼它丟擲一個錯誤。
as 來處理不同的字首
MATCH (cc:CreditCard)
RETURN cc.id as id,cc.number as number,cc.name as name,
cc.valid_from as valid_from,cc.valid_to as valid_to
UNION
MATCH (dc:DebitCard)
RETURN dc.id as id,dc.number as number,dc.name as name,
dc.valid_from as valid_from,dc.valid_to as valid_to
UNION ALL子句
它結合並返回兩個結果集的所有行成一個單一的結果集。它還返回由兩個節點重複行。
限制
結果列型別,並從兩個結果集的名字必須匹配,這意味著列名稱應該是相同的,列的資料型別應該是相同的。
union all 語法
<MATCH Command1>
UNION ALL
<MATCH Command2>
15.LIMIT和SKIP子句
Neo4j CQL已提供“LIMIT”子句來過濾或限制查詢返回的行數。 它修剪CQL查詢結果集底部的結果。
如果我們要修整CQL查詢結果集頂部的結果,那麼我們應該使用CQL SKIP子句
skip跳過
skip和limit可以結合使用達到分頁的效果
16.合併
Neo4j使用CQL MERGE命令 -
- 建立節點,關係和屬性
- 為從資料庫檢索資料
MERGE命令是CREATE命令和MATCH命令的組合。
MERGE = CREATE + MATCH
merge語法
MERGE (<node-name>:<label-name>
{
<Property1-name>:<Pro<rty1-Value>
.....
<Propertyn-name>:<Propertyn-Value>
})
注意 -
Neo4j CQL MERGE命令語法與CQL CREATE命令類似。
17.NULL值
Neo4j CQL將空值視為對節點或關係的屬性的缺失值或未定義值。
當我們建立一個具有現有節點標籤名稱但未指定其屬性值的節點時,它將建立一個具有NULL屬性值的新節點。
還可以用null 作為查詢的條件
18.IN運算子
與SQL一樣,Neo4j CQL提供了一個IN運算子,以便為CQL命令提供值的集合。
IN[<Collection-of-values>]
案例:
MATCH (e:Employee)
WHERE e.id IN [123,124]
RETURN e.id,e.name,e.sal,e.deptno
三、CQL函式
1.字串函式
與SQL一樣,Neo4J CQL提供了一組String函式,用於在CQL查詢中獲取所需的結果。
列舉幾個常用的
案例:
2.AGGEGATION聚合
和SQL一樣,Neo4j CQL提供了一些在RETURN子句中使用的聚合函式。 它類似於SQL中的GROUP BY子句。
我們可以使用MATCH命令中的RETURN +聚合函式來處理一組節點並返回一些聚合值。
3.關係函式
Neo4j CQL提供了一組關係函式,以在獲取開始節點,結束節點等細節時知道關係的細節。
案例:
四、Neo4J和SpringBoot整合
新增對應的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
然後新增對應的配置檔案
# neo4j配置
spring.data.neo4j.uri= bolt://localhost:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=123456
1.Node的操作
然後建立對應的實體物件
@Data
@NodeEntity("Person")
public class Person {
@Id
@GeneratedValue
private Long id;
@Property("name")
private String name;
}
@NodeEntity:標明是一個節點實體
@RelationshipEntity:標明是一個關係實體
@Id:實體主鍵
@Property:實體屬性
@GeneratedValue:實體屬性值自增
@StartNode:開始節點(可以理解為父節點)
@EndNode:結束節點(可以理解為子節點)
然後建立對應的Repository介面
@Repository
public interface PersonRepository extends Neo4jRepository<Person,Long> {
}
然後我們就可以測試Node的建立了
@Autowired
private PersonRepository personRepository;
@Test
void contextLoads() {
Person person = new Person();
person.setName("波哥");
personRepository.save(person);
}
建立成功
2.Node關係的維護
建立關係實體
@Data
@RelationshipEntity(type = "徒弟")
public class PersonRelation implements Serializable {
@Id
@GeneratedValue
private Long id;
@StartNode
private Person parent;
@EndNode
private Person child;
@Property
private String relation;
public PersonRelation(Person parent, Person child, String relation) {
this.parent = parent;
this.child = child;
this.relation = relation;
}
}
建立對應的Dao持久層
@Repository
public interface PersonRelationRepository extends Neo4jRepository<PersonRelation,Long> {
}
然後測試
/**
* 節點關係
*/
@Test
void nodeRelation(){
Person p1 = new Person("唐僧",6666);
Person p2 = new Person("孫悟空",5555);
Person p3 = new Person("豬八戒",3333);
Person p4 = new Person("沙僧",2222);
Person p5 = new Person("白龍馬",1111);
// 維護 關係
PersonRelation pr1 = new PersonRelation(p1,p2,"徒弟");
PersonRelation pr2 = new PersonRelation(p1,p3,"徒弟");
PersonRelation pr3 = new PersonRelation(p1,p4,"徒弟");
PersonRelation pr4 = new PersonRelation(p1,p5,"徒弟");
personRelationRepository.save(pr1);
personRelationRepository.save(pr2);
personRelationRepository.save(pr3);
personRelationRepository.save(pr4);
}
執行後的效果: