已有的neo4j图数据库的相关文章里,苏南大叔大体上就是一直不停的建库删库进行数据尝试。除了通过csv文件直接导入数据之外,neo4j也有自己的查询语言cypher,可以直接插入数据。对比大家已经熟知的sql,业内称cyphercql语言。从本文开始,苏南大叔开始涉及neo4j的专有cypher查询语言的介绍。

苏南大叔:neo4j图数据库,如何使用create语句创建节点和关系数据? - cypher-create
neo4j图数据库,如何使用create语句创建节点和关系数据?(图6-1)

大家好,这里是苏南大叔的“程序如此灵动”博客,这里介绍苏南大叔和计算机代码的故事。本文讲述如何使用普通的语句,来插入一个节点或一条关系。本文测试环境:neo4j@4.4.5win10。龙套主角还是neo4j官方自带的movie例子。

因为苏南大叔使用的是neo4j的社区版,只能用一个默认的图neo4j。这里就省略了create database neo4juse 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})
TheMatrixKeanu都是那个不入数据库的变量。
这个标签就类似原来的table的作用,节点里面的属性就是原来的字段名。

苏南大叔:neo4j图数据库,如何使用create语句创建节点和关系数据? - cql-all
neo4j图数据库,如何使用create语句创建节点和关系数据?(图6-2)

说明:
节点可以不指定标签,或者指定多个标签。比如:

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)

对于已有的两个节点,可以使用先matchcreate的方式,例如:

match (sunan:Person{name:'sunan'}),(sunan2:Person{name:'sunan2'}) 
create (sunan)-[r:similar]->(sunan2) return r;
单独执行的create语句,没有上下文指出node1node2的话,就会自动创建对应空结点。这样的话是不符合大家的初衷的。这里非常容易忽略误解!必须配合上下文!

这里把Keanu节点和TheMatrix节点建立类型为ACTED_IN的关系,这个关系的属性是:rolesNeo

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图数据库,如何使用create语句创建节点和关系数据? - 必需指定type
neo4j图数据库,如何使用create语句创建节点和关系数据?(图6-3)

关系左右节点变量如果在上下文中不存在的话,会建立两个空节点。也就是说,在neo4j browser的不同输入执行框里面,不存在上下文关系。这就引入下一个“语句执行的时机”的话题。

可能错误的使用方式

这个cqlsql语句一个非常重大的区别开始显示了。sql一条一条的执行没有问题,一般不会出错。而这个cqlbrowser里面一条条的执行的话,可能就有问题了。主要的问题是变量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)

苏南大叔:neo4j图数据库,如何使用create语句创建节点和关系数据? - 错误的执行结果
neo4j图数据库,如何使用create语句创建节点和关系数据?(图6-4)

两个节点变成了四个节点,关系被绑定到了两个错误的空节点上。

如果三条语句在一起执行的话,则是正确的结果:

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)

苏南大叔:neo4j图数据库,如何使用create语句创建节点和关系数据? - 正确的执行结果
neo4j图数据库,如何使用create语句创建节点和关系数据?(图6-5)

上述三句并不一致的语句,还可以合并输入,也会得到正确的结果:

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)

苏南大叔:neo4j图数据库,如何使用create语句创建节点和关系数据? - 合并输入
neo4j图数据库,如何使用create语句创建节点和关系数据?(图6-6)

特殊的使用方式

一个节点多个类型

CREATE (DiyMovie:Movie:Movie2 {title:'The Matrix2', released:2022})

可以设置多个标签,属性是绑定在节点上的,并不是标签上,写多个:就可以。

两个节点多条关系

两个节点之间有多个关系的话,就执行多次create里面就好了。

CREATE (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix),
       (Keanu)-[:ACTED_IN2 {roles:['Neo']}]->(TheMatrix)

参考文献

综述

本文里主要讲述的就是非常非常基础的插入数据的动作,一般来说,插入单独的节点是没有意义的,插入单独的关系也是不能实现的。只有两个节点加上一条关系,才是条完整的记录。所以,完成一个具有完整意义的数据插入,实际上至少执行三条语句才能实现:插入两个节点,两个节点上建立个关系。

更多cypher的语句介绍,请点击苏南大叔的博客:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。