Chapter 15. Cypher Query Language

Table of Contents

15.1. Operators
15.2. Expressions
15.3. Parameters
15.4. Identifiers
15.5. Comments
15.6. Updating the graph
15.7. Transactions
15.8. Patterns
15.9. Start
15.10. Match
15.11. Where
15.12. Return
15.13. Aggregation
15.14. Order by
15.15. Limit
15.16. Skip
15.17. With
15.18. Create
15.19. Create Unique
15.20. Set
15.21. Delete
15.22. Foreach
15.23. Functions
15.24. Compatibility
15.25. From SQL to Cypher

Cypher is a declarative graph query language that allows for expressive and efficient querying and updating of the graph store without having to write traversals through the graph structure in code. Cypher is still growing and maturing, and that means that there probably will be breaking syntax changes. It also means that it has not undergone the same rigorous performance testing as other Neo4j components.

Cypher is designed to be a humane query language, suitable for both developers and (importantly, we think) operations professionals who want to make ad-hoc queries on the database. Our guiding goal is to make the simple things simple, and the complex things possible. Its constructs are based on English prose and neat iconography, which helps to make it (somewhat) self-explanatory.

Cypher is inspired by a number of different approaches and builds upon established practices for expressive querying. Most of the keywords like WHERE and ORDER BY are inspired by SQL. Pattern matching borrows expression approaches from SPARQL.

Being a declarative language, Cypher focuses on the clarity of expressing what to retrieve from a graph, not how to do it, in contrast to imperative languages like Java, and scripting languages like Gremlin (supported via the Section 18.18, “Gremlin Plugin”) and the JRuby Neo4j bindings. This makes the concern of how to optimize queries an implementation detail not exposed to the user.

The query language is comprised of several distinct clauses.

Let’s see three of them in action.

Imagine an example graph like the following one:

Figure 15.1. Example Graph


For example, here is a query which finds a user called John in an index and then traverses the graph looking for friends of Johns friends (though not his direct friends) before returning both John and any friends-of-friends that are found.

START john=node:node_auto_index(name = 'John')
MATCH john-[:friend]->()-[:friend]->fof
RETURN john, fof

Resulting in:

johnfof
2 rows
3 ms

Node[4]{name:"John"}

Node[2]{name:"Maria"}

Node[4]{name:"John"}

Node[3]{name:"Steve"}

Next up we will add filtering to set more parts in motion:

In this next example, we take a list of users (by node ID) and traverse the graph looking for those other users that have an outgoing friend relationship, returning only those followed users who have a name property starting with S.

START user=node(5,4,1,2,3)
MATCH user-[:friend]->follower
WHERE follower.name =~ 'S.*'
RETURN user, follower.name

Resulting in

userfollower.name
2 rows
1 ms

Node[5]{name:"Joe"}

"Steve"

Node[4]{name:"John"}

"Sara"

To use Cypher from Java, see Section 4.10, “Execute Cypher Queries from Java”. For more Cypher examples, see Chapter 7, Data Modeling Examples as well.