Neo4j Cypher Query Builder
Asked Answered
O

2

10

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
Osteopathy answered 16/2, 2014 at 18:48 Comment(6)
What is the question here?Within
It is more of an open ended question targeted at receiving feedback and suggestions on a fluent cypher API.Osteopathy
Have you seen (for java) github.com/neo4j/cypher-dslForfar
I like your DSL what about just putting it on github / maven / npm and blogging about it? That would be the best way of gathering feedback. The Neo4j google group might also be better suited for these kinds of discussions.Forfar
is dsl compatible with latest version of Neo4JEsra
We developed a builder, hope it's useful for you github.com/go1com/neo4j_builderCarlacarlee
A
1

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.

Amary answered 17/2, 2014 at 18:25 Comment(0)
N
0

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.

Nectarine answered 16/2, 2014 at 21:24 Comment(1)
Hey deemeetree Thanks for your reply. I agree, Cypher is already easy enough to understand. The actual benefit of the Fluent API lies more in the advantage that it reads like a text and it's easy to understand what we're trying to do, but more importantly the API only allows you to put together well defined formats that yield a syntactically correct query. Fiddling around with String operations to put together a Cypher query is pretty pretty error prone and no one knows if what's in the String is correct. Here, the compiler will complain if you did something wrong.Osteopathy

© 2022 - 2024 — McMap. All rights reserved.