Question

I have been trying to come across a query builder for Neo4j's query language Cypher, ideally using a fluent API. I did not find much, and decided to invest some time on building one myself.

The result so far is a fluent API query builder for the Cypher 1.9 spec.

I wanted to use StackOverflow to kick off a discussion and see what the thoughts are, before I release the code.

Here is a demo query that you would want to send off to Neo4j using Cypher.

Show me all people who John knows who know software engineers at Google (Google company code assumed to be 12345). The relationship strength between John and the people who connect him to Google employees should be at least 3 (assuming a range from 1-5). Return all of John's connections and the people they know at Google, including the relationships between those people. Sort the results by name of John's connections in ascending order and then by relationship strength in descending order.

Using Fluent-Cypher:

Cypher
    .on(Node.named("john").with(Index.named("PERSON_NAMES").match(Key.named("name").is("John"))))
    .on(Node.named("google").with(Id.is(12345)))

    .match(Connection.named("rel1").andType("KNOWS").between("john").and("middle"))
    .match(Connection.named("rel2").andType("KNOWS").between("middle").and("googleEmployee"))
    .match(Connection.withType("WORKS_AT").from("googleEmployee").to("google"))

    .where(Are.allOfTheseTrue(Column.named("rel1.STRENGTH").isGreaterThanOrEqualTo(3)
            .and(Column.named("googleEmployee.TITLE").isEqualTo("Software Engineer"))))

    .returns(Columns.named("rel1", "middle", "rel2", "googleEmployee"))
    .orderBy(Asc.column("middle.NAME"), Desc.column("rel1.STRENGTH"))

which yields the following query:

START john=node:PERSON_NAMES(name='John'),google=node(12345) MATCH john-[rel1:KNOWS]-middle,middle-[rel2:KNOWS]-googleEmployee,googleEmployee-[:WORKS_AT]->google WHERE ((rel1.STRENGTH >= '3' AND googleEmployee.TITLE = 'Software Engineer')) RETURN rel1,middle,rel2,googleEmployee ORDER BY middle.NAME ASC,rel1.STRENGTH DESC

No correct solution

OTHER TIPS

I agree that you should build this with an eye towards Cypher 2.0. As of 2.0, it's very important that WHERE clauses are matched up with the correct START, (OPTIONAL) MATCH, and WITH clauses making the design of a fluent API a bit more challenging.

I like your first example where you just use the text to describe the query. The second option, to tell you the truth, doesn't look so much easier to me than constructing the Cypher query itself. The language is quite easy to use and is well documented. Adding another layer of abstraction would only increase complexity. However, if you find a way of translating this natural language request into a Cypher request, that'd be cool :)

Also, why not start working directly with Cypher 2.0?

Finally, check out this here: http://github.com/noduslabs/infranodus – I'm working on a similar problem but for adding the nodes into the database, not querying them. I chose to use #hashtags to make it easier for people to understand how their queries should be structured (as we already use them). So in your case it could become something like

@show-all #people who #John :knows who :know #software-engineers :at #Google. 

@relationship-strength between #John and the #people who are @linked to #Google #software-engineers should be at least @3 

@return @all of #John's @connections and the #people they :know at #Google, including the @relationships-between those #people. 

@sort the @results @by-name of #John's @connections in @ascending order and then by @relationship-strength in @descending order.

(let's say the #hashtags refer to nodes, the @at refers to actions on them)

If you could pull something like this off, I think that'd be a much better and more useful simplification of the already easy-to-use Cypher.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top