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]
Related
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())
Given a set of vertices (say, for simplicity, that I start with one: G.V().hasId("something")), I want to obtain all outgoing edges and their target vertices. I know that .out() will give me all target vertices, but without the information about the edges (which have properties on them, too). On the other hand, .outE() will give me the edges but not the target vertices. Can I obtain both in a single Gremlin query?
Gremlin is as much about transforming graph data as it is navigating graph data. Typically folks seem to understand the navigation first which got you to:
g.V().hasId("something").outE()
You then need to transform those edges into the result you want - one that includes the edge data and it's adjacent vertex. One way to do that is with project():
g.V().hasId("something").outE()
project('e','v').
by().
by(inV())
Each by()-modulator supplied to project() aligns to the keys supplied as arguments. The first applies to "e" and the second to "v". The first by() is empty and is effectively by(identity()) which returns the same argument given to it (i.e. the current edge in the stream).
Never mind. Figured this out.
G.V().hasId("something").outE().as("E").otherV().as("V").select("E", "V")
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')
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.
I want to set the edge attributes of a certain range of edges in a graph based on the values of the nodes they connect (in R igraph of course).
When I retrieve a certain edge in my graph object, I am served with an edge sequence object:
E(g)[1]
# + 1/2080 edge (vertex names):
# [1] 35->1
class(E(g)[1])
# [1] "igraph.es"
How can I get to the actual edges from that edge sequence? The only relevant function I have found is as_ids:
as_ids(E(g)[1])
# [1] "35|1"
Then I have to split the string to get to the node ids, convert the ids to integers, fetch the nodes using the V(g)[x] notation, check the attributes I am interested in and finally set the edge attribute.
This is an impractical and wasteful process. Is there any more straightforward way to do the same?
I know the %--% notation and in certain cases it solves my issue by allowing me to filter the edges based on node attributes in advance. But in many other cases that notation doesn't help (when edge attribute values have a more complex relationship with node attributes), and I wonder if there is a more general way to get from one edge sequence to the corresponding pair of nodes.
You can use the ends function to get to the vertices:
ends(g, E(g)[1])