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 操作上的对比:
- 创建 (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");
- 读取 (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";
- 更新 (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";
- 删除 (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 类节点表示产品,并且用户和产品之间有多种关系(例如,PURCHASED
、LIKED
等),你可以用以下查询找出所有连接到 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 的路径。