是否可以通过ID合并两个已知顶点的传出顶点

时间:2019-01-04 06:59:36

标签: gremlin

我一般是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

在此方面的任何帮助都将受到高度赞赏。

1 个答案:

答案 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中进行排序,而不是对流本身进行排序。