neo4j图数据库,如何使用create语句创建节点和关系数据?
发布于 作者:苏南大叔 来源:程序如此灵动~
已有的neo4j图数据库的相关文章里,苏南大叔大体上就是一直不停的建库删库进行数据尝试。除了通过csv文件直接导入数据之外,neo4j也有自己的查询语言cypher,可以直接插入数据。对比大家已经熟知的sql,业内称cypher为cql语言。从本文开始,苏南大叔开始涉及neo4j的专有cypher查询语言的介绍。

大家好,这里是苏南大叔的“程序如此灵动”博客,这里介绍苏南大叔和计算机代码的故事。本文讲述如何使用普通的语句,来插入一个节点或一条关系。本文测试环境:neo4j@4.4.5,win10。龙套主角还是neo4j官方自带的movie例子。
因为苏南大叔使用的是neo4j的社区版,只能用一个默认的图neo4j。这里就省略了create database neo4j和use neo4j的步骤了。
带属性的节点和关系
首先,要说明的是neo4j数据库里面的数据是什么样的概念。一个图就是由不同的节点,以及这些不同节点之间的关系所组成的。另外,需要明确的是:
(NODE1) - [:RELATION] -> (NODE2)- 实体有标签,实体可以用一个
string表示,但是它可以有属性,可以是个object。 - 关系有类型,关系可以用一个
string表示,但是它可以有属性,可以是个object。
这里,还是举个例子来说明:
(苏南大叔) - [:毕业于] -> (北京大学)实际上,上述语句可以扩充思路成这样:
| 实体或关系 | 扩充了属性和标签后 |
|---|---|
| (苏南大叔) | (苏南大叔:Person{name:"sunan",website:"newsn.net'}) |
| [:毕业于] | [:毕业于{year:"2022",degree="博士"}] |
| (北京大学) | (北京大学:University{titles:['985','211','双一流']}) |
(苏南大叔:Person{name:"sunan",website:"newsn.net'}) - [:毕业于{year:"2022",degree="博士"}] -> (北京大学:University{titles:['985','211','双一流']})本文中出现了2个冒号的用法,在节点(node:Lable)中是用于修饰标签的,标签可有可无。在关系[:type]中是用于描述类型的,类型还是必须存在的。
| 使用方法 | 说明 |
|---|---|
| (node) | 没有标签的节点 |
| (node:Lable) | 有一个标签的节点 |
| (node:Lable1:Label2) | 有两个标签的节点 |
| [:type] | 类型为type的关系 |
cypher语句插入节点
cypher语句插入节点的基本格式是:
CREATE (n:Label {prop:'value'})其中n部分仅仅是个临时变量,是可以随便写甚至不写,写了也不记录在数据库里面。也就是说:使用者最关心的部分居然是数据库最不关心的部分。是不是有点讽刺...
例如:
建立电影《黑客帝国》(变量是TheMatrix,标签是Movie)节点:
CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})建立演员"Keanu Reeves"(变量是Keanu,标签是Person)的节点:
CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})TheMatrix和Keanu都是那个不入数据库的变量。
这个标签就类似原来的table的作用,节点里面的属性就是原来的字段名。

说明:
节点可以不指定标签,或者指定多个标签。比如:
CREATE (sunan:Person:Student {name:'sunan',www:'newsn.net'})
CREATE (sunan2 {name:'sunan2',www:'newsn.net'})或者只有一个标签,甚至只有属性。
CREATE (:Person {name:'sunan3',www:'newsn.net'})
CREATE ({name:'sunan4',www:'newsn.net'})更有甚者,下面的两个例子也是可以成立的。从效果上看,两者是等价的,都是建立了一个啥都没有的节点。
CREATE (sunan5)
CREATE ()cypher语句建立关系
cypher语句插入关系的基本格式是:
CREATE (node1)-[:type {prop: 'value'}]->(node2)对于已有的两个节点,可以使用先match后create的方式,例如:
match (sunan:Person{name:'sunan'}),(sunan2:Person{name:'sunan2'})
create (sunan)-[r:similar]->(sunan2) return r;单独执行的create语句,没有上下文指出node1和node2的话,就会自动创建对应空结点。这样的话是不符合大家的初衷的。这里非常容易忽略误解!必须配合上下文!
这里把Keanu节点和TheMatrix节点建立类型为ACTED_IN的关系,这个关系的属性是:roles为Neo。
CREATE (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix)对于这条关系来说,左边和右边都是节点,括号里面是变量,节点的类型是:ACTED_IN,属性可以不填的,但是类型是必填的。否则可能会遇到如下错误信息:
Exactly one relationship type must be specified for CREATE. Did you forget to prefix your relationship type with a ':'? (line 1, column 10 (offset: 9))
"CREATE ()-[]->()"
关系左右节点变量如果在上下文中不存在的话,会建立两个空节点。也就是说,在neo4j browser的不同输入执行框里面,不存在上下文关系。这就引入下一个“语句执行的时机”的话题。
可能错误的使用方式
这个cql和sql语句一个非常重大的区别开始显示了。sql一条一条的执行没有问题,一般不会出错。而这个cql在browser里面一条条的执行的话,可能就有问题了。主要的问题是变量n,出了上下文就失效。
如果在browser里面分开执行上述movie例子的语句的话,会得到这个错误的结果:
CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})
CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})CREATE (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix)
两个节点变成了四个节点,关系被绑定到了两个错误的空节点上。
如果三条语句在一起执行的话,则是正确的结果:
CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})
CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})
CREATE (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix)
上述三句并不一致的语句,还可以合并输入,也会得到正确的结果:
CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'}),
(Keanu:Person {name:'Keanu Reeves', born:1964}),
(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix)
特殊的使用方式
一个节点多个类型
CREATE (DiyMovie:Movie:Movie2 {title:'The Matrix2', released:2022})可以设置多个标签,属性是绑定在节点上的,并不是标签上,写多个:就可以。
两个节点多条关系
两个节点之间有多个关系的话,就执行多次create里面就好了。
CREATE (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix),
(Keanu)-[:ACTED_IN2 {roles:['Neo']}]->(TheMatrix)使用汉字并建立双标签
CREATE (十二度:商品:啤酒 {名称:'唐山12度啤酒',编码:'6914340999976',价格:36,规格:'500ml*12',有效期:'9个月'});注意:数字开头不能用做变量名。也就是说"十二度"的字样不能写成"12度",会报错。

参考文献
- https://neo4j.com/docs/cypher-manual/current/query-tuning/basic-example/#_movies
- https://newsn.net/say/neo4j-win.html
综述
本文里主要讲述的就是非常非常基础的插入数据的动作,一般来说,插入单独的节点是没有意义的,插入单独的关系也是不能实现的。只有两个节点加上一条关系,才是条完整的记录。所以,完成一个具有完整意义的数据插入,实际上至少执行三条语句才能实现:插入两个节点,两个节点上建立个关系。
更多cypher的语句介绍,请点击苏南大叔的博客: