[Gremlin] The Generalize AsPipe model - back(), loop(), and table()

110 views
Skip to first unread message

Marko Rodriguez

unread,
Jun 10, 2011, 10:26:38 PM6/10/11
to gremli...@googlegroups.com
Hi people,

The 'as' pipe/step has come to be very handy. You can now use as() to name a step and it will work (naturally) for back(), loop(), and table().

Here are some examples over the graph defined here: 

*** BACK ***

gremlin> g.v(1).out('knows').as('x').filter{it.name.equals('josh')}.back('x')
==>v[4]
gremlin> g.v(1).out('knows').as('x').filter{it.name.equals('josh')}.back('x').name
==>josh


*** LOOP ***

gremlin> g.v(1).as('x').outE.inV.loop('x'){it.loops < 2}
==>v[2]
==>v[3]
==>v[4]

(NOTE: see how as('x').....loop('x') naturally wrap the loop point)


*** TABLE ***

gremlin> t = new Table()
gremlin> g.v(1).as('x').out.as('y').table(t)
==>v[2]
==>v[3]
==>v[4]
gremlin> t
==>[x:v[1], y:v[2]]
==>[x:v[1], y:v[3]]
==>[x:v[1], y:v[4]]


This is definitely a solid model and it has a natural mapping to the underling Pipes engine. Feel free to toString() a pipeline to see how it gets compiled.

Enjoy!,
Marko.

P.S. This is in GitHub and in TinkerPop Maven2 repository.


Pierre De Wilde

unread,
Jun 11, 2011, 8:17:14 AM6/11/11
to gremli...@googlegroups.com
Intuitive since it works (now) as expected.
Thanks, Marko.
Pierre


2011/6/11 Marko Rodriguez <okram...@gmail.com>

Marko Rodriguez

unread,
Jun 11, 2011, 11:41:55 AM6/11/11
to gremli...@googlegroups.com
Thanks for the support Pierre.

I'm really pumped up about 'as'. I couldn't wait to wake up and play with it this morning :).

g.v(89).as('x').out.as('y').name.groupCount(m).back('y').loop('x'){c++ < 100}

...here is the toString():

[AsPipe(x)[IdentityPipe], LoopPipe[[AsPipe(y)[OutPipe], BackFilterPipe[[PropertyPipe(name), GroupCountClosurePipe]]]]]
 
Sexy :).

The old 'as' model I was playing with was super convoluted and not programmically pretty -- I was being dumb about it. The new AsPipe solution was the key. AsPipe implements MetaPipe (a pipe that wraps another pipe -- simply has a getPipes() method). Other MetaPipes include LoopPipe, BackFilterPipe, Pipeline, AsPipe, AndPipe, OrPipe, SplitPipe, MergePipe. I'm sure we will find more uses into the future.......

Finally, check this out. With the way 'as' works, you can do recursive pattern matching --- a very attractive proposition.

gremlin> g.v(89).as('x').out.as('y').name.groupCount(m).back('y').loop('x'){c++ < 100}.name.as('z').table(t)
...
gremlin> t ==>[x:v[89], y:v[83], z:EYES OF THE WORLD] ==>[x:v[89], y:v[21], z:TRUCKING] ==>[x:v[89], y:v[206], z:SING ME BACK HOME] ==>[x:v[89], y:v[127], z:MORNING DEW] ==>[x:v[89], y:v[49], z:HES GONE] ==>[x:v[89], y:v[129], z:CHINA DOLL] ==>[x:v[89], y:v[149], z:SPANISH JAM] ==>[x:v[89], y:v[148], z:THE OTHER ONE] ==>[x:v[89], y:v[130], z:WHARF RAT] ==>[x:v[89], y:v[339], z:Hunter] ==>[x:v[89], y:v[340], z:Garcia] ==>[x:v[89], y:v[296], z:MIND LEFT BODY JAM]
...
..
.

Finally, see out: https://github.com/tinkerpop/gremlin/wiki/Pattern-Match-Pattern (have the new 2nd section. Check out t.apply{} :)


See ya,
Marko.

Pierre De Wilde

unread,
Jun 11, 2011, 12:55:14 PM6/11/11
to gremli...@googlegroups.com
Awesome.

Here is a way to convert a graph into simple triples:

gremlin> g.V.name.as('s').back(1).outE.label.as('p').back(1).inV.name.as('o').back(1).table(t)
...
gremlin> t
==>[s:marko, p:knows, o:vadas]
==>[s:marko, p:created, o:lop]
==>[s:marko, p:knows, o:josh]
==>[s:peter, p:created, o:lop]
==>[s:josh, p:created, o:ripple]
==>[s:josh, p:created, o:lop]

Pierre

Pierre De Wilde

unread,
Jun 11, 2011, 1:08:19 PM6/11/11
to gremli...@googlegroups.com
Unfortunately, there is a known issue that prevent Rexster to play with us:

{"results":[],"success":true,"version":"0.4-SNAPSHOT","queryTime":5.304064}

{"results":[{"_id":"2","_type":"vertex","name":"vadas","age":27},{"_id":"3","_type":"vertex","name":"lop","lang":"java"},{"_id":"4","_type":"vertex","name":"josh","age":32},{"_id":"3","_type":"vertex","name":"lop","lang":"java"},{"_id":"5","_type":"vertex","name":"ripple","lang":"java"},{"_id":"3","_type":"vertex","name":"lop","lang":"java"}],"success":true,"version":"0.4-SNAPSHOT","queryTime":124.003072}
Hope that Stephen may solve this issue.
Thanks,
Pierre

2011/6/11 Pierre De Wilde <pierre...@gmail.com>

Marko Rodriguez

unread,
Jun 11, 2011, 1:39:17 PM6/11/11
to gremli...@googlegroups.com
Thats cool.

One could create a Table->RDF converter.

Marko.

stephen mallette

unread,
Jun 11, 2011, 9:15:34 PM6/11/11
to Gremlin-users
Pierre, looks like the world is going to have to wait a little longer
on this fix. I took a stab at fixing it today:

https://github.com/tinkerpop/rexster/issues/110

sadly, I couldn't solve it. Marko, I assume that you got email
notification of my shame in not being able to solve this one. Please
take a look when you get a chance. Thanks.

On Jun 11, 1:08 pm, Pierre De Wilde <pierredewi...@gmail.com> wrote:
> Unfortunately, there is a known issue that prevent Rexster to play with us:
>
> http://localhost:8182/tinkergraph/tp/gremlin?script=t=new%20Table();g...
> <http://localhost:8182/tinkergraph/tp/gremlin?script=t=new%20Table();g...>
> {"results":[],"success":true,"version":"0.4-SNAPSHOT","queryTime":5.304064}
>
> http://localhost:8182/tinkergraph/tp/gremlin?script=t=new%20Table();g...)
> <http://localhost:8182/tinkergraph/tp/gremlin?script=t=new%20Table();g...)>
> {"results":[{"_id":"2","_type":"vertex","name":"vadas","age":27},{"_id":"3" ,"_type":"vertex","name":"lop","lang":"java"},{"_id":"4","_type":"vertex"," name":"josh","age":32},{"_id":"3","_type":"vertex","name":"lop","lang":"jav a"},{"_id":"5","_type":"vertex","name":"ripple","lang":"java"},{"_id":"3"," _type":"vertex","name":"lop","lang":"java"}],"success":true,"version":"0.4- SNAPSHOT","queryTime":124.003072}
>
> Hope that Stephen may solve this issue.
>
> Thanks,
>
> Pierre
>
> 2011/6/11 Pierre De Wilde <pierredewi...@gmail.com>

Pierre De Wilde

unread,
Jun 12, 2011, 3:06:46 AM6/12/11
to gremli...@googlegroups.com
Hey,

The solution was in the excellent Troubleshooting wiki page :

curl -X POST -d "script=m=[];g.v(1).out('knows').aggregate(m);m" http://localhost:8182/tinkergraph/tp/gremlin
{"results":[],"success":true,"version":"0.4-SNAPSHOT","queryTime":3.97696}
 
curl -X POST -d "script=m=[];g.v(1).out('knows').aggregate(m)>>-1;m" http://localhost:8182/tinkergraph/tp/gremlin
{"results":[{"_id":"2","_type":"vertex","name":"vadas","age":27},{"_id":"4","_type":"vertex","name":"josh","age":32}],"success":true,"version":"0.4-SNAPSHOT","queryTime":3.68896}

Therefore, to convert graph into triples:

curl -X POST -d "script=t=new Table();g.V.name.as('s').back(1).outE.label.as('p').back(1).inV.name.as('o').back(1).table(t)>>-1;t" http://localhost:8182/tinkergraph/tp/gremlin
{"results":["[s:marko, p:knows, o:vadas]","[s:marko, p:created, o:lop]","[s:marko, p:knows, o:josh]","[s:peter, p:created, o:lop]","[s:josh, p:created, o:ripple]","[s:josh, p:created, o:lop]"],"success":true,"version":"0.4-SNAPSHOT","queryTime":5.362944}

Admittedly, I don't grasp why we need to do that... Marko?

Pierre




2011/6/12 stephen mallette <spmal...@gmail.com>

Pierre De Wilde

unread,
Jun 12, 2011, 3:43:07 AM6/12/11
to gremli...@googlegroups.com
Thinking further, table results should be serialized differently.

Currently, Rexster returns:
[
"[s:marko, p:knows, o:vadas]",
"[s:marko, p:created, o:lop]",
"[s:marko, p:knows, o:josh]",
"[s:peter, p:created, o:lop]",
"[s:josh, p:created, o:ripple]",
"[s:josh, p:created, o:lop]"
]

I was expecting
[
{"s":"marko", "p":"knows", "o":"vadas"}, 
{"s":"marko", "p":"created", "o":"lop"}, 
{"s":"marko", "p":"knows", "o":"josh"}, 
{"s":"peter", "p":"created", "o":"lop"}, 
{"s":"josh", "p":"created", "o":"ripple"}, 
{"s":"josh", "p":"created", "o":"lop"}
]

Named steps combined with Table() are new stuff which leads to new clothes...

Thanks,
Pierre


2011/6/12 Pierre De Wilde <pierre...@gmail.com>

stephen mallette

unread,
Jun 12, 2011, 6:30:49 AM6/12/11
to Gremlin-users
Marko, I tried to quickly fix this, but it looks like the Row class is
protected so I can't access the iterator of Rows from the table.
Could you make that public please?

On Jun 12, 3:43 am, Pierre De Wilde <pierredewi...@gmail.com> wrote:
> Thinking further, table results should be serialized differently.
>
> Currently, Rexster returns:
> [
> "[s:marko, p:knows, o:vadas]",
> "[s:marko, p:created, o:lop]",
> "[s:marko, p:knows, o:josh]",
> "[s:peter, p:created, o:lop]",
> "[s:josh, p:created, o:ripple]",
> "[s:josh, p:created, o:lop]"
> ]
>
> I was expecting
> [
> {"s":"marko", "p":"knows", "o":"vadas"},
> {"s":"marko", "p":"created", "o":"lop"},
> {"s":"marko", "p":"knows", "o":"josh"},
> {"s":"peter", "p":"created", "o":"lop"},
> {"s":"josh", "p":"created", "o":"ripple"},
> {"s":"josh", "p":"created", "o":"lop"}
> ]
>
> Named steps combined with Table() are new stuff which leads to new
> clothes...
>
> Thanks,
> Pierre
>
> 2011/6/12 Pierre De Wilde <pierredewi...@gmail.com>
>
>
>
>
>
>
>
> > Hey,
>
> > The solution was in the excellent Troubleshooting wiki page<https://github.com/tinkerpop/gremlin/wiki/Troubleshooting>
> >  :
>
> > curl -X POST -d "script=m=[];g.v(1).out('knows').aggregate(m);m"
> >http://localhost:8182/tinkergraph/tp/gremlin
> > {"results":[],"success":true,"version":"0.4-SNAPSHOT","queryTime":3.97696}
>
> > curl -X POST -d "script=m=[];g.v(1).out('knows').aggregate(m)*>>-1*;m"
> >http://localhost:8182/tinkergraph/tp/gremlin
>
> > {"results":[{"_id":"2","_type":"vertex","name":"vadas","age":27},{"_id":"4" ,"_type":"vertex","name":"josh","age":32}],"success":true,"version":"0.4-SN APSHOT","queryTime":3.68896}

stephen mallette

unread,
Jun 12, 2011, 6:47:56 AM6/12/11
to Gremlin-users
Marko, one other point regarding the Table class: I didn't see a way
to get the column names. The addition of:

String getColumnName(int column)
List<String> columnNames getColumnNames()

would work.

Marko Rodriguez

unread,
Jun 12, 2011, 12:04:37 PM6/12/11
to gremli...@googlegroups.com
Hey Pierre,

In Gremlin, when you create an expression:

g.v(1).outE.inV.blah

You are creating an iterator.

gremlin> g.v(1).outE.inV.blah.class
==>class com.tinkerpop.gremlin.pipes.GremlinPipeline

When you hit <enter> in Gremlin terminal, the terminal says: "Ah this is an iterator, let me iterate it for you and toString() the results."

When you are using Gremlin in an IDE setting (Groovy code, etc.), you will need to manually iterate the iterator yourself. You can do this with:

g.v(1).outE.inV.blah >> -1

This will just while(itty.hasNext()) { itty.next() }

That is good for filling an intermediate data structure -- e.g. groupCount(m), aggregate(x), etc. However, if there is no sideEffect in the pipeline >>-1 will do nothing but waste clock cycles :).

Get it?

Marko.

Marko Rodriguez

unread,
Jun 12, 2011, 12:06:35 PM6/12/11
to gremli...@googlegroups.com
Hi,

Yea, there is no Table -> JSON mapping in Rexster right now. Table is a brand new class maybe 1.5 weeks old :). If someone wants to write the implementation and contribute it, that would be good.

See: ElementJSONHelper  in Rexster for inspiration.

See ya,
Marko.

Marko Rodriguez

unread,
Jun 12, 2011, 12:28:44 PM6/12/11
to gremli...@googlegroups.com
Hi,

Done.
1. Table.Row is a public class.
2. There is now Table.getColumnNames().

I did not add Table.getColumnName(int column) -- simply do: Table.getColumnNames().get(int).

Code/jars In GitHub and TinkerPop Maven2, respectively.

See ya,
Marko.

http://markorodriguez.com

stephen mallette

unread,
Jun 12, 2011, 1:08:12 PM6/12/11
to Gremlin-users
Just finished the changes in Rexster to support Table...works for both
the REST API and Dog House Gremlin Console. Table is pretty awesome!

Stephen

Pierre De Wilde

unread,
Jun 14, 2011, 3:27:29 AM6/14/11
to gremli...@googlegroups.com
Awesome. Was out less than 2 days and everything is implemented. 
Thanks guys,
Pierre

2011/6/12 stephen mallette <spmal...@gmail.com>
Just finished the changes in Rexster to support Table...works for both
Reply all
Reply to author
Forward
0 new messages