【代码备忘录】Neo4j基础语法及复杂查询示例

670 阅读6分钟

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 关键字用于找到名为 zuoyangBob 的两个 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'}) 匹配名为 zuoyangPerson 节点。
  • SET n.age = 27 更新该节点的 age 属性为 27
  • RETURN n 返回更新后的节点。

6. 删除节点

示例代码:

MATCH (n:Person {name: 'zhangwuji'})
DETACH DELETE n

讲解:

  • MATCH (n:Person {name: 'Bob'}) 匹配名为 BobPerson 节点。
  • 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_FOLLOWERLOVE 关系的人物,并将关系定义为 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_GENERALHAS_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著 . 《数据密集型应用系统设计》 . 第二章 . 图状数据模型