Very cool! Btw, just added parameters to the Cypher REST Plugin too, since Andres pushed them into the core parser. http://docs.neo4j.org/chunked/snapshot/cypher-plugin.html#rest-api-send-queries-with-parameters which will mean the mode of submission is the same for Gremlin and Cypher.
Cheers, /peter neubauer GTalk: neubauer.peter Skype peter.neubauer Phone +46 704 106975 LinkedIn http://www.linkedin.com/in/neubauer Twitter http://twitter.com/peterneubauer http://www.neo4j.org - Your high performance graph database. http://startupbootcamp.org/ - Öresund - Innovation happens HERE. http://www.thoughtmade.com - Scandinavia's coolest Bring-a-Thing party. On Tue, Oct 4, 2011 at 7:25 AM, Tatham Oddie <[email protected]> wrote: > Hi Marko, > > That's exactly what we're doing. > > In C# we translate the expression trees from the predicates into Groovy > lambdas we can send over the wire. > > The fluent methods all just return enumerables along the way so it's deferred > execution at the end. > > We use generics to pass the right type to the predicates: > > IGremlinNodeEnumerable<TNode> Out<TNode>(string relationshipType, > Func<TNode, bool> predicate) {...} > > This allows usage like this, where 'p' is of type Program and you get Visual > Studio IntelliSense when you type p.Name: > > var programs = graphClient.RootNode.Out<Program>(HasProgram.TypeKey, p => > p.Name == "foo"); > > During the translation, all of the dynamic parts are quietly whisked away > into Gremlin parameters. The last example goes over the wire like this: > > { > 'script': 'g.v(p0).outE[[label:p1]].inV{it[p2].equalsIgnoreCase(p3)}', > 'params': { > 'p0': 0, > 'p1': 'HAS_PROGRAM', > 'p2': 'Name', > 'p3': 'foo' > } > } > > Using the parameters a) saves Gremlin from having to parse the query again > and b) saves us from having to worry about escaping strings into Java format > (we just serialize to JSON instead). > > To make debugging easier, both GremlinNodeEnumerator and > GremlinRelationshipEnumerator expose a DebugQueryText property. This returns > an artificially expanded version of the query so that you can copy one string > from the watch window straight into the neo4j web console for query > debugging. (As opposed to the version of the query text with the param > markers.) This is just a dumb replacement of pN with '{value}' and thus not > guaranteed to be accurate, but it still helps. > > You'll also notice in this translation that p.Name=="foo" was translated to > {it[p2].equalsIgnoreCase(p3)}. By default, we perform case insensitive > comparisons on strings as that was more consistent with MS SQL (the data > source most .NET devs use as a baseline). Of course, there's an overload that > allows you to specify the case comparison mode. Our currently approach may or > may not be right for other projects, but time will tell. > > The only two places we really deviate from Gremlin are: > > - Instead of .count() we have .GremlinCount(). .NET already has a built in > Count method that spins through the enumerator and counts the number of > entries returned. Ultimately we will intercept this, but for now the simplest > option was just to use a different name that didn't clash. > > - Because we're in a statically typed language, we had to implement BackE and > BackV so that we could return a IGremlinRelationshipEnumerable or > IGremlinNodeEnumerable<TNode> respectively. We figured this would still be a > fairly obvious signature. > > There's definitely some expression tree gymnastics and generics craziness in > there to make all that happen, but it has been fun. :) > > > -- Tatham > > > -----Original Message----- > From: [email protected] [mailto:[email protected]] On > Behalf Of Marko Rodriguez > Sent: Tuesday, 4 October 2011 3:21 AM > To: Neo4j user discussions > Subject: Re: [Neo4j] C# REST binding / wrapper > > Hey Romiko, > >> http://romikoderbynew.com/2011/07/30/neo4jclient-primer/ > > That is really cool how you build a Gremlin expression in C# using a fluent > pattern and then, I suspect, transform it to the appropriate Gremlin string > representation for transport over the wire to Neo4j REST Server. Is that what > you are doing? If so, that is a neat way to build language bindings that are > not just server.eval("some.big.fat.string.all.old.skool.rdbms.style")? > > Finally, in a similar note, TinkerPop is generalizing Gremlin away from a > particular language implementation. We want to provide the "Gremlin-style" to > any JVM language, not just Groovy. We plan to have Gremlin_scala out in the > next release... E.g.: > > gremlin-groovy: g.v(1).out('knows').name.filter{it == 'josh'} > gremlin-scala: g.v(1).out("knows").property("name").filter{_ == "josh"} > > There is an strong conceptual overlap to how you are doing your C# binding > and how Gremlin is becoming JVM language agnostic.... makes me think. :/ > > Anywho, I like the work you did. Thank you for sharing, Marko. > > http://markorodriguez.com > _______________________________________________ > Neo4j mailing list > [email protected] > https://lists.neo4j.org/mailman/listinfo/user > _______________________________________________ > Neo4j mailing list > [email protected] > https://lists.neo4j.org/mailman/listinfo/user > _______________________________________________ Neo4j mailing list [email protected] https://lists.neo4j.org/mailman/listinfo/user

