Neo4j 图数据科学 (Graph Data Science, GDS) 介绍
项目要用,我真是喜欢从头学,喜欢有个完整的体系,要不用的都不爽。
目录
官网课程
1 Neo4j GDS 概述
1.1 GDS 插件和兼容性
1.2 安装

点击Install将下载plugins/目录下
dbms.security.procedures.unrestricted=gds.*这个配置项是必要的
如果配置了程序允许列表
dbms.security.procedures.allowlist=gds.*在
关于
1.3 GDS 的工作方式
在高层次上
1.3.1 基本工作流程

- 读取和加载图
: GDS 需要从Neo4j 数据库中读取数据, 进行转换, 并将其加载到内存图中. 在GDS 中, 这个过程称为投射图(projecting a graph) , 把内存中的图称为图的投影(graph projection) . GDS 可以同时容纳多个图的投影, 由一个叫做图目录(Graph Catalog) 的组件管理 . 图目录和图投影管理将在下一个模块中更详细地介绍. - 执行算法
: 包括经典的图算法, 如中心性算法(centrality) , 社区检测算法(community detection) , 路径搜索算法(path finding) 等. 它还包括嵌入法(embeddings) , 一种强大的图特征工程的形式, 以及机器学习管道(machine learning pipelines) . - 储存结果
: 结果可以写回到数据库, 以csv 格式导出, 或输出到另一个应用程序或下游工作流程.
配置之类的不想看
2 图管理(Graph Management)
2.1 图目录(Graph Catalog)
图目录允许在
- 创建
( 投射) 图 - 查看图的细节
- 删除图投影
- 导出图投影
- 将图投影属性写回数据库
2.1.1 图目录怎么用
用以下形式的命令调用图目录操作
CALL gds.graph.<command>例
列出当前存在于数据库中的图投影
CALL gds.graph.list()由于还没有创建任何投影
在推荐图中Actor和Movie节点以及ACTED_IN关系中创建一个投影
CALL gds.graph.project('my-graph-projection', ['Actor','Movie'], 'ACTED_IN')再次列出图表,我们可以看到刚刚创建的图的信息
CALL gds.graph.list() YIELD graphName, nodeCount, relationshipCount, schema| graphName | nodeCount | relationshipCount | schema |
|---|---|---|---|
| my-graph-projection | 24568 | 35910 | {"relationships":{"ACTED_IN":{}},"nodes":{"Movie":{},"Actor":{}}} |
2.1.2 运行算法
正如之前提到的
例
计算Actor节点的度中心性numberOfMoviesActedIn的节点属性中
CALL gds.degree.mutate('my-graph-projection', {mutateProperty:'numberOfMoviesActedIn'})2.1.3 流动和写入节点属性
有时候我们会想从算法计算中获取结果并将结果流向另一个进程或写回数据库
例
使用numberOfMoviesActedIn的例子streamNodeProperty图目录操作
CALL gds.graph.streamNodeProperty('my-graph-projection','numberOfMoviesActedIn')
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).name AS actorName, propertyValue AS numberOfMoviesActedIn
ORDER BY numberOfMoviesActedIn DESCENDING, actorName LIMIT 10| actorName | numberOfMoviesActedIn |
|---|---|
| Robert De Niro | 56.0 |
| Bruce Willis | 49.0 |
| Nicolas Cage | 45.0 |
| Samuel L. Jackson | 45.0 |
| Clint Eastwood | 40.0 |
| Michael Caine | 40.0 |
| Gene Hackman | 38.0 |
| John Cusack | 38.0 |
| John Travolta | 38.0 |
| Morgan Freeman | 38.0 |
如果我们想把属性写回数据库writeNodeProperties操作
CALL gds.graph.writeNodeProperties('my-graph-projection',['numberOfMoviesActedIn'], ['Actor'])然后我们就能查询按电影数量计算的前
MATCH (a:Actor)
RETURN a.name, a.numberOfMoviesActedIn
ORDER BY a.numberOfMoviesActedIn DESCENDING, a.name LIMIT 102.1.4 导出图
在数据科学工作流程中
- 导出图特征,用于在另一个环境中训练机器学习模型
- 为下游分析或与同事分享需要创建单独的分析视图
- 生成分析结果的快照并保存到文件系统
图目录有两种导出操作
gds.graph.export将图导出到一个新的数据库中——高效地将投影复制到一个单独的Neo4j 数据库中gds.beta.graph.export.csv将图导出到csv 文件中
2.1.5 删除图
投影的图形会占用内存
CALL gds.graph.drop('my-graph-projection')现在再列出图的投影就又会返回空列表了
CALL gds.graph.list()2.1.6 其他图目录操作
图目录中还有一些其他的管理操作
3 原生投影(Native Projections)
在
3.1 关于原生投影
实际上上文已经使用过原生投影原生投影gds.graph.project()
除了从数据库中原封不动地投射节点和关系元素外
- 纳入数值型节点和关系属性
- 改变关系方向
(direction) 或 “朝向(orientation) ” - 聚合平行关系
这些有助于为不同类型的分析工作流程和算法的投影做准备
下面介绍了原生投影的基本语法已经一些常见的配置
3.2 基本语法
原生投影有三个强制参数graphNamenodeProjection和relationshipProjectionconfiguration允许我们进一步配置图的创建
| 参数名称 | 类型 | 是否可选 | 描述 |
|---|---|---|---|
graphName | String | 否 | 图在目录中存储的名称 |
nodeProjection | String, List or Map | 否 | 投射节点的配置 |
relationshipProjection | String, List or Map | 否 | 投射关系的配置 |
configuration | Map | 是 | 配置原生投影的附加参数 |
nodeProjection和relationshipProjection有很多不同的选项
3.3 基础原生投影
首先考虑一个非常基本的情形
CALL gds.graph.project('native-proj',['User', 'Movie'], ['RATED']);还有各种形式的速记语法relationshipProjection 输入 RATED 值获得等效的投影
CALL gds.graph.project('native-proj',['User', 'Movie'], 'RATED');
如果试图用一个已经存在的名字创建一个新的图形投影gds.graph.drop()来删除现有的图投影
CALL gds.graph.drop('native-proj');通配符’*‘可以匹配数据库中的所有节点和关系
CALL gds.graph.project('native-proj','*', '*');3.4 改变关系方向
原生投影也允许改变关系的方向
定向关系是不对称的

无定向关系是对称的

考虑到这一点relationshipProjection中我们有三个方向相关的选项可以应用于关系类型
NATURAL: 与数据库中的方向一致( 默认) REVERSE: 与数据库中的方向相反UNDIRECTED: 无定向
以之前投射的图为例
CALL gds.graph.drop('native-proj', false);
CALL gds.graph.project('native-proj',['User', 'Movie'], ['RATED']);
CALL gds.degree.mutate('native-proj', {mutateProperty: 'ratingCount'});CALL gds.graph.streamNodeProperty('native-proj','ratingCount', ['Movie'])
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).title AS movieTitle, propertyValue AS ratingCount
ORDER BY movieTitle DESCENDING LIMIT 5| movieTitle | ratingCount |
|---|---|
| İtirazım Var | 0.0 |
| À nous la liberté (Freedom for Us) | 0.0 |
| ¡Three Amigos! | 0.0 |
| xXx: State of the Union | 0.0 |
| xXx | 0.0 |
这个结果与关系的方向有关RATED关系反过来的新图
CALL gds.graph.drop('native-proj', false);
//replace with a project that has reversed relationship orientation
CALL gds.graph.project(
'native-proj',
['User', 'Movie'],
{RATED_BY: {type: 'RATED', orientation: 'REVERSE'}}
);
CALL gds.degree.mutate('native-proj', {mutateProperty: 'ratingCount'});现在再使用度调用
CALL gds.graph.streamNodeProperty('native-proj','ratingCount', ['Movie'])
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).title AS movieTitle, propertyValue AS ratingCount
ORDER BY movieTitle DESCENDING LIMIT 5| movieTitle | ratingCount |
|---|---|
| İtirazım Var | 1.0 |
| À nous la liberté (Freedom for Us) | 1.0 |
| ¡Three Amigos!31.0 | 31.0 |
| xXx: State of the Union | 1.0 |
| xXx | 23.0 |
3.5 纳入节点和关系属性
节点和关系属性在图分析可能会有用
下面是一个纳入了多个movie节点属性和rating关系属性的例子。
CALL gds.graph.drop('native-proj', false);
CALL gds.graph.project(
'native-proj',
['User', 'Movie'],
{RATED: {orientation: 'UNDIRECTED'}},
{
nodeProperties:{
revenue: {defaultValue: 0}, // (1)
budget: {defaultValue: 0},
runtime: {defaultValue: 0}
},
relationshipProperties: ['rating'] // (3)
}
);注意
defaultValue参数允许我们用一个默认值来填补缺失值. 此情况我们使用的是0. - 简化语法没有默认值
, 因为根据数据模型, 这些值不应该缺少.
如何利用这些属性将在
3.6 平行关系聚合

有时你会想把这些平行关系聚合成一个单一的关系
原生投影允许这种聚合
下面是一个没有任何属性的关系聚合的例子
CALL gds.graph.project(
'user-proj',
['User'],
{
SENT_MONEY_TO: { aggregation: 'SINGLE' }
}
);
也可以创建一个带有关系数的属性
CALL gds.graph.project(
'user-proj',
['User'],
{
SENT_MONEY_TO: {
properties: {
numberOfTransactions: {
// the wildcard '*' is a placeholder, signaling that
// the value of the relationship property is derived
// and not based on Neo4j property.
property: '*',
aggregation: 'COUNT'
}
}
}
}
);
在聚合过程中
CALL gds.graph.project(
'user-proj',
['User'],
{
SENT_MONEY_TO: {
properties: {
totalAmount: {
property: 'amount',
aggregation: 'SUM'
}
}
}
}
);
3.7 其他本地投影的配置和功能
这里介绍了基础知识
4 Cypher 投影
虽然原生投影又快又扩展性好
虽然
下面将会讨论
4.1 语法
与原生投影类似graphNamenodeQuery和relationshipQueryconfiguration允许我们进一步配置图的创建
| 参数名称 | 是否可选 | 描述 |
|---|---|---|
graphName | 否 | 图在目录中存储的名称 |
nodeQuery | 否 | 投影节点的id列labels列来表示节点标签 |
relationshipProjection | 否 | 投影关系的source和target列type列来表示关系类型 |
configuration | 是 | 配置 |
4.2 应用实例
之前我们根据演员参演过的电影数量来决定哪些演员最多产
在这个例子中,如果一部电影是在
直接用原生投影不容易解决这个问题Actor节点之间聚合以及创建一个拥有actedWithCount属性的ACTED_WITH关系
CALL gds.graph.project.cypher(
'proj-cypher',
'MATCH (a:Actor) RETURN id(a) AS id, labels(a) AS labels',
'MATCH (a1:Actor)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(a2)
WHERE m.year >= 1990 AND m.revenue >= 1000000
RETURN id(a1) AS source , id(a2) AS target, count(*) AS actedWithCount, "ACTED_WITH" AS type'
);然后我们就可以像之前那样应用度中心算法actedWithCount属性对程度中心性进行加权
CALL gds.degree.stream('proj-cypher',{relationshipWeightProperty: 'actedWithCount'})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC LIMIT 5| name | score |
|---|---|
| Robert De Niro | 123.0 |
| Bruce Willis | 120.0 |
| Johnny Depp | 102.0 |
| Denzel Washington | 99.0 |
| Nicolas Cage | 90.0 |
4.3 什么时候该使用Cypher 投影
在上面的例子中
- 复杂的过滤
: 使用节点以及关系属性的条件或其他更复杂的 MATCH/ WHERE条件来从图中筛选, 而不仅仅用节点标签和关系类型. - 聚合有权重的多跳路径
(Multi-Hop Paths) : 关系投影需要将 (Actor)-[ACTED_IN]-(Movie)-[ACTED_IN]-(Actor)形式聚合为(Actor)-[ACTED_WITH {actedWithCount}]-(Actor)形式, 其中actedWithCount是关系的权重属性. 这种投影需要将多跳路径转化为连接源节点和目标节点的聚合关系, 在图分析中经常出现.
4.4 过渡到原生投影
虽然
例如
//set a node label based on recent release and revenue conditions
MATCH (m:Movie)
WHERE m.year >= 1990 AND m.revenue >= 1000000
SET m:RecentBigMovie;
//native projection with reverse relationships
CALL gds.graph.project('proj-native',
['Actor','RecentBigMovie'],
{
ACTED_IN:{type:'ACTED_IN'},
HAS_ACTOR:{type:'ACTED_IN', orientation: 'REVERSE'}
}
);
//collapse path utility for relationship aggregation - no weight property
CALL gds.alpha.collapsePath.mutate('proj-native',{
relationshipTypes: ['ACTED_IN', 'HAS_ACTOR'],
allowSelfLoops: false,
mutateRelationshipType: 'ACTED_WITH'
});//count actors that acted with the most other actors in recent high grossing movies and stream the top 15
CALL gds.degree.stream('proj-native', {nodeLabels:['Actor'], relationshipTypes: ['ACTED_WITH']})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, score
ORDER BY score DESC LIMIT 10| name | score |
|---|---|
| Bruce Willis | 114.0 |
| Robert De Niro | 109.0 |
| Denzel Washington | 96.0 |
| Johnny Depp | 90.0 |
| Nicolas Cage | 86.0 |
| Julianne Moore | 84.0 |
| Samuel L. Jackson | 82.0 |
| Morgan Freeman | 81.0 |
| Ben Affleck | 81.0 |
| Brad Pitt | 79.0 |
以下是根据最初的使用情况
- 用节点属性条件进行过滤
: 为符合属性条件的节点添加标签, 以便能在原生投影中过滤 - 用关系属性条件进行过滤
: 如果可能, 为每个满足属性条件的关系的源节点和目标节点添加一个标签. 否则, 考虑在你的数据模型中添加一个额外的关系类型来获取满足条件的关系. - 聚合多跳路径
: - 查看坍缩路径是否能满足需求
. 它不对关系进行加权, 但结果往往可以与加权的聚合非常相似 - 对于大型投影上的某些类型的问题,可以使用相似性和嵌入算法来近似聚合关系
- 查看坍缩路径是否能满足需求
对于其他复杂的使用场景