一. 前言

本文主要使用Neo4j中常见的CQL语句实现一个简单的案例,是十分基础的。

作者的能力十分有限,若有文章有误,欢迎指正。若您有任何想法,欢迎交流。

二. Neo4j介绍

1. 什么是Neo4j

Neo4j是一个开源的NoSQL图形数据库,2003 年开始开发,使用 scala和java 语言,2007年开始发布。

  • 是世界上最先进的图数据库之一,提供原生的图数据存储,检索和处理;

  • 采用属性图模型(Property graph model),极大的完善和丰富图数据模型;

  • 专属查询语言 Cypher,直观,高效;

官网:https://neo4j.com/

2.Neo4j数据模型

Neo4j作为图数据库,数据模型肯定有别于常见的关系型数据库。
图数据库数据模型的主要构建块是:节点关系属性
以下是一个简单的属性图例子:


不难看出,圆圈代表各个节点,各节点之间用有方向的箭头表示关系。

三. CQL语句

CQL代表Cypher查询语言,在Neo4j中,我们使用CQL语句对数据库进行操作。
以下是一些常用的CQL命令:

序号

CQL命令

用法

1

CREATE

创建节点,关系和属性

2

MATCH

检索有关节点,关系和属性数据

3

RETURN

返回查询结果

4

WHERE

提供条件过滤检索数据

5

DELETE

删除节点和关系

6

REMOVE

删除节点和关系的属性

7

ORDER BY

排序检索数据

8

SET

添加或更新标签

是不是与SQL语句有些类似?接下来,我们通过构建小猪佩奇的家庭关系图,学习简单的CQL语句。

1.创建

我们知道,小猪佩奇一家主要有猪爸爸、猪妈妈、佩奇、乔治。
我们在Neo4j中该如何表示呢,我们可以通过创建四个节点来表示他们。
我们通过如下的语句先来创建一个猪爸爸的节点。

create (:pig{name:'猪爸爸',age:10})

在此语句中,creat()创建了一个节点,括号内:后面的pig为节点标签名称
{}内的键值对,表示该节点所拥有的属性

我们也可以创建多个节点,各节点之间使用,隔开:

create(:pig{name:"佩奇", age:5}),(:pig{name:"乔治", age:3});

此外,还可以在创建节点的同时创建关系。

--- 注意:这里会创建两个节点(猪爸爸和猪妈妈)
create(:pig{name:'猪妈妈',age:9})-[:夫妻{age:5}]->(:pig{name:"猪爸爸",age:10});

需要注意的是,关系是有方向的,
使用(节点a) - [关系] -> (节点b)来表示,其中关系也可以有属性(这里为夫妻的婚龄)

创建关系的内容在后面也会讲解。

至此,我们创建好了如下关系:

2.查询

假如我们想要查询某一个成员的信息,我们该如何查询呢?

我们可以使用match()语句来查询,以查询佩奇的信息为例,使用如下语句:

match(p:pig{name:'佩奇'}) return p

这样就可以查询到佩奇的相关信息,如下图

需要注意的是,在match()之后,需要使用return()进行返回。

这里的p可以任意,有点类似于函数中的形式参数。


刚才我们说到,可以在创建节点的时候可以连同关系一起创建,假如我们想给已有的关系创建节点,我们应该如何操作?

我们可以先查询出需要创建关系的节点,然后创建关系,如下方语句所示:

match (a:pig{name:'猪爸爸'}) match (b:pig{name:'乔治'}) create (a)-[p:父子]->(b)
--- 也可以将第二个match替换为逗号,查询多个节点

我们将其余的关系补全:

--- 创建姐弟关系
match (a:pig{name:'佩奇'}) match (b:pig{name:'乔治'}) create (a)-[p:姐弟]->(b)
--- 创建猪妈妈与佩奇、乔治的关系
match (a:pig{name:'猪妈妈'}) match (b:pig{name:'佩奇'}) create (a)-[p:母女]->(b)
match (a:pig{name:'猪妈妈'}) match (b:pig{name:'乔治'}) create (a)-[p:母子]->(b)
--- 创建猪爸爸与佩奇的关系
match (a:pig{name:'猪爸爸'}) match (b:pig{name:'佩奇'}) create (a)-[p:父女]->(b)

如果我们想单独查询某两个成员之间的关系,我们可以使用
match (节点a) - [关系] -> (节点b) return a,b的方法来查询并返回:

match (a:pig{name:'佩奇'}) - [:姐弟] -> (b:pig{name:'乔治'}) return a,b

查询到的结果如下:


假如我们想查询所有家庭成员以及成员之间的关系,即整个家庭关系图,我们可以使用如下语句:

MATCH (n:pig) RETURN n

这里查询了所有标签为pig的节点并返回。

在语句的最后也可以使用LIMIT子句或SKIP来过滤或限制查询返回的行数( 简单理解为:LIMIT返回前几行,SKIP忽略前几行。)

而这里的条数较少,效果不明显,仅为对LIMITSKIP的补充解释。

3.修改

假如佩奇长大了一岁,我们该如何修改佩奇的年龄呢?
我们可以先将佩奇的信息查询出来,接着再修改年龄,语句如下:
佩奇原先的年龄为5岁,我们将其修改为6岁。

match(a:pig{name:'佩奇'}) set a.age=6 return a

并将佩奇的节点返回,查看修改后的属性。

可以看到age已被修改为6岁,修改成功。


我们也可以结合where子句来使用,如将pig标签中年龄为10的节点的年龄修改为11岁,并将节点返回,语句如下:

match (a:pig) where a.age=10 set a.age=11 return a

如此一来,原先年龄为10的节点(猪爸爸)的年龄就被更改为了11岁。


此外,也可以根据id来修改信息,在Neo4j中,节点自带一个<id>属性,而在where子句中,也可以通过使用id()函数来查询相应节点并进行操作,以下是一个通过id来修改年龄的例子:

match (a:pig) where id(a)=5 set a.age=4 return a

通过此语句,将id为5的节点(即乔治)的年龄更改为了4。

需要注意,where子句中的id()函数,所以才能使用id(a)的形式。


关系的属性也可以修改,如我们可以修改猪妈妈与猪爸爸的婚龄:

match(a:pig{name:"猪妈妈"})-[r:夫妻]->(b:pig{name:"猪爸爸"}) set r.age=6;

如下图,夫妻关系中的婚龄属性已被修改。

4.删除

假设家庭成员中存在猪爷爷(节点已经提前被添加好,但并未删除),现在猪爷爷去世,我们需要将其删除。

我们可以使用以下语句对猪爷爷的节点进行删除:

match(a:pig{name:'猪爷爷'}) delete a;

但需要注意的是,该语句只适用于与其他节点没有关系的情况,如果存在关系,则无法删除,如下图所示:


所以我们在删除节点前,需要先删除与该节点有关的关系。

先删除关系:

match (a:pig{name:'猪爷爷'})-[p:父子]-(b:pig{name:'猪爸爸'}) delete p;

再删除节点:

match(a:pig{name:'猪爷爷'}) delete a;

我们也可以针对标签,对节点进行删除,使用以下语句:

match(a:pig) delete a

同样地,删除节点前也需要先删除关系。


假如我们需要清空数据库中的所有内容,我们可以使用如下语句:

MATCH (n) DETACH DELETE n

该语句能够快速清空数据库,且无需先删除关系。


除了使用delete进行删除关系和节点以外,还可以使用remove删除标签和属性。

可以使用以下语句删除节点的属性,以删除乔治的age属性为例:

match(p:pig{name:'乔治'}) remove p.age

可以看到,乔治的age属性已被删除。

同样可以使用以下语句删除节点的标签,以删除乔治的pig标签为例:

match(p:pig{name:'乔治'}) remove p:pig

四. 最后

至此,Neo4j与CQL语句的基本介绍已经结束。

希望本文对您有用!

一个老鼠人