I am new to Neptune DB, I have created vertices and connected two vertices with edges and I have given some properties to both the edge and value
I want to retrieve both the edge and vertices properties values
Can someone provide me a sample query for this?
Thanks in advance.
Eg:
Vertices: p1, P2, p3
Edges E1-connecting P1 and P2, E2- connecting P2 and P3
Vertices property: name
Edge property: relation
Now I need to take out name and relation for all the vertices connected to P1
path step is what you are looking for. Using the by modulator you can select properties in a round-robin fashion, i.e. vertex-edge.
Start by locating p1 vertex:
g.V().hasLabel("testV").has("name","p1")
Repeat traversal along edges with "relation" property:
.repeat(outE("testE").has("relation").inV()).until(__.not(outE("testE")))
Get the traversal path (or tree), and select "name" for vertices, and "relation" for edges using the by modulator:
.path().by("name").by("relation")
To see results in arrays of strings:
.local(unfold().fold())
Note that this traversal doesn't handle cycles, but that's another question.
If you need only first level neighbors, you can take a different approach:
g.V().hasLabel("testV").has("name","p2").bothE()
.project("relation","name")
.by(values("relation"))
.by(otherV().values("name"))
Related
I am looking at a kryo file with the following vertices
# Tree Vertices
V(label=tree, properties={treeId:1, treeName:treeA})
V(label=tree, properties={treeId:2, treeName:treeB})
# Root Node Vertices
V(label=node, properties={treeId:1, nodeId:111, nodeType:root})
V(label=node, properties={treeId:2, nodeId:222, nodeType:root})
There are no edges between the vertices labeled as tree and the vertices labeled as node. There are further edges nodes connected to the root nodes but they are irrelevant to this question. I do not want to add any edges as this graph file gets vended to me and I am treating it as read-only.
Now I want to join/project the treeNames into a traversal over the root nodes.
g.V()
.hasLabel('node').has('nodeType', 'root')
.project('nodeId', 'treeId', 'treeName') # return nodeId, treeId, treeName for each root node
.by(values('nodeId'))
.by(values('treeId'))
.by(""" # pseudo-sqlish gremlin to clarify my intent
select treeName
from V().hasLabel('tree')
.where(values('treeid'), eq($thisNode.values('treeId'))
"""
)
In SQL terms I'd say: I want to run a subquery (fully independent sub traversal starting from scratch) and then join it with my outer traversal on a given property. And again: No edge between trees and roots.
WITH
trees as (SELECT treeId, treeName FROM vertices v WHERE v.label = 'tree'),
roots as (SELECT nodeId, treeId FROM vertices v where v.label = 'node')
SELECT roots.nodeId, roots.treeId, trees.treeName
FROM roots
JOIN trees ON (roots.treeId, trees.treeId)
So I am looking for a way to perform a projection based on another traversal + one of the returned vertex properties
How abusive is this?
How to do it?
You can do it by starting a new traversal inside the project like this:
g.V().hasLabel('node').
has('nodeType', 'root').as('root').
project('nodeId', 'treeId', 'treeName').
by(values('nodeId')).
by(values('treeId')).
by(coalesce(
V().hasLabel('tree').where(eq('root')).
by('treeId').
values('treeName'),
constant('tree not exist')
))
see the example here: https://gremlify.com/bybp7s9mdia
How abusive is this: Very.
starting a sub-query for each node vertex can be very 'heavy' performance-wise.
and it's missing all of the advantages of graph DB if your graph schema doesn't fit your requirement
I want to return a sub-graph that is attached to a certain vertex (Vertex 3). It should not matter how this sub-graph is structured in detail. Ultimately, all I want is to get the vertices and edges that make up the sub-graph.
Simple graph with sub-graph
Using the TinkerPop-modern sample graph you can do this with the following query:
graph = TinkerFactory.createModern()
g = graph.traversal()
g.E(8).drop() // Edge interferes with OP example graph
g.V(1).bothE().as('e').otherV().where(id().not(is(2))).repeat(
bothE().where(neq('e')).subgraph('subGraph').otherV().simplePath()
).emit().times(4).cap('subGraph').
next().traversal().V()
==>v[3]
==>v[4]
==>v[5]
==>v[6]
Explanation:
v(1) is the vertex connected to the subgraph to be found
v(2) is your start vertex, to be excluded from the subgraph
The edge between v(1) and the subgraph also needs to be excluded from the subgraph and gets a reference 'e'
The repeat(...).emit().times(4) does the looping starting from the subgraph's initial edge(s)
The where(neq('e')) makes sure v(1) is not included in the subgraph
cap('subGraph') makes the traversal hold a TinkerGraph objects, created from all the edges referenced by subgraph('subGraph')
next().traversal().V() returns the subgraph, creates a GraphTraversalSource from it and show all vertices in the subgraph
It does not seem possible to start the traversal from v(2), your start vertex, because gremlin's subgraph mechanism does not create separate subgraphs for different branches in the total graph but rather accumulates them in the global SideEffect referenced by 'subGraph'.
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 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]
I'm newbie to gremlin.
I'm trying to get all nodes which are connected(directly or indirectly) to a given vertices.
ex:
one cluster like this in a graph.
A-D
A-F
F-B
B-C
B-G
G-H
G-I
second cluster like this in a graph.
J-k
J-L
My Requirement when I search for the node "B", I need to get the all connected vertices for B (no edge direction) only.
ex output: A,D,F,B,C,G,H,I
When I search for J.
ex outpu:J,k,L
Any help would be appreciated, Thanks in advance.
It's as simple as:
g.V('B').emit().repeat(both().dedup()).toSet()
You basically traverse in both directions and emit every vertex you see until there's no new vertex found.