Neo4j 是一个高性能的 NoSQL 图数据库,它将数据存储为节点(Nodes)、关系(Relationships)和属性(Properties)。
下面是一些操作示例,并附有详细讲解。
基础示例
1. 创建节点
示例代码:
CREATE (n:Person {name: 'zuoyang', age: 26})
CREATE (zhangwuji:Person {name: 'zhangwuji', age: 30})
讲解:
CREATE关键字用于创建新的节点。(n:Person {name: 'zuoyang', age: 26})定义了一个新的节点,其中n是这个节点的变量名,Person是节点的标签,{name: 'zuoyang', age: 26}是节点的属性。
2. 查询节点
示例代码:
MATCH (n:Person) RETURN n
讲解:
MATCH关键字用于模式匹配,寻找符合特定模式的节点或关系。(n:Person)指定了要匹配的节点类型为Person。RETURN n返回所有匹配的节点。
3. 创建关系
示例代码:
MATCH (a:Person {name: 'zuoyang'}), (b:Person {name: 'zhangwuji'})
CREATE (a)-[:KNOWS]->(b)
讲解:
MATCH关键字用于找到名为zuoyang和Bob的两个Person节点。CREATE (a)-[:KNOWS]->(b)创建了一个从zuoyang节点到Bob节点的关系,关系的类型为KNOWS。
4. 查询关系
示例代码:
MATCH (a:Person)-[r:KNOWS]->(b:Person)
RETURN a, r, b
讲解:
MATCH (a:Person)-[r:KNOWS]->(b:Person)匹配所有Person节点之间存在KNOWS关系的模式。RETURN a, r, b返回匹配的起始节点a、关系r和结束节点b。
5. 更新节点属性
示例代码:
MATCH (n:Person {name: 'zuoyang'})
SET n.age = 27
RETURN n
讲解:
MATCH (n:Person {name: 'zuoyang'})匹配名为zuoyang的Person节点。SET n.age = 27更新该节点的age属性为27。RETURN n返回更新后的节点。
6. 删除节点
示例代码:
MATCH (n:Person {name: 'zhangwuji'})
DETACH DELETE n
讲解:
MATCH (n:Person {name: 'Bob'})匹配名为Bob的Person节点。DETACH DELETE n删除该节点及其所有关联的关系。
7. 删除关系
示例代码:
MATCH (a:Person)-[r:KNOWS]->(b:Person)
DELETE r
讲解:
MATCH (a:Person)-[r:KNOWS]->(b:Person)匹配所有Person节点之间存在KNOWS关系的模式。DELETE r删除匹配的关系r。
以上是 Neo4j 的一些基础操作示例及其详细讲解。
复杂查询
案例:倚天屠龙记人物关系分析
初始数据
假设我们有一个包含《倚天屠龙记》中主要人物及其关系的图数据库,包括门派、角色(如张无忌、赵敏、周芷若等)以及他们之间的关系(如师徒、情侣、敌对等)。
创建初始数据:
CREATE (zhangwuji:Person {name: '张无忌', role: '明教教主'})
CREATE (zhao_min:Person {name: '赵敏', role: '元朝郡主'})
CREATE (zhou_zhiruo:Person {name: '周芷若', role: '峨眉派掌门'})
CREATE (ying_baihu:Person {name: '殷白虎', role: '明教四大法王之一'})
CREATE (xie_xun:Person {name: '谢逊', role: '明教护教法王'})
CREATE (song_qing:Person {name: '宋青书', role: '武当派弟子'})
CREATE (yuansheng:Person {name: '圆真', role: '少林派和尚'})
// 明教
CREATE (zhangwuji)-[:HAS_FOLLOWER]->(ying_baihu)
CREATE (zhangwuji)-[:HAS_FOLLOWER]->(xie_xun)
// 峨眉派
CREATE (zhou_zhiruo)-[:HAS_FOLLOWER]->(song_qing)
// 情侣关系
CREATE (zhangwuji)-[:LOVE]->(zhao_min)
CREATE (zhangwuji)-[:LOVE]->(zhou_zhiruo)
// 敌对关系
CREATE (zhangwuji)-[:ENEMY_OF]->(yuansheng)
CREATE (zhou_zhiruo)-[:ENEMY_OF]->(yuansheng)
// 师徒关系
CREATE (xie_xun)-[:MASTER_OF]->(zhangwuji)
复杂查询: 查找张无忌的所有直接下属
查询代码:
MATCH (zhangwuji:Person {name: '张无忌'})-[rel:HAS_FOLLOWER]->(follower:Person)
RETURN follower.name AS FollowerName, type(rel) AS RelationshipType
讲解:
MATCH (zhangwuji:Person {name: '张无忌'})-[rel:HAS_FOLLOWER]->(follower:Person)匹配所有与张无忌有HAS_FOLLOWER关系的下属,并将关系定义为rel。RETURN follower.name AS FollowerName, type(rel) AS RelationshipType返回这些下属的姓名及其关系类型。
复杂查询: 查找张无忌的情侣及其直接下属
查询代码:
MATCH (zhangwuji:Person {name: '张无忌'})-[rel1:LOVE]->(lover:Person),
(lover)-[rel2:HAS_FOLLOWER]->(follower:Person)
RETURN lover.name AS LoverName, follower.name AS FollowerName, type(rel2) AS RelationshipType
讲解:
MATCH (zhangwuji:Person {name: '张无忌'})-[rel1:LOVE]->(lover:Person)匹配所有与张无忌有LOVE关系的情侣,并将关系定义为rel1。(lover)-[rel2:HAS_FOLLOWER]->(follower:Person)匹配这些情侣的直接下属,并将关系定义为rel2。RETURN lover.name AS LoverName, follower.name AS FollowerName, type(rel2) AS RelationshipType返回情侣及其下属的姓名及其关系类型。
复杂查询: 查找张无忌阵营中所有的人物及其关系
查询代码:
MATCH (zhangwuji:Person {name: '张无忌'})-[rel:HAS_FOLLOWER|LOVE]->(person:Person)
WITH zhangwuji, collect({name: person.name, relationship: type(rel)}) AS relationships
OPTIONAL MATCH (person)-[rel2:HAS_FOLLOWER|LOVE]->(subordinate:Person)
WITH zhangwuji, relationships, collect({name: subordinate.name, relationship: type(rel2)}) AS subordinates
RETURN zhangwuji.name AS LeaderName, relationships, subordinates
讲解:
MATCH (zhangwuji:Person {name: '张无忌'})-[rel:HAS_FOLLOWER|LOVE]->(person:Person)匹配所有与张无忌有HAS_FOLLOWER或LOVE关系的人物,并将关系定义为rel。WITH zhangwuji, collect({name: person.name, relationship: type(rel)}) AS relationships收集这些人物及其关系。OPTIONAL MATCH (person)-[rel2:HAS_FOLLOWER|LOVE]->(subordinate:Person)匹配这些人物的下属(如果有),并将关系定义为rel2。WITH zhangwuji, relationships, collect({name: subordinate.name, relationship: type(rel2)}) AS subordinates收集这些下属及其关系。RETURN zhangwuji.name AS LeaderName, relationships, subordinates返回张无忌及其下属、下属的下属的详细信息。
案例:三国演义人物关系分析
初始数据
假设我们有一个包含三国时期主要人物及其关系的图数据库,包括君主、将领、谋士等角色以及他们之间的关系(如效忠、结拜、交战等)。
创建初始数据:
CREATE (liubei:Person {name: '刘备', role: '君主'})
CREATE (guanyu:Person {name: '关羽', role: '将领'})
CREATE (zhangfei:Person {name: '张飞', role: '将领'})
CREATE (zhugeliang:Person {name: '诸葛亮', role: '谋士'})
CREATE (caocao:Person {name: '曹操', role: '君主'})
CREATE (xiahouyu:Person {name: '夏侯惇', role: '将领'})
CREATE (sunquan:Person {name: '孙权', role: '君主'})
CREATE (zhouyu:Person {name: '周瑜', role: '将领'})
// 刘备阵营
CREATE (liubei)-[:HAS_GENERAL]->(guanyu)
CREATE (liubei)-[:HAS_GENERAL]->(zhangfei)
CREATE (liubei)-[:HAS_ADVISOR]->(zhugeliang)
// 曹操阵营
CREATE (caocao)-[:HAS_GENERAL]->(xiahouyu)
// 孙权阵营
CREATE (sunquan)-[:HAS_GENERAL]->(zhouyu)
// 结拜兄弟关系
CREATE (liubei)-[:BROTHERHOOD]->(guanyu)
CREATE (liubei)-[:BROTHERHOOD]->(zhangfei)
CREATE (guanyu)-[:BROTHERHOOD]->(zhangfei)
// 交战关系
CREATE (liubei)-[:WAR_WITH]->(caocao)
CREATE (sunquan)-[:WAR_WITH]->(caocao)
复杂查询: 查找刘备的所有直接下属
查询代码:
MATCH (liubei:Person {name: '刘备'})-[rel:HAS_GENERAL|HAS_ADVISOR]->(subordinate:Person)
RETURN subordinate.name AS SubordinateName, type(rel) AS RelationshipType
讲解:
MATCH (liubei:Person {name: '刘备'})-[rel:HAS_GENERAL|HAS_ADVISOR]->(subordinate:Person)匹配所有与刘备有HAS_GENERAL或HAS_ADVISOR关系的下属。RETURN subordinate.name AS SubordinateName, type(rel) AS RelationshipType返回这些下属的姓名及其关系类型。
复杂查询: 查找与曹操交战的所有君主及其将领
查询代码:
MATCH (ruler:Person {role: '君主'})-[:WAR_WITH]->(caocao:Person {name: '曹操'}),
(ruler)-[:HAS_GENERAL]->(general:Person)
RETURN ruler.name AS RulerName, general.name AS GeneralName
讲解:
MATCH (ruler:Person {role: '君主'})-[:WAR_WITH]->(caocao:Person {name: '曹操'})匹配所有与曹操有WAR_WITH关系的君主。(ruler)-[:HAS_GENERAL]->(general:Person)匹配这些君主的将领。RETURN ruler.name AS RulerName, general.name AS GeneralName返回这些君主及其将领的姓名。
复杂查询: 查找所有君主及其直接下属和间接下属
查询代码:
MATCH (ruler:Person {role: '君主'})-[rel:HAS_GENERAL|HAS_ADVISOR]->(directSubordinate:Person)
OPTIONAL MATCH (directSubordinate)-[rel:HAS_GENERAL|HAS_ADVISOR]->(indirectSubordinate:Person)
RETURN ruler.name AS RulerName,
collect({name: directSubordinate.name, relationship: type(rel)}) AS DirectSubordinates,
collect({name: indirectSubordinate.name, relationship: type(rel)}) AS IndirectSubordinates
讲解:
MATCH (ruler:Person {role: '君主'})-[:HAS_GENERAL|HAS_ADVISOR]->(directSubordinate:Person)匹配所有君主及其直接下属。OPTIONAL MATCH (directSubordinate)-[:HAS_GENERAL|HAS_ADVISOR]->(indirectSubordinate:Person)匹配这些直接下属的下属(如果有)。RETURN ruler.name AS RulerName, collect({name: directSubordinate.name, relationship: type(rel)}) AS DirectSubordinates, collect({name: indirectSubordinate.name, relationship: type(rel)}) AS IndirectSubordinates返回君主及其直接下属和间接下属的详细信息。
参考资料
[1] . Neo4j官网 . https://neo4j.com/
[2] . Martin Kleppmann著 . 《数据密集型应用系统设计》 . 第二章 . 图状数据模型