0

My use case is that a current user of the system has access to a set of groups. These groups can belong to other groups. So I would like to get to all the base groups and the parent groups in one query.

g.V(currentUser)
        .out("access-to")
        .has(label, "groups")
        .as("baseGrps")
        .aggregate("baseGrps")
        .until(out("belongs-to").count().is(0))
        .repeat(out("belongs-to").simplePath().aggregate("grps"))
        .cap("grps")
        .unfold()
        .dedup()
        .as("nestedGrps")
        .select("baseGrp", "nestedGrps")

However this is returning a map obviously, However I'd like to return just vertices so I can union in another traversal.

The seed sample data to run the above query against

g.addV("user")
  .property("name", "AUser")
  .as("aUser")
  .addV("group")
  .property("name", "UserGroup")
  .as("userGroup")
  .addV("userGroup")
  .property("name", "AdminUserGroup")
  .as("adminUserGroup")
  .addV("group")
  .property("name", "AllUserGroup")
  .as("allUserGrp")
  .select("aUser")
  .addE("access-to")
  .to("userGroup")
  .select("userGroup")
  .addE("belongs-to")
  .to("adminUserGroup")
  .select("adminUserGroup")
  .addE("belongs-to")
  .to("allUserGrp")
  .select("aUser")
  .next();

Any hints or improvements ideas will be really appreciated.

UPDATE: The below query is what seems to work for me. Not sure if its the best way.

g.V().has(T.label, "user").has("name", "AUser")
        .union(
            out("access-to")
                .as("baseGroups")
                .until(out("belongs-to").count().is(0))
                .repeat(out("belongs-to").simplePath())
                .emit()
                .dedup()
                .as("subGroups"),
            out("access-to")
        )
Sathyakumar Seshachalam
  • 2,013
  • 3
  • 20
  • 32
  • Could provide a Gremlin script that constructs some sample data that this traversal could be executed against. I think the quality of the answer you received would be much better if you could provide that. You might also explain more about what you want the final result to look like - right now you have a `Map` and you say you want vertices but how do you want "baseGrp" and "nestedGrp" - all together? or should they remain separate? If you can explain the final result better, they may be ways to optimize your entire traversal to get your answer. – stephen mallette Jan 18 '18 at 22:01
  • @stephenmallette : Hey, the final result should be a traversal with all together and should not be separate keys. I am looking at something like `g.V(currentUser).union(, )` – Sathyakumar Seshachalam Jan 19 '18 at 01:29
  • Also added another update to the question. Not sure if its an optimal query, but kind of works. – Sathyakumar Seshachalam Jan 19 '18 at 05:48

1 Answers1

1

Thanks for updating your answer. Note that your sample data script could be written as:

g.addV("user").
  property("name", "AUser").as("aUser").
  addV("group").property("name", "UserGroup").as("userGroup").
  addV("userGroup").property("name", "AdminUserGroup").as("adminUserGroup").
  addV("group").property("name", "AllUserGroup").as("allUserGrp").
  addE("access-to").from("aUser").to("userGroup").
  addE("belongs-to").from("userGroup").to("adminUserGroup").
  addE("belongs-to").from("adminUserGroup").to("allUserGrp").
  iterate()

which might be more intuitive for some. Also note, that the working traversal you supplied could be simplified a bit to:

gremlin> g.V().has("user","name", "AUser").
......1>   union(out("access-to").
......2>         until(outE("belongs-to").count().is(0)).
......3>           repeat(out("belongs-to").simplePath()).
......4>         emit().
......5>         dedup(),
......6>         out("access-to"))
==>v[4]
==>v[6]
==>v[2]

Note the use of outE() in until() as opposed to out() - that is an important optimization as you only need to count edges there to break out of the loop. Counting adjacent vertices on those edges is more costly.

Here's my attempt at improving upon what you've gotten so far:

gremlin> g.V().has("user","name", "AUser").
......1>   repeat(out('access-to','belongs-to').simplePath()).
......2>     until(outE("belongs-to").count().is(0)).
......3>   emit().
......4>   dedup()
==>v[2]
==>v[4]
==>v[6]

Perhaps I'm making too many assumptions given the example data you provided but if you can assume there are no outgoing "access-to" edges from the "group" vertices then Gremlin will only be traversing "belongs-to" edges after the first step away from the "user" and the traversal gives you what you want. I guess you still need the simplePath() and dedup() steps as I imagine groups can belong to multiple parent groups at which point you might traverse the same paths over and over again.

stephen mallette
  • 45,298
  • 5
  • 67
  • 135