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