【问题标题】:Gremlin repeat() query takes really long timeGremlin repeat() 查询需要很长时间
【发布时间】:2017-10-04 19:35:36
【问题描述】:

我有一个用例,我需要在每个级别获取特定类型的顶点数量,直到定义的级别。 例如:

A 对 B(管理员)、C(用户)、D(管理员)有优势

B (admin) 对 E(user), F(user), G(user), H(admin) 有优势

C(user) 对 I(admin), J(user), K(admin), L(admin) 有边, 男(管理员)

K(admin) 对 N(admin)、O(user)、P(admin)、Q(admin) 有出边, R(admin), S(user), T(user)

如果levels = 3,并且主题顶点是A,结果应该是(格式可以不同):

level=1,users=1,admins=2,total=3

level=2,users=4,admins=5,total=9

level=3,users=3,admins=4,total=7

我有一个为我执行此操作的查询,但是当我有大量数据时,由于 repeat(),它真的很慢。

for (int i = 0; i < levels; i++) {
     Map<Object, Long> next = 
     graphTraversalSource.V().hasLabel(GraphDbConnection.USER)
           .has(GraphDbConnection.UUID, "uuidValue").until(loops().is(i)).repeat(out()) 
     .out().values(GraphDbConnection.MEMBER_TYPE).groupCount().next();
     MemberSponsorMetrics memberSponsorMetrics = new MemberSponsorMetrics();
     memberSponsorMetrics.setLevel(i + 1);
     int users = next.getOrDefault(UserType.USER.ordinal(), (long) 0).intValue();
     memberSponsorMetrics.setUsers(users);
     int admins = next.getOrDefault(UserType.ADMIN.ordinal(), (long) 0).intValue();
     memberSponsorMetrics.setAdmins(admins);
     memberSponsorMetrics.setTotal(users + admins);
     memberSponsorMetricsList.add(memberSponsorMetrics);
}

我怎样才能以有效的方式实现这些结果?我可以使用任何特定的索引类型或其他东西吗?我确实有多个关于顶点属性的基本索引,但我认为它们在这里没有用。

【问题讨论】:

  • A 转到 B 和 C,因此在您的示例中只有 2 个级别,不是吗?
  • 是的,你是对的,我更新了我的数据,还为第 3 级添加了一个

标签: gremlin tinkerpop3 gremlin-server janusgraph


【解决方案1】:

示例图

g = TinkerGraph.open().traversal()
g.addV("person").property(id, "A").as("a").
  addV("person").property("memberType", 1).property(id, "B").as("b").
  addV("person").property("memberType", 0).property(id, "C").as("c").
  addV("person").property("memberType", 1).property(id, "D").as("d").
  addV("person").property("memberType", 0).property(id, "E").as("e").
  addV("person").property("memberType", 0).property(id, "F").as("f").
  addV("person").property("memberType", 0).property(id, "G").as("g").
  addV("person").property("memberType", 1).property(id, "H").as("h").
  addV("person").property("memberType", 1).property(id, "I").as("i").
  addV("person").property("memberType", 0).property(id, "J").as("j").
  addV("person").property("memberType", 1).property(id, "K").as("k").
  addV("person").property("memberType", 1).property(id, "L").as("l").
  addV("person").property("memberType", 1).property(id, "M").as("m").
  addV("person").property("memberType", 1).property(id, "N").as("n").
  addV("person").property("memberType", 0).property(id, "O").as("o").
  addV("person").property("memberType", 1).property(id, "P").as("p").
  addV("person").property("memberType", 1).property(id, "Q").as("q").
  addV("person").property("memberType", 1).property(id, "R").as("r").
  addV("person").property("memberType", 0).property(id, "S").as("s").
  addV("person").property("memberType", 0).property(id, "T").as("t").
  addE("link").from("a").to("b").
  addE("link").from("a").to("c").
  addE("link").from("a").to("d").
  addE("link").from("b").to("e").
  addE("link").from("b").to("f").
  addE("link").from("b").to("g").
  addE("link").from("b").to("h").
  addE("link").from("c").to("i").
  addE("link").from("c").to("j").
  addE("link").from("c").to("k").
  addE("link").from("c").to("l").
  addE("link").from("c").to("m").
  addE("link").from("k").to("n").
  addE("link").from("k").to("o").
  addE("link").from("k").to("p").
  addE("link").from("k").to("q").
  addE("link").from("k").to("r").
  addE("link").from("k").to("s").
  addE("link").from("k").to("t").iterate()

现在您正在寻找的结果可以使用一次遍历来收集,实际上不需要一遍又一遍地执行几乎相同的遍历(只需更改循环数)。

gremlin> g.V("A").
           repeat(out("link").
                  group("x").
                    by(loops()).
                    by(groupCount().
                         by(branch(values("memberType")).
                              option(0, constant("user")).
                              option(1, constant("admin"))))).
             times(3).
           cap("x")
==>[0:[admin:2,user:1],1:[admin:5,user:4],2:[admin:4,user:3]]

外层map的key基本都是level-1。

此查询在 TinkerGraph 上大约需要 1 毫秒。因此,除非您的分支因子要高得多,否则您应该很快就能得到结果。但是,如果分支因子很高并且您实际上要处理数千个顶点,则应考虑在 OLAP 中运行此查询。

【讨论】:

  • 所以,我想我忘了提到几件事,“user”和“admin”将是顶点属性的值(假设 key = memberType),并且该值不是字符串,我只是用它作为字符串来解释问题,它们是整数(0 = 用户,1 = 管理员)。当您使用 groupCount().by('memberType') 时,它不会产生相同的输出,它会将它们全部汇总并使用您的示例返回“[0:[admin:7,user:5]]”,替换“by (label)" with by('memberType')
  • 我使用大数据运行了您的查询和我的查询,我的查询运行 7 次(7 个级别)和您的查询运行 1 次以达到相同结果的总时间花费了相似的时间。 - 我仍然无法返回数组结果以获取每个级别的显示方式,我的结果作为整个组(所有级别)的总和返回,例如“{0={1=1487, 2=185}}”
  • 检查更新。我真的不确定你所说的“它把它们全部加起来”是什么意思,这不是我观察到的行为。
  • 例如,我仍然得到它们的总数 - 如果我对我的数据运行您发布的相同查询,而不是获取具有 3 个级别的数组,我得到的对象只有 1 个级别,但值是总计所有级别 - “{0: {admin:11, user:8}}” 所以 - admin = 2 + 5 + 4 和 user = 1 + 4 + 3
  • 我意识到了这个问题,我使用的是 JanusGraph 而不是直接使用 Tinkerpop。我在 tinkerpop 控制台中运行了相同的查询,它输出了您提供的预期结果。不知道为什么通过 janusgraph 使用 gremlin 会有所不同 - 有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2016-02-02
  • 2018-01-09
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多