1
votes

I have a simple graph of the type:

(3) -> (2) -> (1)
 |     | |     |
(D)    |(B)   (A)
      (C)

In this case, I want to traverse, from (3) to (1). Think of this as a tree where node (1) is the root and node (3) is a leaf and the edges between (3) to (2) and (2) to (1) represent parent relationship (2 is parent of 3, etc.).

At the same time, each vertex that represents tree node (1, 2, 3) has one or more edges that represent permissions relationships, so in this case, (A) represents a user and the relationship between (1) to (A) represents a permission (access) the user (A) has over (1). In the case of (2), there are two users that have access to this vertex (B and C).

You can imagine that nodes with numbers are "folders" and have certain attributes (i.e. name) and nodes with letters are users or permissions and have certain attributes too (i.e name, type of access, etc).

I can successfully traverse the graph from 3 to 1, printing properties of each of the nodes in the path (see example below).

So for example if I do:

gremlin> g.V('3').repeat(out()).until(has(id, '1')).path().by('name')
==>[folder1.1, folder1, root]

or

gremlin> g.V('3').repeat(out()).until(has(id, '1')).path().by('name')
==>[folder1.1, folder1, root]

gremlin> g.V('3').repeat(out('parent').simplePath().store('x')).until(has(id, '1')).cap('x')
==>{v[2]=1, v[1]=1}

// Although at this point I missed listing v[3]

The problem is that I need to traverse the tree and collect the permissions in the way, for example (and format may vary) I'm looking for a way to get something in the lines of:

gremlin> ...
==>[ { { 3, name="foo" } , [ { D, permission="x" } ] }, { 2, [ {A, permission="y" }, {B, permission="z"} ] }, { { 3, name="foo" } , [ { D, permission="x" } ] } ]

Basically I want to traverse the path from (3) to (1) (there may be more than just three nodes), collecting attributes of the vertex in the path, and collecting vertex related to certain out edges (just one level, I don't want to expand beyond a single edge in depth for permissions) together with their attributes.

Note that I'm very new to gremlin, and I've been trying and learning in the process for a couple of days without even knowing if it is possible...

Any idea, suggestion would be appreciated, thanks!

1

1 Answers

1
votes

When you do this:

gremlin> g.V('3').repeat(out()).until(has(id, '1')).path().by('name')
==>[folder1.1, folder1, root]

recognize that the by() modulator to path() is simply a transformation. The modulator is being applied in a round-robin fashion to each item in the path (since you only supplied one by()). That transformation says, "take the graph element (i.e. Vertex) in the path and extract the 'name' property value and return that rather than the actual vertex."

Given that knowledge you really just need a different form of transformation to get the data that you want from the path. Note that by() has an overload that takes a Traversal as an argument which means you can apply a Traversal to each graph element in the path. I would think that project() would be a good step to use to produce the output you want - something like:

g.V('3').repeat(out()).until(has(id, '1')).
  path().
    by(project('name','permissions').
         by('name').
         by(out('permissions').fold()))

Note that the above is saying, "for each vertex in the path, project it to a Map with keys 'name' and 'permissions' where 'name' is the 'name' value from the vertex in the path and 'permissions' is a list of related permission vertices."