You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tinkerpop.apache.org by Mike Personick <mi...@supersonick.io> on 2022/12/12 18:14:45 UTC

Proposal to change the mergeV/E semantics based on user feedback

We are proposing a change to the mergeV/E semantics based on initial
feedback from its use. We propose making these changes in the upcoming
3.6.2 release.

For clarity in this discussion, we refer to the main argument as “mergeMap”
and the onCreate argument as “onCreateMap”. The discussion centers around
how to handle the create branch action, we are not concerned with how the
match branch is currently handled.

mergeV/E(Map mergeMap).option(Merge.onCreate, onCreateMap)

The current semantics for merge are to base the create action entirely on
the onCreateMap - the mergeMap is ignored. The proposal is to instead base
the create action on a union of the mergeMap and the onCreateMap,
effectively an inheritance relationship where onCreateMap inherits from
mergeMap.

Difference in behavior (example):

mergeV({T.id: "1", T.label: "person"}).option(onCreate, {"created": true})

This is an intuitive way to ask for a vertex with T.id=“1” and
T.label=“person” to be either matched or created. Currently however, this
query will create an anonymous vertex with an auto-generated id and the
default vertex T.label=“vertex” during the create action, because there is
no inheritance from the mergeMap arguments during the create action. We
propose to change the semantics such that onCreate inherits the arguments
from the mergeMap by default, so that the query as written above creates
the vertex {T.id: "1", T.label: "person", "created": true} when run on an
empty graph.

This has led to numerous user frustrations and even errors in the public
documentation:
https://tinkerpop.apache.org/docs/current/reference/#mergeedge-step

gremlin> g.withSideEffect('map',[(T.label):'Sibling',(from):1,(to):2]).
           mergeE(select('map')).
             option(Merge.onCreate,[created:'2022-02-07']). //// (1)
             option(Merge.onMatch,[updated:'2022-02-07']) //// (2)
==>e[2][1-edge->2]
gremlin> g.E().elementMap()
==>[id:2,label:edge,IN:[id:2,label:Dog],OUT:[id:1,label:Dog],created:2022-02-07]

Here because T.label='Sibling' was accidentally left out of the onCreateMap
and because there is no inheritance from the mergeMap, we created an edge
with the wrong label and didn’t even notice. There are other examples in
the documentation of this class of user error as well. This is an extremely
common error because of the current semantics of the relationship between
mergeMap and onCreateMap.

Overrides of the element existence criteria (T.id/label and
Direction.IN/OUT) in the onCreate map will NOT be allowed, for example,
these queries will be prohibited:

g.mergeV([T.id: "1", T.label: "foo"])
 .option(onCreate, [T.id: "2", T.label: "bar"])

g.mergeE([T.id: "101", T.label: "foo", OUT: "1", IN: "2"])
 .option(onCreate, [T.id: "202", T.label: "bar", OUT: "3", IN: "4"])

We will assume a lazy consensus and proceed with these changes if there are
no objections by Friday 12/16/22 at 5pm ET.