在 TinkerPop3 中展平图遍历图
Flatten a graph traversal map in TinkerPop3
我的用例是系统的当前用户有 access to
一组组。这些组可以 belong to
其他组。所以我想在一个查询中获取所有基本组和父组。
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")
然而,这显然是 return 地图,但是我想 return 只是顶点,这样我就可以 union
在另一个遍历中。
运行 上述查询针对
的种子样本数据
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();
任何提示或改进想法将不胜感激。
更新:
下面的查询似乎对我有用。不确定这是不是最好的方法。
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")
)
感谢您更新您的回答。请注意,您的示例数据脚本可以写成:
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()
这对某些人来说可能更直观。另请注意,您提供的工作遍历可以简化为:
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]
请注意在 until()
中使用 outE()
而不是 out()
- 这是一项重要的优化,因为您只需要计算那里的边数即可跳出循环。计算这些边上的相邻顶点的成本更高。
这是我尝试改进您目前所获得的内容的尝试:
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]
也许我根据您提供的示例数据做了太多假设,但如果您可以假设 "group" 顶点没有传出 "access-to" 边,那么 Gremlin 将只会遍历 "belongs-to" 在远离 "user" 的第一步之后的边缘,遍历会给你你想要的。我想你仍然需要 simplePath()
和 dedup()
步骤,因为我想组可以属于多个父组,此时你可能会一遍又一遍地遍历相同的路径。
我的用例是系统的当前用户有 access to
一组组。这些组可以 belong to
其他组。所以我想在一个查询中获取所有基本组和父组。
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")
然而,这显然是 return 地图,但是我想 return 只是顶点,这样我就可以 union
在另一个遍历中。
运行 上述查询针对
的种子样本数据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();
任何提示或改进想法将不胜感激。
更新: 下面的查询似乎对我有用。不确定这是不是最好的方法。
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")
)
感谢您更新您的回答。请注意,您的示例数据脚本可以写成:
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()
这对某些人来说可能更直观。另请注意,您提供的工作遍历可以简化为:
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]
请注意在 until()
中使用 outE()
而不是 out()
- 这是一项重要的优化,因为您只需要计算那里的边数即可跳出循环。计算这些边上的相邻顶点的成本更高。
这是我尝试改进您目前所获得的内容的尝试:
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]
也许我根据您提供的示例数据做了太多假设,但如果您可以假设 "group" 顶点没有传出 "access-to" 边,那么 Gremlin 将只会遍历 "belongs-to" 在远离 "user" 的第一步之后的边缘,遍历会给你你想要的。我想你仍然需要 simplePath()
和 dedup()
步骤,因为我想组可以属于多个父组,此时你可能会一遍又一遍地遍历相同的路径。