Upsert properties using Gremlin - gremlin

I'm using python and AWS Neptune.
I'm using the "upsert" pattern by id:
g.V().has(node_type,'id',node.id).fold()
.coalesce(__.unfold(),__.addV('node_type').property('id',node.id)).
property('property','first').next()
Indeed the the vertex is added (Or selected from the graph) with the added property.
Now I want to add two more properties which I fail to add:
I want to add "max" property. If the vertex has the property, I want to take the max value of it and the value "10" (for example). Tried to add the following statement to my query but it doesn't work:
property('time_max', __.max(__.values('max'), 10))
But I'm getting an exception the "Could not locate method: DefaultGraphTraversal.max"
Another property that Increments "count" property the same way. I got the same exception on the "sack" method.
How can these properties can be added? Is the only way is to get the vertex and then commit it? I want it to be as efficient as possible.
Thanks!

The max() step is used to find the maximum value in a stream or collection such as in this simple example:
gremlin> g.inject(1,2,3).max()
==>3
You could do something like this instead
union(values('max'),constant(10)).max()

Related

How to get properties hasid/key with vertexes info in one gremlin query or Gremlin.Net

I try to get properties which has key or id in following query by Gremlin.Net, but vertex info(id and label) in VertexProperty is null in result.
g.V().Properties<VertexProperty>().HasKey(somekey).Promise(p => p.ToList())
So i try another way, but it's return class is Path, and i had to write an ugly code for type conversion.
g.V().Properties<VertexProperty>().HasKey(somekey).Path().By(__.ValueMap<object, object>(true))
Is there a better way to achieve this requirement
I think basically the only thing missing to get what you want is the Project() step.
In order to find all vertices that have a certain property key and then get their id, label, and then all information about that property, you can use this traversal:
g.V().
Has(someKey).
Project<object>("vertexId", "vertexLabel", "property").
By(T.Id).
By(T.Label).
By(__.Properties<object>(someKey).ElementMap<object>()).
Promise(t => t.ToList());
This returns a Dictionary where the keys are the arguments given to the Project step.
If you instead want to filter by a certain property id instead of a property key, then you can do it in a very similar way:
g.V().
Where(__.Properties<object>().HasId(propertyId)).
Project<object>("vertexId", "vertexLabel", "property").
By(T.Id).
By(T.Label).
By(__.Properties<object>(someKey).ElementMap<object>()).
Promise(t => t.ToList());
This filters in both cases first the vertices to only have vertices that have the properties we are looking for. That way, we can use the Project() step afterwards to get the desired data back.
ElementMap should give all information back about the properties that you want.
Note however that these traversals will most likely require a full graph scan in JanusGraph, meaning that it has to iterate over all vertices in your graph. The reason is that these traversals cannot use an index which would make them much more efficient. So, for larger graphs, the traversals will probably not be feasible.
If you had the vertex ids available instead of the property ids in the second traversal, then you could make the traversal a lot more efficient by replacing g.V().Where([...]) simply with g.V(id).

How to filter by property in Gremlin (if exist)?

I am new Gremlin and having trouble with filtering by property.
A -> B
Assume A and B are vertices and has edge between them with properties Created_on and deleted_on.
deleted_on property will be added only at the time of deletion.
How list by the edge property?
g.V(id).outE('Label').has('deleted_on', lt(timestamp.now())).outV().elementMap()
The above query returns empty, because the deleted_on property is not added to the edge yet.
How to handle this?
I'm not completely sure but I think you are looking to find all connections where the deleted_on property is less than now or it does not exist. If that is the case then you can use the or() and hasNot() steps in Gremlin to accomplish this similar to the query below.
g.V(id).
outE('Label').
has('deleted_on', lt(timestamp.now())).
or().
hasNot('deleted_on').
outV().
elementMap()

Add Additional Property to Neptune DB

I am trying to add additional property called "insert_date" to the existing vertices and edges. I tried
g.V().setProperty('insert_date',datetime('2020-10-06'))
Error:
{
"requestId": "33cf8df5-3cbe-41ac-b650-5752debec04d",
"code": "MalformedQueryException",
"detailedMessage": "Query parsing failed at line 1, character position at 10, error message : token recognition error at: 'rop'"
}
I am trying the above command from Neptune Notebook.
It just adds new vertices with insert_date property. But I did not find the way to alter existing vertices or edges.
Please suggest if this is possible. As I want to implement delta extraction so that I can extract only new vertices or edges every time I run ETL.
Thanks
To add a property to an existing vertex in Gremlin you use the property() step. For example, if you wanted to add a property insert_date to a vertex with the id of A you would use the following statement:
g.V('A').property('insert_date', '2020-10-06')
The property() step will add or update the specified property to the new value. This will occur for all the current elements being passed in. For example, if you only wanted to update the elements that did not have an insert_date property you could do this via:
g.V().hasNot('insert_date').property('insert_date', '2020-10-06')
In each of these example the property will be added as part of an array of values. If you want to set the property to only contain a single value then you can use the property() step overload that takes the cardinality like this:
g.V('A').property(Cardinality.single, 'insert_date', '2020-10-06')
One thing to note in the code you have listed above. While Neptune does support the datetime() function for string-based queries, if you are not using a GLV then you will need to create this value and pass in a Native Date/Time as described here.
Below Command worked to add additional properties to existing Graph.
g.V().property("insert_date","2020-01-01 00:00:00")

Gremlin: property name with static and dynamic

I'm trying create a property of vertice with static and dynamic value using selected properties. Here the code:
g.V('%s').as('source')
.until(or(hasLabel('target').has('v', '1'),loops().is(10)))
.repeat(__.in())
.outE('e').as('edge')
.inV().as('u')
.select('source')
.property(single, 'v', '1')
.property(single, union(constant('p_'),select('u').id()), select('e').properties('r').value())
This query is to copy property of edges as value and id of vertice as name of property with prefix 'p_'. The copy works, but the property name does not works, it's saving just prefix 'p_'.
Any ideas about this behaviour? I'm using tinkerpop 3.4.3, same the Neptune version.
Thanks!
The union() step in this traversal will not return a concatenation of the prefix and the property as you are hoping. Instead, it will return a single traverser for each item in the union(). In this case one containing "p_", one containing the id(), and one containing the "r" property.
Unfortunately, Gremlin does not have a string concatenation function that will accomplish this for you. See this below:
Concatenate Gremlin GraphTraversal result with string
As you are using Neptune the proposed solution in that answer will not work either as Neptune does not support lambdas in a traversal. Unfortunately, in this scenario the best way to accomplish this is likely to return the data to your application, concatenate the strings, and then update the property.

When is it appropriate to use g.query()...vertex() vs g.V.has()

I'm a little confused about this one. Several similar examples can be found throughout the documentation. Such as :
g.V.has('name','hercules').next()
g.query().has("name",EQUAL,"hercules").vertices()
Could someone clarify what the difference in the process is between the two above?
Thanks
The first is gremlin-groovy syntax:
g.V.has('name','hercules').next()
and either iterates all vertices looking for vertices that have a "name" property with a value of "hercules". In the event that "name" is indexed then titan will utilize the index to avoid the linear scan to find such vertices.
The second is basically Java and the Titan API. The above gremlin-groovy code basically compiles down to your second statement:
g.query().has("name",EQUAL,"hercules").vertices()
however, in the case of the second statement it returns an iterator of all vertices that match the filter and doesn't just pop off the first one as shown in the gremlin statement (given the use of next()).

Resources