如何在两个当前连接的顶点之间插入顶点?

时间:2016-10-11 21:52:00

标签: titan gremlin tinkerpop tinkerpop3

我正在努力与格雷姆林交手。彻底阅读了文档后,我似乎仍然在概念上苦苦思索。

我正在创建一个基本的新闻源,遵循Neo4j文档中的模型:

http://neo4j.com/docs/snapshot/cypher-cookbook-newsfeed.html

我实际上正在使用titandb,但遵循上面显示的相同原理/架构。

到目前为止,我已经创建了user个顶点的图表,这些顶点通过friend边连接。

我可以添加一个新的post顶点并通过posted边缘将其连接到user顶点,如下所示:

 def activity = graph.addVertex(T.label, "post");
 activity.property("post_id", post_id);
 activity.property("time", time);
 activity.property("body", body);

 def g = graph.traversal();
 def user = g.V().hasLabel("user").has("userid", userid).next();
 user.addEdge("posted", activity, "time", time);

但是,我需要能够在一个Gremlin脚本中执行以下操作:

  1. 创建新的post顶点,如上所述。
  2. 移除posted与当前连接的任何user顶点之间的旧post边缘。但仅当时,当前存在一个帖子。
  3. 将新的post顶点附加到user,并使用新的posted边缘。
  4. 最后,如果有一个先前的post顶点,请通过post边缘将其附加到新添加的next顶点。最终为每个用户创建大量帖子。
  5. 我一直在玩,尝试使用反复试验,现在几个小时,似乎无法理解它。

    非常感谢任何帮助。

2 个答案:

答案 0 :(得分:5)

另一种方式(使用单次遍历):

使用单个用户创建初始图表:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV("user").property("userid", 123)
==>v[0]

添加第一篇帖子:

gremlin> g.V().has("user", "userid", 123).as("user").      /* find the user                            */
           addV("post").as("p").property("post_id", 1).    /* add a new post                           */
             property("time", System.currentTimeMillis()).
             property("body", "bla bla").
           addE("posted").from("user").as("e").            /* connect user and post                    */
             property("time", System.currentTimeMillis()).
           outV().                                         /* traverse to user                         */
           outE("posted").where(neq("e")).as("o").         /* traverse to any pre-existing posted edge */
           inV().                                          /* traverse to pre-existing post            */
           addE("next").to("p").                           /* connect it with the new post             */
           select("o").drop()                              /* drop the old posted edge                 */

gremlin> // check
gremlin> g.V().not(inE()).repeat(union(outE("posted").inV(), inE("next").outV())).until(__.not(union(outE("posted"), inE("next")))).path().by(label)
==>[user, posted, post]

添加其他帖子(相同查询):

gremlin> g.V().has("user", "userid", 123).as("user").
           addV("post").as("p").property("post_id", 1).
             property("time", System.currentTimeMillis()).
             property("body", "bla bla").
           addE("posted").from("user").as("e").
             property("time", System.currentTimeMillis()).
           outV().
           outE("posted").where(neq("e")).as("o").
           inV().
           addE("next").to("p").
           select("o").drop()

gremlin> // check
gremlin> g.V().not(inE()).repeat(union(outE("posted").inV(), inE("next").outV())).until(__.not(union(outE("posted"), inE("next")))).path().by(label)
==>[user, posted, post, next, post]

答案 1 :(得分:4)

以下是您可能采取的一种方式:

gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> createPost = { user, post -> 
......1>   u = g.V().has('userId', user).next()
......2>   previous = g.V(u).outE('posted').inV().tryNext().orElse(null)
......3>   g.V(u).outE('posted').drop().iterate()
......4>   activity = graph.addVertex(T.label, "post", "postId", post)
......5>   u.addEdge("posted", activity)  
......6> 
......6>   if (null != previous) previous.addEdge('next', activity)
......7> 
......7>   // with titan you would want to commit the transaction
......8>   // graph.tx().commit()
......9> }
==>groovysh_evaluate$_run_closure1@522b2631

然后添加用户并多次调用createPost()函数:

gremlin> user = g.addV(label,"user", "userId", "me").next()
==>v[0]
gremlin> createPost("me",1)
gremlin> createPost("me",2)
==>e[8][2-next->5]
gremlin> createPost("me",3)
==>e[12][5-next->9]
gremlin> createPost("me",4)
==>e[16][9-next->13]
gremlin> createPost("me",5)
==>e[20][13-next->17]

你可以看到"发布"针对最新的" post"顶点:

gremlin> g.V().has('userId','me').outE()
==>e[19][0-posted->17]

如果我们从那里沿着传入的"接下来"您可以访问上一篇文章:

gremlin> g.V().has('userId','me').out('posted').in('next')
==>v[13]

以下显示了之前的三篇帖子:

gremlin> g.V().has('userId','me').out('posted').in('next').in('next')
==>v[9]

您还可以沿next遍历任意深度:

gremlin> g.V().has('userId','me').
               out('posted').
               repeat(__.in('next')).
                 until(inE().count().is(0)).emit().
               path().
                 by(choose(label().is('post'),
                      values('postId'),
                      values('userId')))
==>[me,5,4]
==>[me,5,4,3]
==>[me,5,4,3,2]
==>[me,5,4,3,2,1]