In Gremlin/Tinkerpop, I want to perform a versioned upsert on a Vertex. If there is an existing Vertex, I only want to mutate it if the version matches a version number property.
Below is the code that attempts to do this using gremlinjs
. It fails to create the vertex, a later query is unable to find it.
(the prior version of this had a compilation error, but that was a javscriptism undocumented syntax issue)
[UPDATE] see comments in answer as to what was wrong. Working version at https://gist.github.com/pszabop/3b07fa7caadf1dbd86953a713ed96ce0
//
// o.id o.__version, and o.__lastUpdate have special meaning or are reserved
//
graphdb.upsertVertexVersioned = async function(type, o) {
const g = traversal().withRemote(this.connection);
let oldVersion;
if (!o.id) {
o.id = uuidv4();
}
if (!o.__version) {
o.__version = 0;
oldVersion = 0;
} else {
oldVersion = o.__version;
o.__version++;
}
o.__lastUpdate = Date.now();
// @see http://tinkerpop.apache.org/docs/current/recipes/#element-existence
// The pattern we are using is keys get copied into properties that can be used
// by the graph database for its work, and then the
// entire object is JSON serialized into a generic `obj` property.
// XXX TBD use graphson?
const v1 = await g.V().has(type, 'id', o.id)
.fold()
.coalesce(__.unfold(),
__.addV(type).property('id', o.id)
.property('version', o.__version)
).choose(__.values('version').is(oldVersion),
__.in_()
.property('lastUpdate', o.__lastUpdate) // updated properties go here
.property('version', o.__version) // updated properties go here
.property('obj', JSON.stringify(o)), // updated properties go here
__.out()
).next();
return o;
};
References:
- Understanding different methods for adding edges with Gremlin-Python
- http://tinkerpop.apache.org/docs/current/recipes/
Versions
- janusgraph/janusgraph:latest
- gremlinjs 3.4.4
I tried a variation of your code using the "modern" toy graph and your code proved out to be right to me. I believe the following captures the spirit of what you were doing:
I would suggest trying to simplify a bit given your description of the problem. You stated the problem was that:
Does it work properly if you remove the
choose()
logic? In other words, can you get the basic upsert operation to work? If not, then the problem seems isolated to that part of the query, though what you have seems to follow recommended practices, so I'm not sure what might be amiss.