TinkerPop3 - Neo4j Cypher to Gremlin

769 views
Skip to first unread message

Stephen Mallette

unread,
Jul 31, 2014, 9:11:47 AM7/31/14
to gremli...@googlegroups.com
We've been talking a bit about Cypher internally and there was a realization that it might be cool to better improve support for the language with respect to Neo4j.  We've had support for a "query" method on Neo4jGraph that returned an Iterator, but that was about it.  An initial idea for better support was to allow  Cypher in the Gremlin Console.  That was an easy thing to do with the TP3 extension model, but I realized that what was equally easy was to allow Cypher to be a type of Traversal.  Sooooo....you can now do this:

gremlin> :use now com.tinkerpop neo4j-gremlin 3.0.0-SNAPSHOT
==>...
==>loaded: [com.tinkerpop, neo4j-gremlin, 3.0.0-SNAPSHOT]
gremlin> g = Neo4jGraph.open("/tmp/neo4j")
==>neo4jgraph[EmbeddedGraphDatabase [/tmp/neo4j]]
gremlin> g.loadKryo('data/tinkerpop-classic.gio')
==>null
gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a')
==>[a:v[0]]

the "cypher" step returns a Traversal which is basically an Iterator of Map<String,Object>.  It also detects instances of Node/Relationship and converts them automatically to Vertex/Edge instances, which means that I can then process my Cypher results with Gremlin:

gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a').map{it.get().a}
==>v[0]
gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a').map{it.get().a}.out
==>v[2]
==>v[1]
==>v[3]
gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a').map{it.get().a}.out.name
==>lop
==>vadas
==>josh

The limitation here is that "cypher" is a step that starts the Traversal from a Graph.  You can't start with Gremlin and go to Cypher and back again.  

Anyway, I think there can be some improvements here, but not bad for a hour's effort. Enjoy!

Stephen

Marko Rodriguez

unread,
Jul 31, 2014, 10:02:12 AM7/31/14
to gremli...@googlegroups.com
Hey Stephen,

Nice work. I super like how we talked about it < 24 hours ago and then you implemented it. :). 

I was working with Josh's MatchStep and added new features to select() which works perfectly with cypher(). Check this:

gremlin> g = Neo4jGraph.open("/tmp/neo4j")
==>neo4jgraph[EmbeddedGraphDatabase [/tmp/neo4j]]
gremlin> g.loadKryo('data/tinkerpop-classic.gio')
==>null
gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a')
==>[a:v[0]]
gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a').select('a')
==>v[0]
gremlin> g.cypher('MATCH (a {name:"marko"}) RETURN a').select('a').out('knows').name
==>vadas
==>josh

select() now operates on Map<String,Object> incomings (as well as named steps in a path). If you are only selecting one object out of the Map, you can simply "Gremlin flow" off that object. Now, see how it works with the new Gremlin3 match step.

gremlin> g.V.match('a',g.of().as('a').has('name','marko')).select('a').out('knows').name
==>vadas
==>josh

Thus, if you are using Neo4j, you can MATCH with Cypher or your can match() with Gremlin. 

Good stuff,
Marko.
--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/CAA-H43-%3DGRX3-%2BixeFXmdcVoP7kZpLhKXFCpOtAJ-EvCM--pOA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Peter Neubauer

unread,
Jul 31, 2014, 10:06:27 AM7/31/14
to gremlin-users
Stephen,
nice trick for the combination of declarative and imperative parts of one query. Might come in handy in Mapillary actually!

/peter


G:  neubauer.peter
S:  peter.neubauer
P:  +46 704 106975
L:   http://www.linkedin.com/in/neubauer
T:   @peterneubauer

Open Data    - @mapillary
Open Source - @neo4j
Open Future  - @coderdojo


Marko Rodriguez

unread,
Jul 31, 2014, 10:10:45 AM7/31/14
to gremli...@googlegroups.com
Hey Peter,

To your point of going from imperative, to declarative, to imperative, ad nasseum, we updated the MatchStep docs:


As Stephen mentions, you can only start a traversal with cypher(), you can't go back into it -- is that a hard limitation Stephen or just the nature of the current implementation? Be nice to have …cypher()…cypher().. like we do with match().

Take care,
Marko.

Stephen Mallette

unread,
Jul 31, 2014, 11:04:47 AM7/31/14
to gremli...@googlegroups.com

Need to think on it some more (learn more about cypher perhaps)...might be possible to drop in and out seamlessly.

Marko Rodriguez

unread,
Jul 31, 2014, 3:00:14 PM7/31/14
to gremli...@googlegroups.com

Stephen Mallette

unread,
Aug 15, 2014, 5:18:19 PM8/15/14
to gremli...@googlegroups.com
With some help from Marko, we cleaned up the code for the cypher() step.  Prior to this change you could only start a traversal with Cypher and then switch to Gremlin.  Now you can jump between either one feeding the results of one into another.  Here's an example:

gremlin> g.cypher("MATCH (n{name:'marko'})-[:knows]->(m) RETURN m").select('m').id.fold.cypher("MATCH (m)-[:created]->(n) WHERE id(m) in {start} RETURN n").select("n").name
==>lop
==>ripple

We start the traversal with Cypher which returns a Neo4j specific implementation of the Traversal interface called Neo4jTraversal.  This allows us to add the cypher() step to the methods available, providing a way to extend the Gremlin language to include vendor specific features.  Using select() we grab the value of "m" and take the ids from those vertices bound to it.  We gather those ids with "fold" and feed them into the second cypher() step.  The value that enters the cypher() step is bound to a variable called "start" which is used within the second cypher query.  We then drop back into Gremlin to select "n" and pop off the name for each.  So in a round-about way we've used cypher to grab all the people that marko "knows" and then used those results to feed the people he knows into a second cypher query to determine what things they "created".  

Obviously, this example is a bit contrived, however it does introduce some important bits.  First, as alluded to in previous posts, we show how we can interchangeably hook together imperative and declarative querying in a fairly seamless way.  Second, we show that vendors can take features that are very specific or proprietary to their products and expose them as extensions to the Gremlin language.  


Enjoy!

Stephen

On Thursday, July 31, 2014 3:00:14 PM UTC-4, Marko A. Rodriguez wrote:
Hi,

I updated the TinkerPop3 to discuss cypher().


Enjoy!,
Marko.
On Jul 31, 2014, at 9:04 AM, Stephen Mallette <> wrote:

Need to think on it some more (learn more about cypher perhaps)...might be possible to drop in and out seamlessly.

On Jul 31, 2014 10:10 AM, "Marko Rodriguez" <> wrote:
Hey Peter,

To your point of going from imperative, to declarative, to imperative, ad nasseum, we updated the MatchStep docs:


As Stephen mentions, you can only start a traversal with cypher(), you can't go back into it -- is that a hard limitation Stephen or just the nature of the current implementation? Be nice to have …cypher()…cypher().. like we do with match().

Take care,
Marko.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.

Marko Rodriguez

unread,
Aug 15, 2014, 6:01:29 PM8/15/14
to gremli...@googlegroups.com
Hey,

With some talking with Josh on IM, Josh said:

"You could put cypher() inside of match()."

gremlin> g.V.match('a',
            g.of().as('a').id().cypher("MATCH (m)-[:writtenBy]->(n) WHERE n.name = 'Garcia' AND id(m) = {start} RETURN m").select('m').as('b'),
            g.of().as('b').out('sungBy').has('name','Garcia').as('c')).select('b').name
==>CRYPTICAL ENVELOPMENT
==>CREAM PUFF WAR

You can have declarative Cypher in your declarative Gremlin. Or, if you prefer Xhibit's understanding of the situation: 

Marko.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/190d4db0-797c-4481-8b29-c2e9cedc5327%40googlegroups.com.

pieter

unread,
Aug 16, 2014, 2:48:42 AM8/16/14
to gremli...@googlegroups.com
Say, would a Cypher to Gremlin transformation be viable?

Having cypher available to any tp db would be pretty neat.

Cheers
Pieter
--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.

Stephen Mallette

unread,
Aug 16, 2014, 6:08:06 AM8/16/14
to gremli...@googlegroups.com
It's interesting and I can't say it didn't pop into my mind here and there, but I don't plan to figure out how to do that one any time soon. ;)


Yehonathan Sharvit

unread,
Jan 3, 2018, 7:03:51 AM1/3/18
to Gremlin-users
More than 3 years have passed.
Does anyone know if it is possible to make a Cypher to Gremlin transformation.

It would be extremely cool to be able to run Cypher on any TinkerPop db.

Stephen Mallette

unread,
Jan 3, 2018, 7:11:16 AM1/3/18
to Gremlin-users
Back october at GraphConnect NYC Neo4j announced that they had built such a tool, but it hadn't been formally released yet:


I've not seen anything since.

To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/d0afb3a0-8dc8-4a49-aa24-300c64b66c20%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages