如何在两个当前连接的顶点之间插入一个顶点?
How can I insert a vertex between two currently connected vertexes?
我正在努力掌握 Gremlin。彻底阅读文档后,我似乎仍然在概念上苦苦挣扎。
我正在创建一个基本的新闻源,遵循此处 Neo4j 文档中的模型:
http://neo4j.com/docs/snapshot/cypher-cookbook-newsfeed.html
我实际上使用的是 titandb,但我遵循与上面所示相同的 principles/schema。
到目前为止,我已经创建了一个包含 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 脚本中执行以下操作:
- 如上所述创建新的
post
顶点。
- 删除
user
和任何当前连接的 post
顶点之间的旧 posted
边。但是仅当,当前存在post。
- 使用新的
posted
边将新的 post
顶点附加到 user
。
- 最后,如果之前有一个
post
顶点,则通过 next
边将其附加到新添加的 post
顶点。最终为每个用户创建 post 的长流。
我一直在尝试,尝试和错误,现在似乎已经好几个小时了,但似乎无法理解它。
如有任何帮助,我们将不胜感激。
您可以采用以下一种方法:
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]
可以看到 "posted" 边指向最新的 "post" 顶点:
gremlin> g.V().has('userId','me').outE()
==>e[19][0-posted->17]
如果我们从那里沿着传入的 "next" 边穿过,您可以到达前一个 post:
gremlin> g.V().has('userId','me').out('posted').in('next')
==>v[13]
以下显示前三个 post:
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]
另一种方式(使用单遍历):
创建单个用户的初始图表:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV("user").property("userid", 123)
==>v[0]
添加第一个post:
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]
添加另一个 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]
我正在努力掌握 Gremlin。彻底阅读文档后,我似乎仍然在概念上苦苦挣扎。
我正在创建一个基本的新闻源,遵循此处 Neo4j 文档中的模型:
http://neo4j.com/docs/snapshot/cypher-cookbook-newsfeed.html
我实际上使用的是 titandb,但我遵循与上面所示相同的 principles/schema。
到目前为止,我已经创建了一个包含 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 脚本中执行以下操作:
- 如上所述创建新的
post
顶点。 - 删除
user
和任何当前连接的post
顶点之间的旧posted
边。但是仅当,当前存在post。 - 使用新的
posted
边将新的post
顶点附加到user
。 - 最后,如果之前有一个
post
顶点,则通过next
边将其附加到新添加的post
顶点。最终为每个用户创建 post 的长流。
我一直在尝试,尝试和错误,现在似乎已经好几个小时了,但似乎无法理解它。
如有任何帮助,我们将不胜感激。
您可以采用以下一种方法:
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]
可以看到 "posted" 边指向最新的 "post" 顶点:
gremlin> g.V().has('userId','me').outE()
==>e[19][0-posted->17]
如果我们从那里沿着传入的 "next" 边穿过,您可以到达前一个 post:
gremlin> g.V().has('userId','me').out('posted').in('next')
==>v[13]
以下显示前三个 post:
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]
另一种方式(使用单遍历):
创建单个用户的初始图表:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV("user").property("userid", 123)
==>v[0]
添加第一个post:
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]
添加另一个 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]