I am trying to to grips with Gremlin. Having thoroughly read the documentation I still appear to be struggling with it conceptually.
I am creating a basic newsfeed, following the model found in the Neo4j documentation here:
http://neo4j.com/docs/snapshot/cypher-cookbook-newsfeed.html
I am actually using titandb, but am following the same sort of principles/schema as shown above.
So far I have created a graph of user
vertexes, which are connected via friend
edges.
And I am able to add a new post
vertex and connect it via a posted
edge to a user
vertex like so:
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);
However, I need to be able to do the following in a single Gremlin script:
post
vertex, as above.posted
edge between the user
and any currently connected post
vertex. But only if, a post currently exists.post
vertex to the user
with a new posted
edge.post
vertex, attach it to the newly added post
vertex via a next
edge. Ultimately creating long streams of posts for each user.I've been playing around, using trial and error, for what seems like hours now, and just cannot seem to get my head around it.
Any help would be greatly appreciated.
Another way (using a single traversal):
Create the initial graph with a single user:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV("user").property("userid", 123)
==>v[0]
Add the first 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]
Add another post (same query):
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]