【问题标题】:How can I compare sets of vertices for equality in TinkerPop?如何在 TinkerPop 中比较顶点集是否相等?
【发布时间】:2017-08-02 14:27:27
【问题描述】:

给定一组User 顶点,我需要找到与这些顶点相连的所有Chat 顶点,但没有其他顶点。例如,只有 AliceBob 参与的所有聊天。查询应该对结果进行排序,以便首先返回与最新消息相关的聊天。

在我最初的尝试中,我尝试从其中一个用户开始,访问他/她参与的所有聊天,并对其进行过滤,以便只保留那些完全由所有其他用户作为参与者的聊天。

traversal().V(user.id()) //random user of the set
            .out("participates")
            .hasLabel("Chat")
            .where(__.in("participates")
                    .hasLabel("User")
                    .fold()) //how could I match this collection against my set?

这是一个合适的方法吗?如何通过链接Messages 的时间戳匹配集合和顺序?感谢您的任何指点。

编辑感谢丹尼尔的回答,这是新的查询:

边、顶点、属性标签在实际产品中略有不同(ChatCONVERSATIONtimestampCREATED_ATparticipatesMEMBER_OF)和部分自定义枚举。 vertex 数组包含应该成为对话一部分的所有用户顶点。

traversal().V(vertices[0].id())
            .out(EdgeLabel.MEMBER_OF.name())
            .hasLabel(VertexLabel.CONVERSATION.name())
            .filter(__.in(EdgeLabel.MEMBER_OF.name())
                    .hasLabel(VertexLabel.USER.name())
                    .is(P.within(vertices)).count().is(vertices.length))
            .order().by(__.out(EdgeLabel.CONTAINS.name())
                        .values(PropertyKey.CREATED_AT.name())
                        .order().by(Order.decr).limit(1), Order.decr)

【问题讨论】:

    标签: java gremlin tinkerpop3


    【解决方案1】:

    让我们从示例图开始:

    g = TinkerGraph.open().traversal()
    g.addV("user").property("name", "alice").as("a").
      addV("user").property("name", "bob").as("b").
      addV("user").property("name", "caesar").as("c").
      addV("chat").property("name", "A").as("A").
      addV("chat").property("name", "B").as("B").
      addV("chat").property("name", "C").as("C").
      addV("message").property("timestamp", 1).property("text", "Sed mollis velit.").as("m1").
      addV("message").property("timestamp", 2).property("text", "Aenean aliquet dapibus.").as("m2").
      addV("message").property("timestamp", 3).property("text", "Nunc vel dignissim.").as("m3").
      addV("message").property("timestamp", 4).property("text", "Aliquam in auctor.").as("m4").
      addV("message").property("timestamp", 5).property("text", "Nulla dignissim et.").as("m5").
      addV("message").property("timestamp", 6).property("text", "Pellentesque semper dignissim.").as("m6").
      addE("participates").from("a").to("A").
      addE("participates").from("a").to("B").
      addE("participates").from("a").to("C").
      addE("participates").from("b").to("B").
      addE("participates").from("b").to("C").
      addE("participates").from("c").to("C").
      addE("contains").from("A").to("m1").
      addE("contains").from("A").to("m2").
      addE("contains").from("B").to("m3").
      addE("contains").from("B").to("m4").
      addE("contains").from("C").to("m5").
      addE("contains").from("C").to("m6").iterate()
    
    • Alice 参与了聊天 A、B 和 C。
    • Bob 参与了聊天 B 和 C。
    • Caesar 仅参与聊天 C。

    因此,如果我们现在查找 Alice 和 Bob 之间的对话,我们应该只找到 Chat B。果然:

    gremlin> g.V(users.head()).
               out("participates").
               not(__.in("participates").is(without(users))).
               filter(__.in("participates").is(within(users)).count().is(users.size())).
               order().by(out("contains").values("timestamp").order().by(decr).limit(1), decr).
               valueMap()
    ==>[name:[B]]
    

    如果时间戳是contains 边的一部分,会更容易和更快。

    【讨论】:

    • 非常感谢这个优雅的查询。我编写了各种测试用例以确保它做它应该做的事情。它仍然返回那些 将给定用户作为参与者的Chat 顶点,但不仅仅是那些。就像如果 A、B 和 C 在聊天,而我要求只与 A 和 B 聊天,我也会得到所有三个人的聊天。你认为它与.is(within(...)).count().is(...) 的串联有关吗?请查看我为当前 (Java) 查询编辑的问题。
    • 您是说您想要完全匹配吗?例如。如果你要求 A 和 B,那么 A 和 B 应该是这个聊天的唯一参与者?
    • 没错。我认为.is(within(users)) 过滤了所有不属于对话的用户,这意味着如果所有用户都参与了聊天,则后续的.count().is(users.size()) 将始终映射到true,无论是否有更多用户。你怎么看?
    • 精准!非常感谢,一个非常简洁的解决方案。
    猜你喜欢
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2012-02-15
    • 2013-03-29
    • 2010-12-10
    • 2015-03-13
    相关资源
    最近更新 更多