2017-08-02 23 views
0

给定一组User顶点,我需要找到所有连接到这些顶点的Chat顶点,但没有其他顶点。例如,所有只有Alice的聊天Bob参与。查询应该排序结果,以便最先返回与最新消息相关的聊天。如何比较TinkerPop中相等的顶点集?

Query Example

在我最初的尝试我试图从用户的一个开始,请访问他/她参加了所有的聊天记录,并筛选它们,以便只有那些聊天记录仍然是具有完全相同的所有其他用户参加。

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) 

回答

4

让我们开始与样品图表:

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() 
  • 爱丽丝参与聊天A,B和C.
  • 鲍勃参与聊天B和C.
  • 凯撒参与聊天只有C。

因此,如果我们现在寻找聊天与Alice和Bob之间的交谈中,我们只找到聊天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边缘。

+0

非常感谢这个优雅的查询。我编写了各种测试用例,以确保它能够做到应有的功能。它仍然返回那些''聊天'顶点,也有参与者给定的用户,但不只是那些。就像A,B和C在聊天中一样,我要求只有A和B在聊天,我也会得到这三个人的聊天。你认为它与'.is(in(...))。count()。is(...)''的连接有关。请参阅我编辑的问题以获取当前(Java)查询。 –

+0

你是说你想要完全匹配吗?例如。如果你要求A和B,那么A和B应该是这次聊天的唯一参与者? –

+0

没错。我认为'.is(在(用户)内)'过滤了所有不属于对话的用户,这意味着后续的'.count()。(users.size())'将总是映射到'true'如果所有的用户都是聊天的一部分,不管是否有更多。你怎么看? –