I have a graph database in Azure CosmoDB that stores how similar vertices are and the edge contains the numeric value of how similar they are.
The complication is that I want to add an edge or update by incrementing the similarity value. This is the current code I have for adding:
g.V('A').addE('similar').to(g.V('B')).property('x', 10)
I need something that will increase X if the edge exists, or create it if not. Pseudo code exemplifying it:
g.V('A').updateE('similar').to(g.V('B')).property('x', currentValue+2).ifNulll({g.V('A').addE('similar').to(g.V('B')).property('x', 10)})
is there an easy way to achieve this ?
There is a known recipe for checking existence by using the pattern fold().coalesce(unfold()...) for vertex and similar pattern for edge. In your case, you want to update a property value as well.
Assuming there are vertices with IDs A and B, and edge goes from A-->B, the query might look like this:
g.withSack(0).V('B').as('toV').V('A').coalesce(
outE('similar').where(inV().as('toV')),
addE('similar').to('toV').property('similarity', 0)
)
.sack(assign).by('similarity').sack(sum).by(constant(2))
.property('similarity', sack())
Explanation:
Get B (target) vertex and save reference, get A (source) vertex.
Using coalesce, check if there is an edge connecting them, otherwise create such edge and set similarity to 0.
Assign the 'similarity' value to the sack, and sum the additional value.
Last, store the new value on the edge property.
Another query without using sack:
g.V('B').as('toV').V('A').coalesce(
outE('similar').where(inV().as('toV')),
addE('similar').to('toV').property('similarity', 0)
).property('similarity', values('similarity').fold(10, sum))
Related
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")
The following query searches for the set of shortest paths from a given vertex (377524408) to another vertex that has an edge with the property test_property, and exits after 3 iterations (i.e. if no vertex is found on 3 traverses, we return no paths).
s.V(377524408).repeat(both().simplePath())
.until(or(__.bothE().has('test_feature', gt(0)),
loops().is(lt(4))))
.path().dedup().toList()
However, I want to filter the edges on which the above query traverses.
For example, only traverse edges that have a property filter_property < 100. How would I modify the above query to include this edge filter?
Instead of both().simplePath() you would use bothE().has('filter_property', lt(100)).otherV().
Also, note, that loops().is(lt(4)) will always evaluate true in the first iteration. You probably want that to be loops().is(3).
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')
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])
i am using mxgraph to show the process. I need to select a edge programtically. The mxgraph provids selectEdges(true,false,false) which will select all the edges in the graph. But i need to select a particular edge in the graph.
Suppose if there is vertex1, vertex2 and vertex3. Each of these vertex is connected using edges. I need to select the edge between vertex2 and vertex3. Whether mxgraph provides any api to dod so? Please help me.
The mxGraph class hold a mxGraphSelectionModel instance, which is where you perform most of the selection operations. clear() and addCell(Object) will give you the result you require.
You should use GraphComponent.
Use graphComponent.getCellAt(x,y) ( x y are you mouse/click coordinates)
when you get the returned object, make sure it is an edge by checking the boolean isEdge().
So if you have the x, y programatically you can use the same process I described.
For example u can get the common edge of two vertices and it would be your edge.