Cypher是Neo4j的聲明式圖查詢語言,專為處理圖數據而設計。它允許用戶以直觀、高效的方式查詢和修改圖數據庫中的數據。本章將介紹Cypher的基本概念和語法,幫助讀者掌握使用Cypher進行基礎圖數據操作的能力。
4.1 Cypher語言概述
Cypher是Neo4j的主要查詢語言,其設計理念是讓圖查詢變得簡單直觀,即使對于沒有編程背景的用戶也能快速上手。了解Cypher的設計理念和基本語法結構,是掌握這門語言的第一步。
Cypher的設計理念
Cypher 的設計融合了 SQL、SPARQL 和正則表達式等多種語言和概念,其核心理念體現在聲明式查詢、模式匹配、可讀性和靈活性等方面。首先,Cypher 是一種聲明式語言,用戶只需描述“想要什么”,而無需關心“如何獲取”,這讓查詢更專注于業務需求而非實現細節。其次,Cypher 以模式匹配為核心,用戶通過描述節點和關系的結構,Neo4j 引擎自動查找匹配的子圖。Cypher 獨特的 ASCII 藝術風格語法,使節點和關系的結構在查詢語句中直觀可見,提升了可讀性。其語法接近自然語言,即使復雜查詢也能簡潔表達,便于理解和維護。此外,Cypher 支持通過組合簡單模式構建復雜查詢,實現查詢的模塊化和重用。靈活的查詢能力涵蓋從精確匹配到路徑分析和聚合操作等多種場景。這些設計理念共同造就了 Cypher 強大且易用的特性,適用于各種圖數據檢索與分析需求。
Cypher與SQL的對比
對于熟悉SQL的用戶,了解Cypher與SQL的異同有助于快速掌握這門新語言。
Cypher和SQL都是聲明式查詢語言,用戶只需描述“想要什么”,而無需關心“如何獲取”。兩者都采用類似的子句結構,例如Cypher的MATCH
與SQL的SELECT
,以及共同的WHERE
、ORDER BY
等子句。此外,它們都支持聚合函數和分組操作,能夠對數據進行統計和匯總。無論是Cypher還是SQL,都具備事務支持和數據修改語句,能夠保證數據操作的完整性和一致性。
Cypher與SQL的主要區別體現在數據模型、連接方式、關系查詢、結果形式和語法風格等方面。首先,SQL采用表格模型,數據以行和列的形式組織,而Cypher則基于圖模型,數據以節點、關系和屬性的方式存儲。其次,在連接操作上,SQL通過JOIN語句實現表之間的關聯,而Cypher則通過模式匹配和路徑表達式直接描述節點之間的連接。對于復雜關系的查詢,SQL需要多個JOIN操作,隨著關系層級的增加,查詢語句會變得更加復雜;而Cypher可以用簡潔的路徑表達式(如()-[:KNOWS*1..3]->()
)直接表示和查詢任意深度的關系。查詢結果方面,SQL通常返回表格數據(行和列),而Cypher不僅可以返回表格,還能返回路徑或子圖,更適合圖結構的數據分析。最后,語法風格上,SQL以英語關鍵詞和表達式為主,Cypher則結合了英語關鍵詞和ASCII藝術風格的圖模式,使查詢結構更加直觀和易讀。
以下是一個簡單的對比示例,展示了如何使用Cypher和SQL查詢圖數據。
查找名為"John"的用戶的朋友:
SQL(假設有Users表和Friendships表):
SELECT f.name
FROM Users u
JOIN Friendships fs ON u.id = fs.user_id
JOIN Users f ON fs.friend_id = f.id
WHERE u.name = 'John';
Cypher:
MATCH (u:User {name: 'John'})-[:FRIENDS_WITH]->(f:User)
RETURN f.name;
查找朋友的朋友:
SQL:
SELECT ff.name
FROM Users u
JOIN Friendships fs1 ON u.id = fs1.user_id
JOIN Users f ON fs1.friend_id = f.id
JOIN Friendships fs2 ON f.id = fs2.user_id
JOIN Users ff ON fs2.friend_id = ff.id
WHERE u.name = 'John'
AND ff.id <> u.id; -- 排除自己
Cypher:
MATCH (u:User {name: 'John'})-[:FRIENDS_WITH]->(f:User)-[:FRIENDS_WITH]->(ff:User)
WHERE u <> ff -- 排除自己
RETURN ff.name;
這種對比清晰地展示了Cypher在處理關聯數據時的簡潔性和直觀性。隨著關系復雜度的增加,這種優勢會變得更加明顯。
Cypher的語法結構
Cypher查詢語句由多個子句組成,每個子句負責查詢的不同方面。理解這些基本子句及其組合方式是掌握Cypher的基礎。
主要子句及其功能:
-
MATCH:指定要在圖中查找的模式。這是大多數Cypher查詢的起點。
MATCH (p:Person)-[:WORKS_FOR]->(c:Company)
-
WHERE:添加過濾條件,限制匹配結果。
WHERE p.age > 30 AND c.name = 'Neo4j'
-
RETURN:指定查詢結果中應包含哪些數據。
RETURN p.name, p.age, c.name
-
ORDER BY:對結果進行排序。
ORDER BY p.age DESC
-
SKIP/LIMIT:分頁或限制結果數量。
SKIP 10 LIMIT 5
-
CREATE:創建新的節點或關系。
CREATE (p:Person {name: 'Alice', age: 30})
-
MERGE:查找現有模式,如果不存在則創建。
MERGE (p:Person {name: 'Bob'})
-
SET:設置或更新屬性。
SET p.age = 31
-
DELETE/DETACH DELETE:刪除節點或關系。
DETACH DELETE p
-
WITH:將一個查詢部分的結果傳遞給下一個部分,允許查詢鏈接。
MATCH (p:Person) WITH p, size((p)-[:KNOWS]->()) AS friendCount WHERE friendCount > 5 RETURN p.name, friendCount
Cypher語句的基本結構通常遵循這樣的模式:
- 使用
MATCH
找到圖中的模式 - 使用
WHERE
應用過濾條件 - 使用
RETURN
指定輸出 - 可選地使用
ORDER BY
、SKIP
、LIMIT
等修飾結果
更復雜的查詢可能包括:
- 多個
MATCH
子句 - 使用
WITH
連接的多個查詢部分 - 子查詢和復合查詢
- 聚合和分組操作
節點和關系的表示:
- 節點用圓括號表示:
()
- 可以為節點指定變量名:
(p)
- 可以為節點指定標簽:
(p:Person)
- 可以為節點指定屬性:
(p:Person {name: 'Alice'})
- 關系用方括號表示,并用箭頭指示方向:
-[:KNOWS]->
- 可以為關系指定變量名:
-[r:KNOWS]->
- 可以為關系指定屬性:
-[r:KNOWS {since: 2020}]->
- 可以指定關系的方向,或者不指定方向(雙向):
-[:KNOWS]->
,<-[:KNOWS]-
,-[:KNOWS]-
路徑變量:
可以為整個路徑指定一個變量,以便后續引用:
MATCH p = (a:Person)-[:KNOWS]->(b:Person)
RETURN p
理解這些基本語法元素及其組合方式,是掌握Cypher的關鍵。隨著經驗的積累,您將能夠編寫越來越復雜和強大的查詢。
4.2 基本查詢操作
掌握基本的查詢操作是使用Cypher的第一步。本節將介紹如何使用MATCH、WHERE、RETURN等子句進行基本的數據檢索。
MATCH與WHERE子句
MATCH
子句是Cypher查詢的核心,用于指定要在圖中查找的模式。WHERE
子句則用于添加過濾條件,進一步限定匹配結果。
基本的MATCH用法:
-
匹配特定標簽的節點:
MATCH (p:Person) RETURN p
這將返回所有帶有
Person
標簽的節點。 -
匹配多個標簽:
MATCH (p:Person:Employee) RETURN p
這將返回同時帶有
Person
和Employee
標簽的節點。 -
匹配特定屬性的節點:
MATCH (p:Person {name: 'Alice'}) RETURN p
這將返回標簽為
Person
且name
屬性值為’Alice’的節點。 -
匹配關系:
MATCH (p:Person)-[:KNOWS]->(friend) RETURN p, friend
這將返回所有
Person
節點及其通過KNOWS
關系連接的朋友節點。 -
匹配多跳關系:
MATCH (p:Person)-[:KNOWS*1..3]->(friend) RETURN p, friend
這將返回與
Person
節點之間有1到3跳KNOWS
關系的朋友節點。
WHERE子句的使用:
-
基本比較:
MATCH (p:Person) WHERE p.age > 30 RETURN p
返回年齡大于30的所有
Person
節點。 -
多條件過濾:
MATCH (p:Person) WHERE p.age > 30 AND p.city = 'London' RETURN p
返回年齡大于30且城市為London的所有
Person
節點。 -
字符串操作:
MATCH (p:Person) WHERE p.name STARTS WITH 'A' RETURN p
返回名字以’A’開頭的所有
Person
節點。 -
正則表達式:
MATCH (p:Person) WHERE p.email =~ '.*@gmail\\.com' RETURN p
返回Gmail郵箱的所有
Person
節點。 -
列表操作:
MATCH (p:Person) WHERE 'Java' IN p.skills RETURN p
返回技能列表中包含’Java’的所有
Person
節點。 -
存在性檢查:
MATCH (p:Person) WHERE exists(p.phone) RETURN p
返回有
phone
屬性的所有Person
節點。 -
路徑過濾:
MATCH (p:Person)-[r:RATED]->(m:Movie) WHERE r.score > 4 RETURN p, m
返回評分高于4的所有人-電影對。
MATCH和WHERE的組合使用允許構建復雜的查詢模式和過濾條件,是Cypher查詢的基礎。
RETURN與ORDER BY子句
RETURN
子句指定查詢結果中應包含哪些數據,而ORDER BY
子句則用于對結果進行排序。
RETURN子句的用法:
-
返回整個節點或關系:
MATCH (p:Person) RETURN p
返回完整的
Person
節點,包括所有屬性。 -
返回特定屬性:
MATCH (p:Person) RETURN p.name, p.age
只返回
Person
節點的name
和age
屬性。 -
使用別名:
MATCH (p:Person) RETURN p.name AS Name, p.age AS Age
為返回的屬性指定別名,使結果更易讀。
-
返回計算結果:
MATCH (p:Person) RETURN p.name, p.birthYear, 2023 - p.birthYear AS Age
返回計算得出的年齡。
-
返回去重結果:
MATCH (p:Person)-[:LIVES_IN]->(c:City) RETURN DISTINCT c.name
返回不重復的城市名稱。
-
返回聚合結果:
MATCH (p:Person) RETURN count(p) AS PersonCount, avg(p.age) AS AvgAge
返回人數統計和平均年齡。
ORDER BY子句的用法:
-
基本排序:
MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age
按年齡升序排列結果。
-
指定排序方向:
MATCH (p:Person) RETURN p.name, p.age ORDER BY p.age DESC
按年齡降序排列結果。
-
多字段排序:
MATCH (p:Person) RETURN p.name, p.age, p.city ORDER BY p.city, p.age DESC
先按城市升序排列,城市相同的再按年齡降序排列。
-
使用表達式排序:
MATCH (p:Person)-[:KNOWS]->(friend) RETURN p.name, count(friend) AS FriendCount ORDER BY FriendCount DESC
按朋友數量降序排列。
-
使用別名排序:
MATCH (p:Person) RETURN p.name AS Name, p.age AS Age ORDER BY Age
使用返回結果的別名進行排序。
RETURN
和ORDER BY
子句的靈活使用,可以幫助您獲取所需的數據并以合適的方式呈現。
LIMIT與SKIP子句
LIMIT
和SKIP
子句用于控制返回結果的數量和起始位置,常用于分頁查詢。
LIMIT子句限制返回的結果數量:
MATCH (p:Person)
RETURN p.name, p.age
LIMIT 10
這將只返回前10個結果。
SKIP子句跳過指定數量的結果:
MATCH (p:Person)
RETURN p.name, p.age
SKIP 10
這將跳過前10個結果,從第11個開始返回。
組合使用實現分頁:
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.name
SKIP 20 LIMIT 10
這將返回按名字排序后的第21到第30個結果,相當于第3頁(假設每頁10條)。
注意事項:
- 使用
SKIP
和LIMIT
進行分頁時,應始終配合ORDER BY
使用,以確保分頁結果的一致性。 - 對于大數據集,大的
SKIP
值可能導致性能問題,因為Neo4j需要先找到所有匹配的結果,然后跳過指定數量。在這種情況下,可以考慮使用其他分頁策略,如基于上一頁最后一個結果的屬性值進行過濾。
基礎查詢模式
掌握一些常見的查詢模式,可以幫助您更有效地使用Cypher。以下是一些基礎查詢模式:
-
查找與特定節點相關的節點:
MATCH (p:Person {name: 'Alice'})-[:KNOWS]->(friend) RETURN friend.name
查找Alice認識的所有人。
-
查找兩個節點之間的關系:
MATCH (p1:Person {name: 'Alice'})-[r]-(p2:Person {name: 'Bob'}) RETURN type(r), r
查找Alice和Bob之間的所有關系。
-
查找滿足特定條件的路徑:
MATCH path = (start:Person {name: 'Alice'})-[:KNOWS*1..3]-(end:Person {name: 'Charlie'}) RETURN path
查找Alice和Charlie之間最多3跳的"認識"路徑。
-
查找沒有特定關系的節點:
MATCH (p:Person) WHERE NOT (p)-[:LIVES_IN]->() RETURN p.name
查找沒有指定居住地的人。
-
查找具有最多關系的節點:
MATCH (p:Person)-[:KNOWS]->(friend) RETURN p.name, count(friend) AS FriendCount ORDER BY FriendCount DESC LIMIT 5
查找朋友最多的5個人。
-
查找共同關系:
MATCH (p1:Person {name: 'Alice'})-[:KNOWS]->(common)<-[:KNOWS]-(p2:Person {name: 'Bob'}) RETURN common.name
查找Alice和Bob共同認識的人。
-
條件路徑查詢:
MATCH (p:Person {name: 'Alice'})-[:KNOWS]->(friend) WHERE friend.age > 30 RETURN friend.name, friend.age
查找Alice認識的年齡大于30歲的朋友。
-
組合多個MATCH子句:
MATCH (p:Person {name: 'Alice'}) MATCH (p)-[:LIVES_IN]->(city) MATCH (other:Person)-[:LIVES_IN]->(city) WHERE other <> p RETURN other.name AS Neighbor, city.name AS City
查找與Alice住在同一城市的其他人。
這些基礎查詢模式可以根據具體需求進行調整和組合,構建更復雜的查詢。隨著對Cypher的深入理解,您將能夠設計出更高效、更精確的查詢來滿足各種業務需求。
4.3 創建與修改操作
除了查詢數據,Cypher還提供了強大的數據創建和修改功能。本節將介紹如何使用CREATE、MERGE、SET等命令來添加和更新圖數據。
CREATE與MERGE命令
CREATE
命令用于在圖中創建新的節點和關系,而MERGE
命令則結合了查找和創建功能,只在不存在時才創建新的元素。
CREATE命令的用法:
-
創建單個節點:
CREATE (p:Person {name: 'Alice', age: 30})
創建一個帶有
Person
標簽和兩個屬性的節點。 -
創建多個節點:
CREATE (p1:Person {name: 'Alice', age: 30}),(p2:Person {name: 'Bob', age: 35})
一次創建多個節點。
-
創建節點和關系:
CREATE (p1:Person {name: 'Alice'})-[:KNOWS {since: 2020}]->(p2:Person {name: 'Bob'})
創建兩個節點及它們之間的關系。
-
創建關系(節點已存在):
MATCH (p1:Person {name: 'Alice'}), (p2:Person {name: 'Bob'}) CREATE (p1)-[:KNOWS {since: 2020}]->(p2)
在已存在的節點之間創建關系。
MERGE命令的用法:
-
合并節點:
MERGE (p:Person {name: 'Alice'}) ON CREATE SET p.created = timestamp() ON MATCH SET p.lastSeen = timestamp()
如果不存在名為’Alice’的
Person
節點,則創建一個并設置created
屬性;如果已存在,則更新lastSeen
屬性。 -
合并關系:
MATCH (p1:Person {name: 'Alice'}), (p2:Person {name: 'Bob'}) MERGE (p1)-[r:KNOWS]->(p2) ON CREATE SET r.since = 2020
如果Alice和Bob之間不存在
KNOWS
關系,則創建一個并設置since
屬性。 -
合并完整路徑:
MERGE (p1:Person {name: 'Alice'})-[r:KNOWS]->(p2:Person {name: 'Bob'})
這將確保整個路徑存在,如果任何部分(節點或關系)不存在,則創建它。
CREATE與MERGE的區別:
CREATE
總是創建新的節點或關系,即使完全相同的已經存在。MERGE
首先嘗試查找匹配的模式,只有在不存在時才創建新的元素。- 使用
MERGE
時,可以使用ON CREATE
和ON MATCH
子句分別處理創建和匹配的情況。
使用建議:
- 當確定要創建新元素且不關心重復時,使用
CREATE
。 - 當需要確保唯一性或實現"查找或創建"邏輯時,使用
MERGE
。 - 對于大批量數據導入,
CREATE
通常比MERGE
更高效,因為它不需要先查找。
SET與REMOVE命令
SET
命令用于添加或更新節點和關系的屬性或標簽,而REMOVE
命令用于刪除屬性或標簽。
SET命令的用法:
-
設置或更新單個屬性:
MATCH (p:Person {name: 'Alice'}) SET p.age = 31
將Alice的年齡更新為31。
-
同時設置多個屬性:
MATCH (p:Person {name: 'Alice'}) SET p.age = 31, p.updated = timestamp()
同時更新多個屬性。
-
使用屬性映射設置多個屬性:
MATCH (p:Person {name: 'Alice'}) SET p += {age: 31, city: 'London', updated: timestamp()}
使用映射一次性設置多個屬性。
-
添加標簽:
MATCH (p:Person {name: 'Alice'}) SET p:Employee
給節點添加新的標簽。
-
替換所有屬性:
MATCH (p:Person {name: 'Alice'}) SET p = {name: 'Alice', age: 31, city: 'London'}
這將替換節點的所有現有屬性。注意:這會刪除未在新映射中指定的任何屬性。
REMOVE命令的用法:
-
刪除屬性:
MATCH (p:Person {name: 'Alice'}) REMOVE p.age
刪除Alice的年齡屬性。
-
刪除多個屬性:
MATCH (p:Person {name: 'Alice'}) REMOVE p.age, p.city
同時刪除多個屬性。
-
刪除標簽:
MATCH (p:Person:Temporary {name: 'Alice'}) REMOVE p:Temporary
刪除節點的
Temporary
標簽。
SET與REMOVE的注意事項:
SET
可以添加新屬性或覆蓋現有屬性,但不會刪除未提及的屬性。- 使用
SET p = {...}
會替換所有現有屬性,可能導致數據丟失。 REMOVE
永久刪除屬性或標簽,無法撤銷。- 刪除節點的最后一個標簽不會刪除節點本身。
- 屬性值可以設置為
null
,但這與刪除屬性不同。設置為null
的屬性仍然存在,只是值為null
。
DELETE與DETACH DELETE命令
DELETE
命令用于刪除節點和關系,而DETACH DELETE
命令用于刪除節點及其所有關系。
DELETE命令的用法:
-
刪除關系:
MATCH (p1:Person {name: 'Alice'})-[r:KNOWS]->(p2:Person {name: 'Bob'}) DELETE r
刪除Alice和Bob之間的
KNOWS
關系。 -
刪除沒有關系的節點:
MATCH (p:Person {name: 'Charlie'}) WHERE NOT (p)--() // 確保節點沒有關系 DELETE p
刪除沒有任何關系的Charlie節點。
DETACH DELETE命令的用法:
-
刪除節點及其所有關系:
MATCH (p:Person {name: 'Alice'}) DETACH DELETE p
刪除Alice節點及其所有入站和出站關系。
-
刪除多個節點及其關系:
MATCH (p:Person) WHERE p.inactive = true DETACH DELETE p
刪除所有標記為非活躍的人及其關系。
DELETE與DETACH DELETE的注意事項:
- 嘗試刪除仍有關系的節點(不使用
DETACH
)會導致錯誤。 DETACH DELETE
是一個強大的操作,會刪除節點的所有關系,使用時需謹慎。- 刪除操作是永久性的,無法撤銷。在生產環境中執行刪除操作前,建議先進行備份或使用測試數據庫。
- 可以在一個事務中組合多個操作,例如先創建新節點,然后刪除舊節點。
基礎修改模式
以下是一些常見的數據修改模式,展示了如何組合使用上述命令來完成常見任務:
-
創建唯一節點:
MERGE (p:Person {email: 'alice@example.com'}) ON CREATE SET p.name = 'Alice', p.created = timestamp()
確保每個電子郵件只對應一個
Person
節點。 -
添加關系(如果不存在):
MATCH (p1:Person {name: 'Alice'}), (p2:Person {name: 'Bob'}) MERGE (p1)-[r:KNOWS]->(p2) ON CREATE SET r.since = date()
確保Alice和Bob之間有一個
KNOWS
關系。 -
更新或創建節點和關系:
MERGE (p:Person {email: 'alice@example.com'}) ON CREATE SET p.name = 'Alice', p.created = timestamp() ON MATCH SET p.lastSeen = timestamp() WITH p MATCH (c:Company {name: 'Neo4j'}) MERGE (p)-[r:WORKS_FOR]->(c) ON CREATE SET r.since = date()
確保用戶存在并與公司有工作關系。
-
條件更新:
MATCH (p:Person {name: 'Alice'}) SET p.age = CASE WHEN p.age IS NULL THEN 30 ELSE p.age + 1 END
如果年齡未設置,則設為30;否則增加1。
-
批量更新:
MATCH (p:Person) WHERE p.city = 'New York' SET p.region = 'East Coast'
為所有紐約的人設置區域屬性。
-
替換節點:
MATCH (old:Person {name: 'Alice', outdated: true}) CREATE (new:Person {name: 'Alice', updated: true}) WITH old, new MATCH (old)-[r]->(other) CREATE (new)-[r2:KNOWS]->(other) SET r2 = properties(r) WITH old, new MATCH (other)-[r]->(old) CREATE (other)-[r2:KNOWS]->(new) SET r2 = properties(r) WITH old DETACH DELETE old
創建節點的新版本,復制所有關系,然后刪除舊節點。
-
有條件地刪除數據:
MATCH (p:Person)-[r:VISITED]->(c:City) WHERE r.lastVisit < date('2020-01-01') DELETE r
刪除2020年之前的訪問記錄。
這些基礎修改模式展示了Cypher在數據操作方面的靈活性和表達能力。通過組合不同的命令和子句,可以實現各種復雜的數據修改需求。
4.4 基礎查詢模式
在實際應用中,某些查詢模式會反復出現。掌握這些常見的查詢模式,可以幫助您更有效地使用Cypher解決實際問題。
節點查詢模式
節點查詢是最基本的查詢類型,涉及查找和過濾特定類型的節點。
-
基于標簽查詢:
MATCH (p:Person) RETURN p
查找所有
Person
節點。 -
基于屬性查詢:
MATCH (p:Person {name: 'Alice'}) RETURN p
查找名為’Alice’的
Person
節點。 -
使用WHERE子句的復雜過濾:
MATCH (p:Person) WHERE p.age > 30 AND p.city = 'London' RETURN p
查找年齡大于30且住在倫敦的人。
-
模糊查詢:
MATCH (p:Person) WHERE p.name CONTAINS 'Al' OR p.name STARTS WITH 'B' RETURN p
查找名字包含’Al’或以’B’開頭的人。
-
正則表達式查詢:
MATCH (p:Person) WHERE p.email =~ '.*@gmail\\.com' RETURN p
查找使用Gmail的人。
-
空值處理:
MATCH (p:Person) WHERE p.age IS NULL RETURN p
查找未設置年齡的人。
-
列表屬性查詢:
MATCH (p:Person) WHERE 'Java' IN p.skills RETURN p
查找技能包含’Java’的人。
-
計算屬性查詢:
MATCH (p:Person) WHERE size(p.name) > 5 RETURN p
查找名字長度大于5的人。
關系查詢模式
關系查詢涉及查找節點之間的連接和路徑。
-
基本關系查詢:
MATCH (p:Person)-[:KNOWS]->(friend) RETURN p.name, friend.name
查找所有人及其認識的朋友。
-
特定關系查詢:
MATCH (p:Person {name: 'Alice'})-[:KNOWS]->(friend) RETURN friend.name
查找Alice認識的所有人。
-
關系屬性過濾:
MATCH (p:Person)-[r:KNOWS]->(friend) WHERE r.since > 2018 RETURN p.name, friend.name, r.since
查找2018年之后建立的朋友關系。
-
多重關系查詢:
MATCH (p:Person)-[:KNOWS|:WORKS_WITH]->(other) RETURN p.name, other.name
查找通過’認識’或’一起工作’關系連接的人。
-
關系方向不限:
MATCH (p:Person {name: 'Alice'})-[:KNOWS]-(friend) RETURN friend.name
查找與Alice互相認識的人(不考慮關系方向)。
-
關系類型動態查詢:
MATCH (p:Person {name: 'Alice'})-[r]->(other) RETURN type(r), other.name
查找Alice與其他節點之間的所有關系類型。
-
關系計數:
MATCH (p:Person) RETURN p.name, size((p)-[:KNOWS]->()) AS FriendCount
統計每個人的朋友數量。
路徑查詢模式
路徑查詢涉及查找節點之間的連接路徑,可能跨越多個關系。
-
固定長度路徑:
MATCH (p1:Person {name: 'Alice'})-[:KNOWS]->(friend)-[:KNOWS]->(foaf) RETURN foaf.name
查找Alice的朋友的朋友。
-
可變長度路徑:
MATCH (p1:Person {name: 'Alice'})-[:KNOWS*1..3]->(other) RETURN other.name
查找與Alice距離1到3跳的所有人。
-
最短路徑:
MATCH p = shortestPath((p1:Person {name: 'Alice'})-[:KNOWS*]-(p2:Person {name: 'Charlie'})) RETURN length(p), [n IN nodes(p) | n.name]
查找Alice和Charlie之間的最短路徑。
-
所有簡單路徑:
MATCH p = allShortestPaths((p1:Person {name: 'Alice'})-[:KNOWS*]-(p2:Person {name: 'Charlie'})) RETURN p
查找Alice和Charlie之間的所有最短路徑。
-
帶條件的路徑查詢:
MATCH path = (p1:Person {name: 'Alice'})-[:KNOWS*1..3]->(p2:Person) WHERE all(r IN relationships(path) WHERE r.active = true) RETURN p2.name
查找通過所有活躍關系連接的人。
-
路徑不包含特定節點:
MATCH path = (p1:Person {name: 'Alice'})-[:KNOWS*1..3]->(p2:Person {name: 'Charlie'}) WHERE none(n IN nodes(path) WHERE n.name = 'Bob') RETURN path
查找不經過Bob的從Alice到Charlie的路徑。
-
帶權重的路徑查詢:
MATCH path = (p1:Person {name: 'Alice'})-[:KNOWS*1..3]->(p2:Person) RETURN p2.name, reduce(weight = 0, r IN relationships(path) | weight + r.strength) AS TotalStrength
計算路徑上所有關系強度的總和。
這些基礎查詢模式涵蓋了大多數常見的圖數據查詢需求。通過組合和擴展這些模式,可以構建更復雜、更強大的查詢來解決各種業務問題。隨著對Cypher的深入理解和實踐,您將能夠設計出更高效、更精確的查詢來滿足特定需求。
4.5 小結
本章介紹了Cypher的基本語法和查詢操作,包括與SQL的對比、基本查詢子句、數據創建和修改命令,以及常見的查詢模式。通過掌握這些基礎知識,您可以開始使用Cypher進行圖數據的查詢和操作。