0

一般来说,我是 Graph DBs 的新手,正在尝试学习 Gremlin QL。我想知道是否有一种方法可以直接合并 id 已知的两个顶点的两个直接邻居。例如,在下图中

我不想遍历整个图,我只想让两个子图根据它们的共同邻居进行合并,并根据通向同一顶点的两条边的权重之和进行排序。

在上图中,我希望能够在使用 verticesA, B, C, D进行查询时显示这些顶点1 and 2。我希望能够合并顶点1和顶点2的outE,聚合(edge 1 -> A and Edge 2 -> A),(edge 1 -> B and Edge 2 -> B),(edge 1 -> C and Edge 2 -> C) and (edge 1 -> D and 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

对此的任何帮助都将受到高度赞赏。

4

1 回答 1

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()step 进行求和:

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(即顶点和相关边)中获取值,然后只找到那些边属性为“权重”的元素(顶点将被过滤掉)。最后,它将这些权重值相加。

这一点 Gremlin 可能对您的示例中的数据进行了过多调整。如果图形结构创建的不仅仅是这些简单的路径,我想你会在输出中看到一些边缘重复。如果您不关心重复并且想总结所有内容,那么我想我所拥有的将按原样工作。如果您只想计算总和中的唯一边权重,那么您可能需要dedup()has('weight').

如果您需要对结果进行排序,则可以在结果中添加步骤order()和排序:valuesMap

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

于 2019-01-04T20:49:35.210 回答