手把手教你入门 neo4j 图数据库

631 阅读8分钟

这是我参与更文挑战的第28天,活动详情查看: 更文挑战

什么是 Neo4j

Neo4j 是一个很流行的图数据库,和图形理论类似,有三个主要的概念:

  • 节点
  • 关系
  • 属性

节点和关系都包含属性,而关系连接节点,且可以单向和双向。在 Neo4j 的直观页面上,节点用圆圈表示,关系用线和键头表示。

Neo4j 的优缺点

优点:

  • 很容易存储大量的连接数据
  • 检索数据也很快速,结果很直观
  • 上手比较容易, CQL 语言可读性强
  • 数据量不过千万的话,性能基本能够保证

缺点:

  • 只能是单机版本,如果有海量数据,没法做分布式
  • 图数据结构导致写入性能差,实时性读写跟不上

Neo4j 用途

常见于以下用途:

  • 社交网络
  • 推荐系统
  • 欺诈分析
  • Web 安全(垃圾邮件等等)

Neo4j 安装

很简单,进入官网,自行解决: neo4j.com

CQL

CQL 是 Neo4j 图形数据库的查询语言,下面通过案例来讲解主要的命令。

CREATE 命令

CREATE 命令主要功能是:

  • 创建节点
  • 创建关系
  • 为节点或者关系创建标签

创建一个名为 dept ,标签为 Dept ,并且有 dname 和 location 两个属性的节点,dept 只是一个类似变量的东西,可以命名为 d 或者其他字符串,不是该节点的属性:

CREATE (dept:Dept { dname:"qjfy",location:"hky" })

创建一个名为 emp ,标签为 Employee ,并且有 name 和 dname 两个属性的节点,emp 只是一个类似变量的东西,可以命名为 e 或者其他字符串,不是该节点的属性:

CREATE (emp:Employee{name:"wys",dname:"qjfy"})

创建一个名为 emp1 ,标签为 Employee 和 Actor 的没有属性的节点,emp1 只是一个类似变量的东西,可以命名为 e1或者其他字符串,不是该节点的属性:

CREATE (emp1: Employee:Actor)

MATCH 命令

MATCH 命令主要功能是:

  • 获取节点、关系、属性的数据

一般 MATCH 命令需要和 RETURN 命令结合使用,不能单独使用 MATCH 命令,否则会报错 Neo.ClientError.Statement.SyntaxError 。

RETURN 命令

RETURN 命令主要功能是:

  • 检索节点的属性
  • 检索节点和关联关系的属性

同样的,一般 MATCH 命令需要和 RETURN 命令结合使用,不能单独使用 RETURN 命令,否则会报错 Neo.ClientError.Statement.SyntaxError 。

MATCH & RETURN 命令

MATCH & RETURN 命令的主要功能是:

  • 检索节点的属性
  • 检索节点和关联关系的属性

返回标签为 Dept 的所有节点的属性 dname 和 location ,因为只有一个节点,所以只返回了一行数据。这里的 dept 类似于对象名,可以任意其他的字符串代替,如换成 d :

MATCH (dept: Dept) RETURN dept.dname,dept.location

返回结果:

dept.dnamedept.location
"qjfy""hky"

或者 :

MATCH (d: Dept) RETURN d.dname,d.location

返回结果:

d.dnamed.location
"qjfy""hky"

在不指定返回属性的时候,会显示图结构,如下图所示,这里多出来的一个 属性是数据库内部设置的,和 mysql 中的 id 类似:

MATCH (dept: Dept) RETURN dept

ID 属性

是节点和关系的默认的内部属性。 当创建一个新的节点或关系时,其内部会分配一个数字,如果再创建其他新的节点或者关系,它会自动递增。 ID 上限约为 35 亿。

创建关系

1.我们已经有了 Dept 和 Employee 两个节点,现在创建没有属性的关系连接它们,关系标签为 WORK_AT ,关系名称为 r :

MATCH (e: Employee),(d: Dept) CREATE (e)-[r:WORK_AT]->(d) 

创建成功,然后使用查询语句查看关系:

MATCH (e)-[r:WORK_AT]->(d) RETURN r

结果中 start 是 id 为 5026 的 Employee 标签的节点,end 是 id 为 5024 的 Dept 标签的节点:

{
  "identity": 14452,
  "start": 5026,
  "end": 5024,
  "type": "WORK_AT",
  "properties": {

  }
}

2.我们现在创建两个节点之间有 sal 属性的关系:

MATCH (e: Employee),(d: Dept) CREATE (e)-[r:WORK_AT{sal:1000}]->(d) 

创建成功,然后使用查询语句查看关系:

MATCH  (e)-[r:WORK_AT{sal:1000}]->(d) return r

结果:

{
  "identity": 14453,
  "start": 5026,
  "end": 5024,
  "type": "WORK_AT",
  "properties": {
  "sal": 1000
  }
}

3.创建不存在于数据库中不带属性的的两个节点和关系:

CREATE (w1:WeChatUser)-[like:LIKES]->(w2:WeChatUser) 

创建成功之后,使用查询语句查看关系:

MATCH (w1)-[like:LIKES]->(w2) RETURN like

结果中 start 是 id 为 5027 的 WeChatUser 标签的节点,end 是 id 为 5028 的 WeChatUser 标签的节点:

{
  "identity": 14454,
  "start": 5027,
  "end": 5028,
  "type": "LIKES",
  "properties": {

  }
}

4.创建不存在于数据库中带属性的的两个节点和关系:

CREATE (w1:WeChatUser{name:"wys"})-[like:LIKES{rating:100}]->(w2:WeChatUser{name:"ppy"}) 

创建成功之后,使用查询语句查看关系:

MATCH (w1)-[like:LIKES{rating:100}]->(w2) RETURN like

结果中 start 是 id 为 5029 的 WeChatUser 标签的节点,end 是 id 为 5030 的 WeChatUser 标签的节点:

{
  "identity": 14455,
  "start": 5029,
  "end": 5030,
  "type": "LIKES",
  "properties": {
  "rating": 100
  }
}	

5.查询连接在关系 LIKES 两边的节点:

MATCH (a)-[r:LIKES]->(b) RETURN a,b

在结果中的没有内容的两个节点,就是我们在第 3 步中没有使用属性直接创建的两个节点。内容为 ppy 和 wys 的两个节点就是我们在第 4 步中使用属性创建的两个节点。

WHERE 命令

类似于 SQL ,WHERE 命令来过滤 MATCH 查询的结果。

过滤出 name 为 wys 或者 dname 为 qjfy 的 Employee 标签的节点:

MATCH (e:Employee) WHERE e.name = 'wys' OR e.dname = 'qjfy' RETURN e

DELETE 命令

DELETE 命令主要的功能是:

  • 删除节点及其属性
  • 删除节点之间的关系

删除现有的所有 Employee 标签的节点(前提是这些节点上没有其他关系连接,否则会报错):

MATCH (e: Employee) DELETE e

删除现有的所有 LIKE 关系及其有关的节点:

MATCH (a:WeChatUser)-[r]->(b:WeChatUser) DELETE a,r,b

REMOVE 命令

REMOVE 命令主要的功能是:

  • 移除节点或者关系的属性
  • 移除节点或者关系的标签

1.现在创建一个带有属性的节点:

CREATE (emp:Employee{name:"wys",dname:"qjfy"})

移除 dname 属性:

MATCH (emp:Employee { name:"wys" }) REMOVE emp.dname RETURN emp

2.创建一个有多个标签的节点:

CREATE (emp:Employee:Actor)

移除了节点的 Actor 标签:

MATCH (e: Employee)  REMOVE e: Actor

SET 命令

SET 命令的主要功能是:

  • 向现有节点或关系添加新属性
  • 添加或更新属性值

现在创建一个的节点:

CREATE (emp:Employee{name:"wys"})

开始添加一个属性 age ,并设置值为 27 :

MATCH (e: Employee) WHERE e.name="wys" SET e.age = '27' RETURN e

ORDER BY 命令

类似于 SQL ,ORDER BY 命令对 MATCH 查询返回的结果进行排序。

再创建一个年龄为 28 的 Employee 节点:

CREATE (emp:Employee{name:"wyt",age:'28'})

按照 age 将 Employee 节点排序,默认升序排序:

MATCH (e:Employee) RETURN e ORDER BY e.age

LIMIT 和 SKIP 命令

类似于 SQL, LIMIT 命令限制查询返回的行数,SKIP 命令过滤掉查询返回的前面若干行。

只返回一个 Employee 节点:

MATCH (emp:Employee) RETURN emp LIMIT 1

跳过第一个结果,把第二个及之后的结果返回:

MATCH (emp:Employee) RETURN emp SKIP 1

IN 命令

类似于 SQL, IN 命令允许在 WHERE 子句中规定多个值。

只返回名为 wys 的节点:

MATCH (e:Employee)  WHERE e.name IN ['wys'] RETURN e

NULL 值

NULL 值表对节点或关系的属性的缺失值或未定义值。

返回 Employee 标签中 age 属性为空的节点:

MATCH (e:Employee)  WHERE e.age IS NULL RETURN e

MERGE 命令

MERGE 类似于 CREATE 命令和 MATCH 命令的组合,主要功能是:

  • 创建节点、关系或者属性
  • 从数据库检索数据

如果我们使用 CREATE 重复执行两次,因为 CREATE 命令总是向数据库添加新的节点,所以会创建两个一样的节点,但是将下面的语句重复执行两次,则只会创建一个节点:

MERGE (e: Employee{ name:"wangda"})

所以 MERGE 命令检查该节点在数据库中是否存在。 如果它不存在创建新节点。 否则它不创建新的。

UNION 命令

UNION 命令主要有两个:

  • UNION,它将两组结果中的公共行组合并返回到一组结果中。 它不返回两个节点中重复的行。结果列名称和数据类型应该相同。

返回的结果中的 name 列没有重复行:

MATCH (a:Employee) return a.name as name UNION MATCH (b:Actor) return b.name as name
  • UNION ALL,它结合并返回两个结果集的所有行组成一个结果集。它返回两个节点中的重复行。同上,列名称和数据类型应该是相同的。

返回的结果中的 name 列有重复行:

MATCH (a:Employee) return a.name as name UNION ALL MATCH (b:Actor) return b.name as name