TinkerPop 3 Gremlin Collect Edge Properties during traversal - gremlin

Using TinkerPop 3 Java APIs:
My graph looks like this:
james {risk: 'n'} --> chris {risk: 'n'} --> raj {risk: 'n'} --> joanne {risk: 'y'}
The edge label is 'travelledWith' and a property called 'pnrLocator'
Now, I want to traverse from james till a vertex where the risk is set to 'y'. Along the way, I'd want to collect the vertex and edge properties.
This is what I have which only works for vertex properties. How can I add a 'by' and collect the 'pnrLocator' too?
GraphTraversal<Vertex, ?> values =
g.traversal()
.V()
.has("personId", "james")
.repeat(out("travelledWith"))
.until(has("risk", "y"))
.limit(100)
.path()
.by("personId");
values.forEachRemaining(v -> System.out.println(v));

The path() step is going to output any elements Gremlin traverses given the steps you provided so, using the "modern" TinkerPop toy graph:
gremlin> g.V().repeat(out()).emit().path().by("name")
==>[marko,lop]
==>[marko,vadas]
==>[marko,josh]
==>[marko,josh,ripple]
==>[marko,josh,lop]
==>[josh,ripple]
==>[josh,lop]
==>[peter,lop]
I traversed out() which returns vertices so that's the only output I see in the path output. If I change my traversal a little to explicitly traverse the edges (i.e. out() to outE().inV()) then I can do this:
gremlin> g.V().repeat(outE().inV()).emit().path().by("name").by('weight')
==>[marko,0.4,lop]
==>[marko,0.5,vadas]
==>[marko,1.0,josh]
==>[marko,1.0,josh,1.0,ripple]
==>[marko,1.0,josh,0.4,lop]
==>[josh,1.0,ripple]
==>[josh,0.4,lop]
==>[peter,0.2,lop]

Related

Gremlin get elementMap() for vertices and valueMap() for edges when used with .bothE().otherV().path()

Assume we want to retrieve all in-coming and out-going edges for some specific vertex and have the result include from_vertex, edge and to_vertex.
The following should give us the result.
g.V(1).bothE().otherV().path()
==>path[v[...], e[...][...-...->...], v[...]]
The following adds .elementMap() for vertices and edge.
g.V(1).bothE().otherV().path().by(__.elementMap())
==>path[{...} {...} {...}]
Now, we want to retrieve the properties, where we want to use .elementMap() for the vertices and .valueMap() for the edges. My first guess is the following
g.V(1).
bothE().as("edges").
otherV().as("nodes").
path().
by(__.select("nodes").elementMap().select("edges").valueMap())
which just returns
==>path[null, null, null]
Any ideas?
Further, how to get the path output for an entire subtree starting from some specific vertex.
Your path will be an alternating list of node-edge-node etc. To get the desired results you just need to use two by modulators.
g.V(1).
bothE().
otherV().
path().
by(elementMap()).
by(valueMap())

Gremlin: how to identify which properties belong to which edges

I have a simple graph with two vertices, having ids 'a' and 'b'.
I have assigned two edges from 'a' to 'b' where each edge has the label = "foo"
[1] gremlin> g.V('a').outE()
==>e[f4b4b71d-ca98-5302-3eb1-7f99a7e74081][a-foo->b]
==>e[98b4b71d-c8c9-4ca2-9fbe-2f58e33d25e4][a-foo->b]
Each of the edges has a property with key = "committed".
[2] gremlin> g.E().properties()
==>p[committed->2]
==>p[committed->1]
My question: I want to enumerate the edges and return their respective properties as in step [2], but how can I match the edge-properties in the results back to their respective edges (ids)? All I get back are the property key-value assignments; nothing that relates to an edge id.
Thanks,
Joel Stevick
You should avoid returning graph elements like vertices and edges and instead transform your result to the specific form in which you need it. You could do that in a number of ways. In this case project() works nicely:
gremlin> g.V().outE().project('id','weight').by(id).by('weight')
==>[id:9,weight:0.4]
==>[id:7,weight:0.5]
==>[id:8,weight:1.0]
==>[id:10,weight:1.0]
==>[id:11,weight:0.4]
==>[id:12,weight:0.2]
or you could use valueMap() - on 3.4.0 you have the with() syntax:
gremlin> g.V().outE().valueMap('weight').with(WithOptions.tokens)
==>[id:9,label:created,weight:0.4]
==>[id:7,label:knows,weight:0.5]
==>[id:8,label:knows,weight:1.0]

Following edges who's properties match one on the source vertex with Gremlin

I have a graph, and I want to follow the edges that contain a property that matches one on the vertex. E.g.
vertex -------edge ---------> vertex
vertValue: 123 vert: 123 vertValue: 463
So in the above case, say I'm starting at the first vertex, I want to follow the edges that has the property 'vert' equal to it's 'vertValue'.
I've manage to make a query using where that manages to follow the edge:
g.V(id).as('verts')
.outE().values('vert')
.where(eq('verts'))
.by('vertValue')
Problem, is I want to return the actual edge object. However, as I need to do the 'where' on the 'vert' value of the edge, in the query I'm doing a values('vert') so the result I get is just the value I'm testing, not the edge object. I want to do something like:
g.V(id).as('verts')
.outE()
.where(eq('verts'))
.by('vertValue','vert')
To compare the 'vertValue' on the vertex, to the 'vert' value on the edge. But I can't seem to find a way to specify by on the 'input' values of the where.
Edit: Trying:
g.V("95c4a57a-9262-45b7-a905-8cca95d3ebb6").as('v').
outE().
where(eq('v')).
by('vert').
by('vertValue')
Returns an error:
Gremlin Query Execution Error: Select One: Get Projection: The provided traversal or property name of path() does not map to a value.
g.V("95c4a57a-9262-45b7-a905-8cca95d3ebb6").as('v').
outE().
where(eq('v')).
by('vertValue').
by('vert')
returns an empty array!
You got really close to the solution. It's:
g.V(id).as('v').
outE().
where(eq('v')).
by('vert').
by('vertValue')

Finding vertices without a particular edge with gremlin

I'm able to find all of my tag vertex points which have an edge labeled tagged using:
gremlin> g.V().hasLabel('tag').inE().hasLabel('tagged')
==>e[eas0-109ds-e8l-y8oo][1691776-tagged->1597560]
==>e[ed5c-109ds-e8l-1181s][1691776-tagged->1736704]
Now, I would like to remove all of the tag vertices which do not have an edge labeled tagged. When I use this command to find these vertices:
gremlin> g.V().hasLabel('tag').inE().hasNot('label', 'tagged')
I get the error message No signature of method: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.hasNot() is applicable for argument types: (java.lang.String, java.lang.String) values: [label, tagged]
How would I phrase this query?
Use the not() filter step:
g.V().hasLabel('tag').not(inE('tagged')).drop()

TinkerPop: Filter by Edge count

Sample data: TinkerPop Modern
Summary: I want to find People who have created 2 softwares.
I started with the basics, and got the count properly
g.V().hasLabel("Person").as("from" ,"to1" )
.repeat(bothE().as("e1").otherV().as("to1").dedup("from", "to1")).times(1)
.emit(filter(hasLabel("Software"))).hasLabel("Software")
.group().by(select("from").by("name")).by(count()).as("c")
Result:
>> {'Marko': 1, 'Peter': 1, 'Josh': 2}
So I tried to apply a filter but its not working (ie. Result is incorrect), what I tried:
g.V().hasLabel("Person").as("from")
.repeat(bothE().as("e1").otherV().as("to1").dedup("from", "to1")).times(1)
.filter(bothE().otherV().hasLabel("Software").count(local).is(eq(1)))
.dedup()
.values("name")
Any idea what am I doing wrong?
Sample data:
If you just need "person" vertices by edge count I don't really see why you need all that repeat() infrastructure. It's just:
gremlin> g.V().hasLabel('person').
......1> filter(outE('created').limit(2).count().is(2))
==>v[4]
You only need to count outgoing edges because the schema is such that the "created" label only connects to "software", so you don't need to check the
"software" vertex label. You limit(2) to exit the edge iteration as soon as possible but not before you have the 2 edges you are trying to count.

Resources