## Neo4j的cyhper基本语法 ### 1. 创建节点和关系 #### 1.1创建节点 ```sql create (n) create (n),(m) create(n:Movie) create(n:Movie:Person) # 创建一个带有标签(Person)和属性(name:'TEST-NAME', age:1)的节点 create(n:Person {name:'qiusj',age:18}) # 返回创建的节点 CREATE(n:TEST {name:'TEST-NAME1', age:2}) return n ``` #### 1.2 创建关系 ```sql # 创建两个节点之间的关系 MATCH (a:TEST),(b:TEST) WHERE a.name = 'TEST-NAME' AND b.name = 'TEST-NAME1' CREATE (a)-[r:RELTYPE] -> (b) RETURN r # 创建两个节点之间的关系,并调用两个节点的属性: MATCH (a:TEST),(b:TEST) WHERE a.name = 'TEST-NAME' AND b.name = 'TEST-NAME1' CREATE (a)-[r:RELTYPE { name: a.name + b.name}] -> (b) RETURN r ``` #### 1.3 `merge` 命令 在Neo4j数据库中,**MERGE**命令是一个非常强大的工具,它结合了**CREATE**和**MATCH**命令的功能。当你需要确保一个特定的节点或关系在图中存在时,MERGE命令就显得尤为重要。如果该节点或关系不存在,MERGE将会创建它;如果已经存在,MERGE则会匹配到这个现有的元素。 > 如果这个节点已经存在,那么MERGE命令的作用就相当于MATCH命令。判断是否存在的方式是表达式中所有的属性组合匹配的:如 MERGE (p:Person {name: 'Alice'}) RETURN p;只要在已有的Person中name属性没有等于'Alice'的就是不存在,MERGE (p:Person {name: 'Alice,age:18}) 则要求现有的Person中的name和age都不相同才表示不存在 ```sql MERGE (robert:Person { name: 'Robert' }) RETURN robert, labels(robert) ``` MERGE还可以用来创建节点之间的关系。如果两个节点之间的关系不存在,MERGE会创建这个关系。例如,以下命令会创建一个名为"Robert"的Person节点和一个名为"hanscal"的Person节点之间的FAMILY关系: ```sql MATCH (n:Person { name: 'Robert' }), (m:Person { name: "hanscal" }) MERGE (n)-[r:FAMILY]->(m) RETURN n.name, type(r), m.name ``` **使用ON CREATE和ON MATCH** MERGE命令可以与**ON CREATE**和**ON MATCH**子句结合使用,这允许你根据元素是被匹配到还是被创建来执行不同的操作。例如,以下命令在创建新节点时设置一个时间戳属性: ```sql MERGE (c:Person { name: 'Hanscal' }) ON CREATE SET c.create = timestamp() RETURN c.name, c.create ``` 如果节点"Hanscal"已经存在,则不会设置任何属性。相反,如果使用**ON MATCH**,则只有在匹配到节点时才会设置属性。 **批量操作** MERGE命令也可以用于批量操作,快速创建大量的节点和关系。例如,以下命令会将所有Person节点的出生地属性与City节点连接起来,并创建BORN_IN关系: ```sql MATCH (person:Person) MERGE (city:City { name: person.bornIn }) MERGE (person)-[r:BORN_IN]->(city) RETURN person.name, person.bornIn, city ``` 总的来说,`MERGE`命令在确保数据一致性和避免重复创建相同的元素时非常有用。 **约束与 MERGE 命令的关系** - **唯一性约束**:确保指定标签的节点在特定属性上具有唯一性,是 Neo4j 保证数据完整性的重要机制 - MERGE 命令行为: - 若匹配条件的节点 / 关系存在,则返回现有节点 / 关系 - 若不存在,则创建新的节点 / 关系 - **冲突点**:当 MERGE 的匹配条件触发唯一性约束时,会因重复数据导致操作失败 #### 1.4 添加属性 方案 1:使用 MATCH 而非 MERGE(推荐) ```sql MATCH (p:Person {name: 'Robert'}) SET p.age = 18 RETURN p; ``` 方案 2:修改 MERGE 语句避免重复创建 ```sql # 安全的MERGE写法(先检查节点是否存在) MERGE (p:Person {name: 'Robert'}) # 仅当节点不存在时才创建新属性(避免冲突) ON CREATE SET p.create = timestamp() # 无论是否创建都可以设置属性(不会触发约束) SET p.money = 1 RETURN p; ``` #### 1.5 修改节点的关系类型 在 Neo4j 中,关系类型(Relationship Type)是不可变的,无法直接修改。若要更改关系类型,需通过以下步骤实现:**创建新关系 → 复制属性 → 删除旧关系**。以下是详细方法: **方法一:使用 Cypher 手动转换关系类型** ```sql // 示例:将 KNOWS 关系转换为 FRIEND 关系 MATCH (p1:Person)-[r:KNOWS]->(p2:Person) WHERE p1.name = 'Alice' AND p2.name = 'Bob' // 创建新类型的关系 CREATE (p1)-[r2:FRIEND]->(p2) // 复制旧关系的所有属性到新关系 SET r2 = r // 删除旧关系 DELETE r RETURN p1, r2, p2; ``` ### 2.查询语法 > match、optional match、where、start和aggregation聚合 #### 2.1 match语法 **简单查询** ```sql # 查询所有节点 match (n) return n # 查询指定标签的节点 match (n:Person) return n # 查询指定标签和属性的节点 match (n:Person {name:"张三"}) return n ``` **关系查询** ```sql # 查询出度1的节点 match (n:Person{name:"张三"})-[r]->(m) return m match (n:Person{name:"zhangsan"})-->(m) return m # 查询入度1节点: match (n:Person{name:"zhangsan"})<-[r]-(m) return m match (n:Person{name:"zhangsan"})<--(m) return m ``` ### 3.删除节点 - 删除无关系的孤立节点 使用`DELETE`语句直接删除节点 ```sql // 删除单个节点(无关系) MATCH (p:Person {name: 'Alice'}) DELETE p; // 批量删除符合条件的节点 MATCH (p:Person) WHERE p.age < 18 DELETE p; ``` - 删除带有关联关系的节点 需先删除关系,再删除节点。可使用`DETACH DELETE`一次性完成: ```sql // 方法1:分步删除(手动删除关系) MATCH (p:Person {name: 'Bob'})-[r]->() DELETE r; // 先删除所有外出关系 MATCH (p:Person {name: 'Bob'}) DELETE p; // 再删除节点 // 方法2:使用DETACH DELETE(推荐) MATCH (p:Person {name: 'Charlie'}) DETACH DELETE p; // 自动删除节点及其所有关系 ``` - 基于关系条件删除节点 删除符合特定关系条件的节点: ```sql // 删除所有没有朋友的人(无FOLLOWS关系) MATCH (p:Person) WHERE NOT (p)-[:FOLLOWS]->() DELETE p; // 删除被超过100人关注的明星节点 MATCH (s:Star)<-[r:FOLLOWS]-() WITH s, count(r) as followers WHERE followers > 100 DETACH DELETE s; ``` - 删除整个标签的所有节点 ```sql // 删除所有Person节点及其关系 MATCH (p:Person) DETACH DELETE p; // 更安全的分批删除方法 CALL apoc.periodic.iterate( "MATCH (p:Person) RETURN p", "DETACH DELETE p", {batchSize:1000, parallel:false} ); ``` - 删除节点并返回删除数量 ```sql MATCH (p:Person) WHERE p.lastLogin < date("2023-01-01") DETACH DELETE p RETURN count(*) as deletedNodes; ``` ### 4. 删除关系 场景一:删除特定关系 ```sql // 方法1:通过匹配节点和关系类型删除 MATCH (p1:Person {name: 'Alice'})-[r:FRIEND]->(p2:Person {name: 'Bob'}) DELETE r; // 方法2:使用更精确的匹配条件(如属性) MATCH (p1:Person)-[r:WORKS_ON {projectId: 'PRJ-123'}]->(p2:Project) DELETE r; ``` 场景二:只有查询返回的ID ```sql // 方法1:使用关系ID直接删除 MATCH ()-[r]->() WHERE id(r) = 5678 // 替换为实际关系ID DELETE r; // 仅删除关系,保留节点 // 方法2:验证关系后删除 MATCH ()-[r]->() WHERE id(r) = 5678 RETURN r; // 先查询确认关系是否存在 // 确认无误后执行删除 MATCH ()-[r]->() WHERE id(r) = 5678 DELETE r; ```