我正在尝试在gremlin中实现Ldbc SNB IC5。现在,我得到了以下DSL:
g.E().
hasLabel('hasMember').has('joinDate', gt(1292457600000)).
fold().
sideEffect(g.V().has('p.id', 4398046514041).
repeat(both('knows').simplePath()).
emit().times(2).dedup().aggregate('friend')).
unfold().as('candidate').
inV().where(within('friend')).as('person').
select('candidate').outV().as('forum').
out('containerOf').hasLabel('post').out('hasCreator').as('creator').
where(eq('person')).count(local).
as('cnt').select('forum', 'person', 'cnt')
哪个产生结果:
==>[forum:v[f17179878665],person:v[p2199023257492],cnt:1]
==>[forum:v[f34359749233],person:v[p3298534884212],cnt:1]
==>[forum:v[f8589934681],person:v[p4398046511765],cnt:1]
==>[forum:v[f17179880026],person:v[p1099511630430],cnt:1]
==>[forum:v[f34359740386],person:v[p2370],cnt:1]
==>[forum:v[f25769814145],person:v[p5497558139737],cnt:1]
结果非常接近,但不完全是我想要的结果,我需要空条目的记录,其中cnt
是0
。
直观的方法是使用choose
:
g.E().
hasLabel('hasMember').has('joinDate', gt(1292457600000)).
fold().
sideEffect(g.V().has('p.id', 4398046514041).
repeat(both('knows').simplePath()).
emit().times(2).dedup().aggregate('friend')).
unfold().as('candidate').
inV().where(within('friend')).as('person').
select('candidate').outV().as('forum').
out('containerOf').hasLabel('post').out('hasCreator').as('creator').
choose(
where(eq('person')),
constant(1),
constant(0)).
as('cnt').select('forum', 'person', 'cnt')
不幸的是,该查询超时在默认超时30s
之后。然后,我强制设置limit
来查看profile
的结果:
gremlin> g.E().
......1> hasLabel('hasMember').has('joinDate', gt(1292457600000)).
......2> fold().
......3> sideEffect(g.V().has('p.id', 4398046514041).
......4> repeat(both('knows').simplePath()).
......5> emit().times(2).dedup().aggregate('friend')).
......6> unfold().as('candidate').
......7> inV().where(within('friend')).as('person').
......8> select('candidate').outV().as('forum').
......9> out('containerOf').hasLabel('post').out('hasCreator').as('creator').
.....10> limit(100).
.....11> choose(
.....12> where(eq('person')),
.....13> constant(1),
.....14> constant(0)).
.....15> as('cnt').select('forum', 'person', 'cnt').profile()
==>Traversal Metrics
Step Count Traversers Time (ms) % Dur
=============================================================================================================
GraphDbGraphStep(edge,[~label.eq(hasMember), jo... 29704 29704 559.852 50.95
FoldStep 1 1 15.712 1.43
TraversalSideEffectStep([ParallelStep([GraphDbG... 1 1 25.613 2.33
ParallelStep([GraphDbGraphStep(vertex,p.id.eq... 2 2 10.947
RepeatStep([VertexStep(BOTH,[knows],vertex), ... 692 692 5.613
VertexStep(BOTH,[knows],vertex) 696 696 3.714
PathFilterStep(simple) 692 692 0.736
RepeatEndStep 692 692 0.634
DedupGlobalStep 330 330 0.542
AggregateStep(friend) 330 330 0.659
UnfoldStep@[candidate] 84 84 0.202 0.02
EdgeVertexStep(IN) 84 84 0.130 0.01
WherePredicateStep(within([friend]))@[person] 18 18 0.086 0.01
SelectOneStep(last,candidate) 18 18 0.038 0.00
EdgeVertexStep(OUT)@[forum] 18 18 0.037 0.00
VertexStep(OUT,[containerOf],vertex) 101 101 1.748 0.16
HasStep([~label.eq(post)]) 101 101 0.163 0.01
VertexStep(OUT,[hasCreator],vertex)@[creator] 101 101 8.613 0.78
RangeGlobalStep(0,100) 100 100 0.232 0.02
ChooseStep([WherePredicateStep(eq(person)), Pro... 100 100 485.889 44.22
WherePredicateStep(eq(person)) 80.862
HasNextStep 100 100 0.324
ConstantStep(0) 100 100 0.365
EndStep 100 100 0.295
SelectStep(last,[forum, person, cnt]) 100 100 0.571 0.05
>TOTAL - - 1098.892 -
profile
的结果表明,choose
步骤花费的时间比我预期的要多得多。
然后我尝试了branch/coalesce
,它花费的时间与choose
相同。
所以我的问题是,是否可以使用除choose/branch/coalesce
以外的更好的步骤。
我的数据库规模如下:
gremlin> g.V().count()
==>92118
gremlin> g.E().count()
==>335131