cypher vs. sql

Posted on Wed 09 October 2024 in Journal

Abstract cypher vs. sql
Authors Walter Fan
 Category    learning note  
Status v1.0
Updated 2024-10-09
License CC-BY-NC-ND 4.0

Cypher vs. SQL

在图数据库和关系数据库中,Cypher 和 SQL 都是用于数据操作的查询语言,但它们的设计和应用方式有所不同。Cypher 是为图数据库(如 Neo4j 和 Memgraph)设计的,适用于处理节点和边的图状结构;SQL 则是关系型数据库的查询语言,专为操作表格数据而设计。下面是两种语言在 CRUD 操作上的对比:

  1. 创建 (Create)

Cypher(在图数据库中创建节点和关系):

// 创建一个 Person 节点 CREATE (p:Person {name: "Alice", age: 30})

// 创建一个节点和它之间的关系 CREATE (p1:Person {name: "Alice"}) CREATE (p2:Person {name: "Bob"}) CREATE (p1)-[:FRIEND]->(p2)

SQL(在关系数据库中创建记录):

-- 创建 Person 表中的一条记录 INSERT INTO Person (name, age) VALUES ("Alice", 30);

-- 在 Friend 表中表示 Alice 和 Bob 是朋友 INSERT INTO Person (name) VALUES ("Alice"), ("Bob"); INSERT INTO Friend (person1, person2) VALUES ("Alice", "Bob");

  1. 读取 (Read)

Cypher:

// 查找所有名为 "Alice" 的 Person 节点 MATCH (p:Person {name: "Alice"}) RETURN p

// 查找 Alice 的所有朋友 MATCH (p1:Person {name: "Alice"})-[:FRIEND]->(p2:Person) RETURN p2

SQL:

-- 查询所有名为 "Alice" 的 Person 记录 SELECT * FROM Person WHERE name = "Alice";

-- 查找 Alice 的所有朋友 SELECT p2.* FROM Person p1 JOIN Friend f ON p1.name = f.person1 JOIN Person p2 ON f.person2 = p2.name WHERE p1.name = "Alice";

  1. 更新 (Update)

Cypher:

// 将名为 "Alice" 的 Person 节点的年龄更新为 31 MATCH (p:Person {name: "Alice"}) SET p.age = 31

SQL:

-- 将 Person 表中名为 "Alice" 的记录的年龄更新为 31 UPDATE Person SET age = 31 WHERE name = "Alice";

  1. 删除 (Delete)

Cypher:

// 删除名为 "Alice" 的 Person 节点以及其所有关系 MATCH (p:Person {name: "Alice"}) DETACH DELETE p

SQL:

-- 删除 Person 表中名为 "Alice" 的记录 DELETE FROM Person WHERE name = "Alice";

-- 删除 Friend 表中涉及 Alice 的关系 DELETE FROM Friend WHERE person1 = "Alice" OR person2 = "Alice";

tips

在 Neo4j 中,如果你想查询从 A 类节点到 B 类节点之间经过若干节点和边的所有路径,并取出所有 B 类节点,你可以使用 Cypher 的可变长度路径查询。假设 A 类节点有标签 A,B 类节点有标签 B,你可以通过以下查询来实现:

MATCH (a:A)-[:RELATIONSHIP*]-(b:B)
RETURN b

在这个查询中:

  • (a:A) 匹配具有 A 标签的节点。
  • [:RELATIONSHIP*] 表示路径中可能经过任意数量的关系(RELATIONSHIP 是关系的类型,你可以根据实际情况更改)。
  • (b:B) 匹配具有 B 标签的节点。
  • RETURN b 返回所有符合条件的 B 类节点。

说明

  • [:RELATIONSHIP*]:可变长度的路径,表示可以经过 0 到任意数量的中间节点和关系。如果你只想匹配特定长度的路径,可以限制长度,如 [:RELATIONSHIP*1..3](表示路径长度为 1 到 3)。
  • RELATIONSHIP 是关系类型,你可以替换为实际的关系名,或者使用 [:] 表示任何关系类型。
  • 查询返回的是所有与 A 类节点有连接路径的 B 类节点。

示例:查找 A 类用户到 B 类产品的路径

如果你有一个社交网络,其中 A 类节点表示用户,B 类节点表示产品,并且用户和产品之间有多种关系(例如,PURCHASEDLIKED 等),你可以用以下查询找出所有连接到 A 类用户的 B 类产品:

MATCH (a:A)-[*]-(b:B)
RETURN DISTINCT b

这里 [*] 匹配任意类型的关系和任意数量的中间节点,DISTINCT 确保返回的 B 类节点不重复。

限制路径长度

如果你只关心从 A 类节点到 B 类节点的特定长度的路径,可以用以下查询。例如,限制路径长度在 2 到 4 之间:

MATCH (a:A)-[*2..4]-(b:B)
RETURN DISTINCT b

这个查询将返回所有从 A 类节点到 B 类节点的长度为 2 到 4 的路径。