mergeE(): increment counter on match

Hi, is there an easy way to increment an existing edge property based on its current value using mergeE() in one single query? (e.g., counter += 1) Something similar to this:
g.mergeE([(T.label):'called', (from): person1, (to):person2]).
option(Merge.onCreate,['num_calls': 1]).
option(Merge.onMatch,['num_calls': X+1])
g.mergeE([(T.label):'called', (from): person1, (to):person2]).
option(Merge.onCreate,['num_calls': 1]).
option(Merge.onMatch,['num_calls': X+1])
where X is the current value of edge propery num_calls.
Solution:
gremlin> g.mergeE([(Direction.from):44,(Direction.to):8]).valueMap(true)
==>[id:5062,label:route,dist:549]
gremlin> g.mergeE([(Direction.from):44,(Direction.to):8]).valueMap(true)
==>[id:5062,label:route,dist:549]
and then...
Jump to solution
11 Replies
rpuga
rpugaOP9mo ago
BTW, I was able to obtain the result I need with a query that looks like this:
p1 = g.addV('person').property('name', 'marko').next()
p2 = g.addV('person').property('name', 'maria').next()
g.V(p1).as("v1").
V(p2).as("v2").
coalesce(
select("v1").outE("called").where(inV().has(id, select("v2").id())),
addE("called").from("v1").to("v2").property("num_calls", 0)).
as("e").
property(
"num_calls",
union(select("e").values("num_calls").unfold(), constant(1)).sum())
p1 = g.addV('person').property('name', 'marko').next()
p2 = g.addV('person').property('name', 'maria').next()
g.V(p1).as("v1").
V(p2).as("v2").
coalesce(
select("v1").outE("called").where(inV().has(id, select("v2").id())),
addE("called").from("v1").to("v2").property("num_calls", 0)).
as("e").
property(
"num_calls",
union(select("e").values("num_calls").unfold(), constant(1)).sum())
but I'm wondering how something similar can be done with mergeE()
Valentyn Kahamlyk
I think this is impossible now. @spmallette, do you think this is a good use case for passing matching Element as context to onMatch traversal?
Flynnt
Flynnt8mo ago
And what about delegating this « business stuff » to an event strategy ?
kelvinl2816
kelvinl28168mo ago
So long as mergeE is used as a start step, I think you can make this work. But it maybe that this ability needs to get disabled temporarily in order to prevent some error conditions we have seen lately from happening as @Valentyn Kahamlyk mentions while we rework the mergeE semantics a little. I'll post an example in a bit. Need to type one up.
Solution
kelvinl2816
kelvinl28168mo ago
gremlin> g.mergeE([(Direction.from):44,(Direction.to):8]).valueMap(true)
==>[id:5062,label:route,dist:549]
gremlin> g.mergeE([(Direction.from):44,(Direction.to):8]).valueMap(true)
==>[id:5062,label:route,dist:549]
and then
gremlin> g.mergeE([(Direction.from):44,(Direction.to):8]).
......1> option(onMatch,property('dist',union(values('dist'), __.constant(1)).sum()).constant([:])).valueMap(true)
==>[id:5062,label:route,dist:550]
gremlin> g.mergeE([(Direction.from):44,(Direction.to):8]).
......1> option(onMatch,property('dist',union(values('dist'), __.constant(1)).sum()).constant([:])).valueMap(true)
==>[id:5062,label:route,dist:550]
kelvinl2816
kelvinl28168mo ago
@spmallette has been working on some PRs to improve a few mergeE behaviors. I would like him to comment on whether my example will still be vallid after those updates land. So @rpuga that is one way you can (with the current latest version) make this work. Regarding EventStrategy @Flynnt , those only really make sense when the graph is embedded into the application (as a TinkerGraph can be). In order to catch database wide changes you need something more like the Amazon Neptune CDC stream, or JanusGraph triggers.
Flynnt
Flynnt8mo ago
Totally agree. And with those, transactional problems can occurs. I think that the best approche for the use case is a change in the data models. And not in using the merge step. with the introduction of a vertex « phone calls » and « call » (for exemple) phone calls beeing liked to the two person and liked to each call. This way a new call is just a new vertex in the graph liked to a relation. And for knowing the count, you can just count the edges.
rpuga
rpugaOP8mo ago
Thanks @Kelvin Lawrence, your solution works great! Adapting it to the example graph I was using, it looks like this:
g.mergeE([(T.label):'called', (from):p1, (to):p2]).
option(Merge.onCreate, ['num_calls': 1]).
option(Merge.onMatch, property('num_calls', union(values('num_calls'), constant(1)).sum()).constant([:]))
g.mergeE([(T.label):'called', (from):p1, (to):p2]).
option(Merge.onCreate, ['num_calls': 1]).
option(Merge.onMatch, property('num_calls', union(values('num_calls'), constant(1)).sum()).constant([:]))
kelvinl2816
kelvinl28168mo ago
FYI @spmallette and @Valentyn Kahamlyk this is I think one of the key cases where being able to do additional work inside onMatch is very useful.
Valentyn Kahamlyk
Will we have same behavior for starting and mid-traversal mergeE?
kelvinl2816
kelvinl28168mo ago
Currently no unfortunately. It will depend on what is in the stream until changes can be made to the way the step is working today. I called out this case mainly as an example of a behavior that needs to be supported in some way (as it is very useful).
Want results from more Discord servers?
Add your server