我一般是Graph数据库的新手,正在尝试学习Gremlin QL。我想知道是否有一种方法可以直接合并已知ID的两个顶点的两个直接邻居。例如,在下图中
我不想遍历整个图,我只希望两个子图基于它们的共同邻居合并,并基于通向同一顶点的两个边的权重之和排序。
在上图中,当我查询顶点A, B, C, D
时,我希望能够显示顶点1 and 2
。我希望能够合并顶点1和顶点2的outE,汇总(edge 1-> A和Edge 2-> A),(edge 1-> B and Edge 2-> B),(edge 1-> C和Edge 2-> C)和(edge 1-> D和Edge 2-> D),然后根据此综合得分对结果进行排序。
下面的图形创建代码
g.addV().property('id',1).property("type","A").as('1')
addV().property('id',2).property("type","B").as('2').
addV().property('id',A).property("type","X").as('A').
addV().property('id',B).property("type","X").as('B').
addV().property('id',C).property("type","X").as('C').
addV().property('id',D).property("type","X").as('D').
addE('connects').from('1').to('A').property("weight",0.1d)
addE('connects').from('1').to('B').property("weight",0.4d)
addE('connects').from('1').to('C').property("weight",0.2d)
addE('connects').from('1').to('D').property("weight",0.7d)
addE('connects').from('2').to('A').property("weight",0.5d)
addE('connects').from('2').to('B').property("weight",0.2d)
addE('connects').from('2').to('C').property("weight",0.7d)
addE('connects').from('2').to('D').property("weight",0.4d).iterate()
如果要在SQL中表示以上数据,则示例模型如下
create table items(id varchar(20), toId varchar(20), weight double(5,4), primary key (id, toId);
insert into items values("1","A",0.1);
insert into items values("1","B",0.4);
insert into items values("1","C",0.2);
insert into items values("1","D",0.7);
insert into items values("2","A",0.5);
insert into items values("2","B",0.2);
insert into items values("2","C",0.7);
insert into items values("2","D",0.4);
select toId, a.weight+b.weight as weight from items a, items b where a.id = "1" and b.id = "2" and a.toId = b.toId order by weight desc;
通常返回
D, 0.11
C, 0.9
B, 0.6
A, 0.5
在此方面的任何帮助都将受到高度赞赏。
答案 0 :(得分:0)
我对您的数据创建脚本进行了一些调整,因为它存在一些语法错误:
g.addV().property('id',1).property("type","A").as('1').
addV().property('id',2).property("type","B").as('2').
addV().property('id','A').property("type","X").as('A').
addV().property('id','B').property("type","X").as('B').
addV().property('id','C').property("type","X").as('C').
addV().property('id','D').property("type","X").as('D').
addE('connects').from('1').to('A').property("weight",0.1d).
addE('connects').from('1').to('B').property("weight",0.4d).
addE('connects').from('1').to('C').property("weight",0.2d).
addE('connects').from('1').to('D').property("weight",0.7d).
addE('connects').from('2').to('A').property("weight",0.1d).
addE('connects').from('2').to('B').property("weight",0.4d).
addE('connects').from('2').to('C').property("weight",0.2d).
addE('connects').from('2').to('D').property("weight",0.7d).iterate()
可能还有其他方法,但是在编写查询的方法中,我决定首先收集“ 1”和“ 2”两个起始顶点之间所需的边:
gremlin> g.V().has('id',1).
......1> outE('connects').as('1e').
......2> inV().as('v').
......3> inE('connects').as('2e').
......4> where(outV().has('id',2)).
......5> select('1e','v','2e')
==>[1e:e[18][0-connects->6],v:v[6],2e:e[22][3-connects->6]]
==>[1e:e[19][0-connects->9],v:v[9],2e:e[23][3-connects->9]]
==>[1e:e[20][0-connects->12],v:v[12],2e:e[24][3-connects->12]]
==>[1e:e[21][0-connects->15],v:v[15],2e:e[25][3-connects->15]]
因此,以上内容为我们提供了所有共享的边以及要为其求权重之和的顶点。您可以通过group()
步骤进行求和:
gremlin> g.V().has('id',1).
......1> outE('connects').as('1e').
......2> inV().as('v').
......3> inE('connects').as('2e').
......4> where(outV().has('id',2)).
......5> select('1e','v','2e').
......6> group().
......7> by(select('v').by('id')).
......8> by(select(values).
......9> unfold().has('weight').
.....10> values('weight').sum())
==>[A:0.2,B:0.8,C:0.4,D:1.4]
第一个by()
调制器从传入的Map
结果中获取“ v”键,并从其中的顶点中提取“ id”属性。第二个by()
调制器通过执行可能无法立即清除的操作来产生总和。它从传入的Map
(即顶点和相关的边)中获取值,然后仅查找具有“ weight”的edge属性的元素(顶点将被滤除)。最后,将这些权重值相加。
这部分Gremlin可能与您示例中的数据相差太大。如果图形结构创建的不只是这些简单路径,我想您会在输出中看到一些边缘重复。如果您不关心重复项,而是想将其全部加总,那么我想我所拥有的将照常工作。如果您只想计算总和中的唯一边权重,则可能需要在dedup()
之后添加一个has('weight')
步骤。
如果需要对结果进行排序,则可以在order()
结果中添加values
步骤并按Map
进行排序:
gremlin> g.V().has('id',1).
......1> outE('connects').as('1e').
......2> inV().as('v').
......3> inE('connects').as('2e').
......4> where(outV().has('id',2)).
......5> select('1e','v','2e').
......6> group().
......7> by(select('v').by('id')).
......8> by(select(values).
......9> unfold().has('weight').
.....10> values('weight').sum()).
.....11> order(local).by(values, desc)
==>[D:1.4,B:0.8,C:0.4,A:0.2]
请注意,您使用local
是因为您正在遍历流的当前Map
中进行排序,而不是对流本身进行排序。