如何获取 JanusGraph Gremlin 返回的子图的邻接矩阵?
How to acquire adjacency matrix of a subgraph returned by JanusGraph Gremlin?
我使用这个查询得到指定节点的 3 跳子图
subgraph = g.V().has('customer', 'id', '528311').repeat(bothE().subgraph('subGraph').otherV()).times(3).cap('subGraph').next()
我想得到这个子图的邻接矩阵,以便我可以将它提供给谱聚类模型。
使用 TinkerPop 从图形生成邻接矩阵确实没有捷径(也许应该纠正)。你基本上只需要自己构建一个,这并不难——我将以“现代”图为例:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> count = g.V().order().by('name').store('x').
......1> property('oid',union(select('x').count(local),
......2> constant(-1)).sum()).
......3> count().next()
==>6
我添加了一个“oid”属性 值,它只是一个自定义 ID,它使用数据的自定义排序格式从零开始递增,因此很容易与矩阵结构对齐,其中“oid”将与数据中行和列的位置对齐:
gremlin> g.V().elementMap()
==>[id:1,label:person,name:marko,oid:2,age:29]
==>[id:2,label:person,name:vadas,oid:5,age:27]
==>[id:3,label:software,name:lop,oid:1,lang:java]
==>[id:4,label:person,name:josh,oid:0,age:32]
==>[id:5,label:software,name:ripple,oid:4,lang:java]
==>[id:6,label:person,name:peter,oid:3,age:35]
然后我构造一个给定顶点数的字节矩阵:
gremlin> matrix = new byte[count][count]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
最后,我遍历每条边以更新矩阵作为副作用。我选择将每个 Edge
转换为 Map
,这样可以很容易地删除顶点之间的多条边,并且可能更清楚地展示对矩阵本身的更新:
gremlin> g.E().project('out','in').
......1> by(outV().values('oid')).
......2> by(inV().values('oid')).
......3> dedup().
......4> each {
......5> matrix[(int) it['out']][(int) it['in']] = 1
......6> }
gremlin> matrix
==>[0, 1, 0, 0, 1, 0]
==>[0, 0, 0, 0, 0, 0]
==>[1, 1, 0, 0, 0, 1]
==>[0, 1, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
我使用这个查询得到指定节点的 3 跳子图
subgraph = g.V().has('customer', 'id', '528311').repeat(bothE().subgraph('subGraph').otherV()).times(3).cap('subGraph').next()
我想得到这个子图的邻接矩阵,以便我可以将它提供给谱聚类模型。
使用 TinkerPop 从图形生成邻接矩阵确实没有捷径(也许应该纠正)。你基本上只需要自己构建一个,这并不难——我将以“现代”图为例:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> count = g.V().order().by('name').store('x').
......1> property('oid',union(select('x').count(local),
......2> constant(-1)).sum()).
......3> count().next()
==>6
我添加了一个“oid”属性 值,它只是一个自定义 ID,它使用数据的自定义排序格式从零开始递增,因此很容易与矩阵结构对齐,其中“oid”将与数据中行和列的位置对齐:
gremlin> g.V().elementMap()
==>[id:1,label:person,name:marko,oid:2,age:29]
==>[id:2,label:person,name:vadas,oid:5,age:27]
==>[id:3,label:software,name:lop,oid:1,lang:java]
==>[id:4,label:person,name:josh,oid:0,age:32]
==>[id:5,label:software,name:ripple,oid:4,lang:java]
==>[id:6,label:person,name:peter,oid:3,age:35]
然后我构造一个给定顶点数的字节矩阵:
gremlin> matrix = new byte[count][count]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
最后,我遍历每条边以更新矩阵作为副作用。我选择将每个 Edge
转换为 Map
,这样可以很容易地删除顶点之间的多条边,并且可能更清楚地展示对矩阵本身的更新:
gremlin> g.E().project('out','in').
......1> by(outV().values('oid')).
......2> by(inV().values('oid')).
......3> dedup().
......4> each {
......5> matrix[(int) it['out']][(int) it['in']] = 1
......6> }
gremlin> matrix
==>[0, 1, 0, 0, 1, 0]
==>[0, 0, 0, 0, 0, 0]
==>[1, 1, 0, 0, 0, 1]
==>[0, 1, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]
==>[0, 0, 0, 0, 0, 0]