1、图数据库RedisGraph介绍

RedisGraph在Redis上实现了一种高性能内存图数据库。该项目作为Redis模块开源提供,支持openCyper查询语言,可完成图的创建、查询、条件匹配等操作。为支持高效的图搜索操作,RedisGraph底层实现了一种称为Hexastore的三元组存储结构。本文介绍了RedisGraph的一些内部设计和特性,并展示其当前所具备的能力。

2、环境搭建

2.1、安装redis

redis.io官方下载链接任意选择一种安装方法,安装redis

2.2、下载redisgraph,配置启动环境

1、在redis.io官方redisgraph模块中下载redisgraph模块。

2、将redistraph加载到Redis中,我们建议在启动过程中通过将以下内容添加到redis.conf文件中,让Redis加载redistraph:

loadmodule /path/to/module/src/redisgraph.so

// demo
loadmodule /home/hjm/RedisGraph/src/redisgraph.so THREAD_COUNT 4 CACHE_SIZE 25 OMP_THREAD_COUNT 1 MAINTAIN_TRANSPOSED_MATRICES yes

在上面的行中,将/path/to/module/src/redisgraph.so替换为redistraph库的实际路径。如果Redis作为服务运行,则必须确保redis用户(默认)具有访问redisgraph.so所需的文件/文件夹权限。

或者,可以使用以下命令行参数语法让Redis load redistraph:

~/$ redis-server --loadmodule /path/to/module/src/redisgraph.so

成功加载redistraph后,您的Redis日志应具有类似以下内容的行:

...
30707:M 20 Jun 02:08:12.314 * Module 'graph' loaded from <redacted>/src/redisgraph.so
...

3、安装RedisInsight 可视化工具

请参照官方具体操作,需要注意的是依赖的环境、文件运行需要相关权限的问题,在这里我遇到了一个问题:

在执行完./redisinsight-linux64-version命令后,报错如下:

...
RequestsDependencyWarning: urllib3 (1.26.5) or chardet (3.0.0) doesn‘t match a supported version!
...

经过一系列查找问题原因后,找到的解决方法是,运行的时候执行如下操作:

# 后台运行
[solang@solang redisinsight-1.4.0]$ nohup redisinsight-linux64-1.4.0 &

# 前台运行
[solang@solang redisinsight-1.4.0]$ ./redisinsight-linux64-1.4.0

[solang@solang ~]$ ps -ef | grep redis

solang  14964      1  0 May09 ?        00:05:11 redis-server 127.0.0.1:6379
solang  17699  17675  2 09:46 pts/2    00:00:19 redisinsight-linux64-1.4.0
solang  17703  17699  0 09:47 pts/2    00:00:07 redisinsight-linux64-1.4.0
solang  17744   5594  0 10:01 pts/1    00:00:00 grep --color=auto redis

3、RedisGraph-CQL使用

官方配置+使用教程【全英,锻炼英语水平~】

官方开发文档教程【全英,锻炼英语水平~】

快速入门

让我们使用以下查询创建一个简单的示例图:

使用 shell 方式

shell~创建两个图标签

>> GRAPH.QUERY graph:movies "CREATE (:Actor {name:'Mark Hamill', actor_id:1}), (:Actor {name:'Harrison Ford', actor_id:2}), (:Actor {name:'Carrie Fisher', actor_id:3})"

1) 1) "Labels added: 1"
   2) "Nodes created: 3"
   3) "Properties set: 6"
   4) "Query internal execution time: 0.675400 milliseconds"
   
>> GRAPH.QUERY graph:movies "CREATE (:Movie {title:'Star Wars: Episode V - The Empire Strikes Back', release_year: 1980 , movie_id:1})"
1) 1) "Labels added: 1"
   2) "Nodes created: 1"
   3) "Properties set: 3"
   4) "Query internal execution time: 0.392300 milliseconds"  
  
  
# demo
GRAPH.QUERY DEMO_GRAPH "CREATE (jim:Person{name:'Jim', age:29})-[:FRIENDS]->(pam:Person {name:'Pam', age:27})-[:WORKS]->(:Employer {name:'Dunder Mifflin'})"

shell~建立一些关系

>> GRAPH.QUERY graph:movies "MATCH (a:Actor),(m:Movie) WHERE a.actor_id = 1 AND m.movie_id = 1 CREATE (a)-[r:Acted_in {role:'Luke Skywalker'}]->(m) RETURN r"
1) 1) "r"
2) 1) 1) 1) 1) "id"
            2) (integer) 1
         2) 1) "type"
            2) "Acted_in"
         3) 1) "src_node"
            2) (integer) 0
         4) 1) "dest_node"
            2) (integer) 3
         5) 1) "properties"
            2) 1) 1) "role"
                  2) "Luke Skywalker"
3) 1) "Properties set: 1"
   2) "Relationships created: 1"
   3) "Query internal execution time: 0.664800 milliseconds"
   
   
# 对其他节点重复操作
>> GRAPH.QUERY graph:movies "MATCH (a:Actor), (m:Movie) WHERE a.actor_id = 2 AND m.movie_id = 1 CREATE (a)-[r:Acted_in {role:'Han Solo'}]->(m) RETURN r"
>> GRAPH.QUERY graph:movies "MATCH (a:Actor), (m:Movie) WHERE a.actor_id = 3 AND m.movie_id = 1 CREATE (a)-[r:Acted_in {role:'Princess Leila'}]->(m) RETURN r"

# 或者

>> GRAPH.QUERY graph:movies "CREATE (:Actor {name:'Marlo Brando', actor_id:4})-[:Acted_in {role:'Don Vito Corleone'}]->(:Movie {title:'The Godfather', release_year: 1972 , movie_id:2})"

1) 1) "Nodes created: 2"
   2) "Properties set: 6"
   3) "Relationships created: 1"
   4) "Query internal execution time: 0.848500 milliseconds"

shell~查询

# 所有电影的名字是什么?
>> GRAPH.QUERY graph:movies "MATCH (m:Movie) RETURN m.title"

1) 1) "m.title"
2) 1) 1) "Star Wars: Episode V - The Empire Strikes Back"
   2) 1) "The Godfather"
3) 1) "Query internal execution time: 0.349400 milliseconds"

# ID为1的电影的信息是什么?
>> GRAPH.QUERY graph:movies "MATCH (m:Movie) WHERE m.movie_id = 1 RETURN m"

1) 1) "m"
2) 1) 1) 1) 1) "id"
            2) (integer) 3
         2) 1) "labels"
            2) 1) "Movie"
         3) 1) "properties"
            2) 1) 1) "title"
                  2) "Star Wars: Episode V - The Empire Strikes Back"
               2) 1) "release_year"
                  2) (integer) 1980
               3) 1) "movie_id"
                  2) (integer) 1
3) 1) "Query internal execution time: 0.365800 milliseconds"

# 电影《星球大战:第五集:帝国反击战》中的演员是谁,他们扮演了什么角色?
>> GRAPH.QUERY graph:movies "MATCH (a:Actor)-[r:Acted_in]-(m:Movie) WHERE m.movie_id = 1 RETURN a.name,m.title,r.role"
1) 1) "a.name"
   2) "m.title"
   3) "r.role"
2) 1) 1) "Mark Hamill"
      2) "Star Wars: Episode V - The Empire Strikes Back"
      3) "Luke Skywalker"
   2) 1) "Harrison Ford"
      2) "Star Wars: Episode V - The Empire Strikes Back"
      3) "Han Solo"
   3) 1) "Carrie Fisher"
      2) "Star Wars: Episode V - The Empire Strikes Back"
      3) "Princess Leila"
3) 1) "Query internal execution time: 0.641200 milliseconds"
使用 RedisInsight 方式

使用redisinsight工具的话,命令简化,具体参考neo4jcql可视化的语句…

# d
MATCH (m:Actor) return m

neo4jcql参考命令如下:

CREATE创建

create语句是创建模型语句用来创建数据模型

创建节点
//创建简单节点
create (n)
//创建多个节点
create (n),(m)

//创建带标签和属性的节点并返回节点
create (n:person {name:'如来'}) return n 
                   
//demo
create (:student{name:"小红"}),(:student{name:"张三"}),(:student{name:"小明"})
创建关系

Neo4j图数据库遵循属性图模型来存储和管理其数据。

根据属性图模型,关系应该是定向的。否则,Neo4j将抛出一个错误消息。

基于方向性,Neo4j关系被分为两种主要类型。

  • 单向关系
  • 双向关系
//使用新节点创建关系
CREATE (n:person {name:'杨戬'})-[r:师傅]->(m:person {name:'玉鼎真人'}) RETURN type(r)
                                                                           
//使用已知节点创建带属性的关系
MATCH (n:person {name:'沙僧'}),(m:person{name:'唐僧'})
CREATE (n)-[r:`师傅`{relation:'师傅'}]->(m) RETURN r

//检索关系节点的详细信息
MATCH(n:person)-[r]-(m:person) RETURN n,m      
    
//demo
match (n:student{name:"小明"}),(m:student{name:"小红"})
create (n)-[r:同学{relation:"同学"}]->(m) return n.name,type(r),m.name
                                                         
match (n:student),(t:teacher)
create (t)-[r:老师]->(n) return t.name,type(r),n.name
                                                         
创建全路径
CREATE p=(:person{name:'蛟魔王'})-[:义兄]->(:person{name:'牛魔王'})<-[:义兄]-(:person {name:'鹏魔王'}) RETURN p
MATCH查询

Neo4jCQL match 命令用于

  • 从数据库取有关节点和属性的数据
  • 从数据库取有关节点,关系和属性的数据
MATCH (n:`西游`) RETURN n LIMIT 25
// 忽略前面n个数据
match (n:student)return n skip 10
RETURN返回

Neo4jCQL return子句用于

  • 检索节点的某些属性
  • 检索节点的所有属性
  • 检索节点和关联关系的某些属性
  • 检索节点和关联关系的所有属性
MATCH (n:`西游`) RETURN id(n),n.name,n.tail,n.relation
WHERE子句

像SQL一样,Neo4j CQL在CQL MATCH命令中提供了WHERE子句来过滤MATCH查询的结果

MATCH (n:person) WHERE n.name='孙悟空' or n.name='猪八戒' RETURN n
//创建关系
match (n:person),(m:person) where n.name='孙悟空' and m.name='猪八戒'
create (n)-[r:师弟]->(m) return n.name,type(r),m.name
DELETE删除

Neo4j使用CQL delete子句

  • 删除节点
  • 删除节点及相关节点和关系
//删除节点(前提:节点不存在关系)
match (n:person{name:"白龙马"}) delete n
                 
//删除关系
match(n:person{name:"沙僧"})<-[r]-(m) delete r return type(r)
                                                         
//demo
match (n:student{name:"小a"})<-[r]-(m) delete r return type(r)  
match (n:student{name:"小艾"})delete n                                                           
//删除所有数据
MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r
//删除所有关系和节点
MATCH (n)
DETACH DELETE n

REMOVE删除
create (n:student{name:"小c",age:20,class:"三年二班"})
//删除属性操作                   
match (n:student{name:"小c"}) remove n.age return n
SET子句
// 设置修改属性值操作,不存在的则新增,存在的则修改
match (n:student{name:"小c"})set n.age=20 return n 
ORDER BY排序

Neo4jCQL在MATCH命令中提供了"ORDER BY"子句,对MATCH查询返回的结果进行修改。

我们可以按升序或降序对行进行排序。默认情况下,它按升序对行进行排序。如果我们要按降序对它们进行排序,我们需要使用DESC子句。

//默认升序
match (n:student) return id(n),n.name order by id(n)
//降序
match (n:student) return id(n),n.name order by id(n) desc                            
UNION子句

与SQL一样,Neo4jCQL有两个子句,将两个不同的结果合并成一组结果

  • UNION

    它将两组结果中的公共行组合并返回到一组结果中。它不从两个节点返回重复的行。

    限制:

    结果列类型和来自两组结果的名称必须匹配,这意味着列名称应该相同,列的数据类型应该相同。

  • UNION ALL

    它结合并返回两个结果集的所有行成一个单一的结果集。它还会由两个节点重复行。

    限制:

    结果列类型,并从两个结果集的名字必须匹配,这意味着列名称应该是相同的,列的数据类型应该是相同的。

MATCH (n:role) RETURN n.name as name UNION 
MATCH (m:person) RETURN m.name as name

MATCH (n:role) RETURN n.name as name UNION ALL
MATCH (m:person) RETURN m.name as name
LIMIT和SKIP子句

Neo4jCQL已提供LIMIT子句和SKIP来过滤或限制查询返回的行数。

LIMIT返回前几行,SKIP忽略前几行

//前几行
MATCH (N:`西游`)RETURN n LIMIT 2
       
//忽略前两行
MATCH(n:person) RETURN n SKIP 2
NULL值

Neo4jCQL将空值视为对节点或关系的属性的缺失值或未定义值。

当我们创建一个具有现有节点标签名称但未指定其属性值的节点时,它将创建一个具有NULL属性值的新节点。

MATCH (n:`西游`) where n.label IS NULL RETURN id(n),n.name,n.tail,n.label
                                               
//demo
match (n:student{name:"小a"})set n.sex=null return n                                             
match (n:student)where n.sex is null return n

IN操作符

与SQL一样,Neo4jCQL提供了一个IN运算符,以便为CQL命令提供值的集合。

match (n:student)where n.name in["小红","小明"] return n
INDEX索引

Neo4jSQL支持节点或关系属性上的索引,以提高应用程序的性能。

我们可以为具有相同标签名称的所有节点的属性创建索引。

我们可以在MATCH或WHERE或IN运算符上使用这些索引列来改进CQLCommand的执行。

Neo4j索引操作
  • Create Index创建索引
  • Drop Index 丢弃索引
// 创建索引
create index on :`西游` (name)
// 删除索引
drop index on :`西游` (name)
                     
//demo
create index on :student (name)
drop index on :student (name)
UNIQUE约束

在Neo4j数据库中,CQL CREATE命令始终创建新的节点或关系,这意味着即使您使用相同的值,它也会插入一个新行。根据我们对某些节点或关系的应用需求,我们必须避免这种重复。

像SQL一样,Neo4j数据库也支持对NODE或Relationship的属性的UNIQUE约束

UNIQUE约束的优点
  • 避免重复记录
  • 强制执行数据完整性规则
//创建唯一约束-————-所有标签为xiyou的name属性必须是唯一的
create constraint on (n:xiyou) assert n.name is unique

//删除唯一约束
drop constraint on (n:xiyou) assert n.name is unique
DISTINCT

这个函数的用法就像SQL中的distinct关键字,返回的是所有不同值。

match (n:`西游`) return distinct(n.name)

常用函数

  • 字符串函数
  • AGGREGATION聚合
  • 关系函数
字符串函数

与SQL一样,Neo4J CQL提供了一组String函数,用于在CQL查询中获取所需的结果。
这里我们将讨论一些重要的和经常使用的功能。

功能描述
UPPER它用于将所有字母更改为大写字母。
LOWER它用于将所有字母改为小写字母。
SUBSTRING它用于获取给定String的子字符串。
REPLACE它用于替换一个字符串的子字符串。
UPPER

它需要一个字符串作为输入并转换为大写字母。 所有CQL函数应使用“()”括号。

函数语法
UPPER (<input-string>)
MATCH (e:Employee) 
RETURN e.id,UPPER(e.name),e.sal,e.deptno
LOWER

它需要一个字符串作为输入并转换为小写字母。 所有CQL函数应使用“()”括号。

函数语法
LOWER (<input-string>)
MATCH (e:Employee) 
RETURN e.id,LOWER(e.name),e.sal,e.deptno
SUBSTRING

它接受一个字符串作为输入和两个索引:一个是索引的开始,另一个是索引的结束,并返回从StartInded到EndIndex-1的子字符串。 所有CQL函数应使用“()”括号。

函数语法
SUBSTRING(<input-string>,<startIndex> ,<endIndex>)

注意:-

在Neo4J CQL中,如果一个字符串包含n个字母,则它的长度为n,索引从0开始,到n-1结束。

是SUBSTRING函数的索引值。

是可选的。 如果我们省略它,那么它返回给定字符串的子串从startIndex到字符串的结尾。

MATCH (e:Employee) 
RETURN e.id,SUBSTRING(e.name,0,2),e.sal,e.deptno

//demo 
match (n:student)where n.name="小明"return substring(n.name,1,1)                      
AGGREGATION聚合

和SQL一样,Neo4j CQL提供了一些在RETURN子句中使用的聚合函数。 它类似于SQL中的GROUP BY子句。我们可以使用MATCH命令中的RETURN +聚合函数来处理一组节点并返回一些聚合值。

聚集功能描述
COUNT它返回由MATCH命令返回的行数。
MAX它从MATCH命令返回的一组行返回最大值。
MIN它返回由MATCH命令返回的一组行的最小值。
SUM它返回由MATCH命令返回的所有行的求和值。
AVG它返回由MATCH命令返回的所有行的平均值。
COUNT

它从MATCH子句获取结果,并计算结果中出现的行数,并返回该计数值。 所有CQL函数应使用“()”括号。

函数语法
COUNT(<value>)
// 此示例演示如何使用COUNT(*)函数返回数据库中可用的Employee节点数。
MATCH (e:Employee) RETURN COUNT(*)

// demo
match (n:student)return count(n)
MAX

它采用一组行和节点或关系的作为输入,并从给定行的give 列中查找最大值。

函数语法
MAX(<property-name> )
MIN

它采用一组行和节点或关系的作为输入,并从给定行的give 列中查找最小值。

函数语法
MIN(<property-name> )

注意 -

应该是节点或关系的名称。让我们用一个例子看看MAX和MIN的功能。

MATCH (e:Employee) 
RETURN MAX(e.sal),MIN(e.sal)

AVG

它采用一组行和节点或关系的作为输入,并从给定行的give 列中查找平均值。

函数的语法
AVG(<property-name> )
SUM

它采用一组行和节点或关系的作为输入,并从给定行的give 列中查找求和值。

函数的语法
SUM(<property-name> )
MATCH (e:Employee) 
RETURN SUM(e.sal),AVG(e.sal)
关系函数

Neo4j CQL提供了一组关系函数,以在获取开始节点,结束节点等细节时知道关系的细节。在这里,我们将讨论一些重要的和经常使用的功能。

功能描述
STARTNODE它用于知道关系的开始节点。
ENDNODE它用于知道关系的结束节点。
ID它用于知道关系的ID。
TYPE它用于知道字符串表示中的一个关系的TYPE。
STARTNODE和ENDNODE

它需要一个字符串作为输入并为大写格式, 所有CQL函数应使用“()”括号。

函数语法
STARTNODE (<relationship-label-name>)
ENDNODE (<relationship-label-name>)

此示例演示如何使用CQL STARTNODE关系函数来检索关系的开始节点详细信息。
在关系“ACTION_MOVIES”上执行STARTNODE()函数之前,我们将检查其详细信息

MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN STARTNODE(movie)
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ENDNODE(movie)
ID和TYPE
ID和TYPE关系函数来检索关系的Id和类型详细信息。
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ID(movie),TYPE(movie)

demo1 ID和TYPE关系函数来检索关系的Id和类型详细信息。

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN STARTNODE(movie)

demo2 使用CQL ENDNODE关系函数来检索关系的结束节点详细信息。

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ENDNODE(movie)

demo3 使用CQL ID和TYPE关系函数来检索关系的Id和类型详细信息。

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ID(movie),TYPE(movie)

E关系函数来检索关系的Id和类型详细信息。

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN STARTNODE(movie)

demo2 使用CQL ENDNODE关系函数来检索关系的结束节点详细信息。

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ENDNODE(movie)

demo3 使用CQL ID和TYPE关系函数来检索关系的Id和类型详细信息。

MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2) 
RETURN movie
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ID(movie),TYPE(movie)
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐