DEV Community

Cover image for The Cypher Query Language - Best Practices
g-despot
g-despot

Posted on • Originally published at memgraph.com

The Cypher Query Language - Best Practices

Cypher, like any other programming or query language, has a defined set of rules for writing readable and well-designed constructs. By following this guide, you will learn how to format and organize Cypher queries so that naming conventions and formatting are consistent and understandable to everyone.

Don't worry if you are still new to graph databases or Cypher. Most example queries are very easy to understand just from context and don't require any advanced knowledge.

Data model styling

Defining your data model is one of the most important steps when it comes to styling. Because these constructs will be used throughout your whole project, it would be very wise to think about the naming convention and formatting rules before committing to specific ones.
Sticking to shared best practices is by far the best choice because it enables other users to easily read and understand your data model and queries. In this section, you'll find recommendations on how to name nodes and relationships, their properties, variables... and so on.

Nodes

When it comes to nodes, the most important factor is styling labels. Node labels should be defined in CamelCase, which means that the first letter of each word begins with a capital letter. Because Cypher is case-sensitive, it is important to uphold this style throughout every query you write.

(:Country)
(:City)
(:CapitalCity)
Enter fullscreen mode Exit fullscreen mode

Relationships

Relationship types are styled upper-case and use the underscore character _ to separate multiple words.

[:LIVES_IN]
(:BORDERS_WITH)
Enter fullscreen mode Exit fullscreen mode

Properties, variables, parameters, aliases, and functions

Property keys, variables, parameters, aliases, and functions should have a camelCase style where the first letter of the word is lower-case, and the first letter of each following word is a capital letter. All of these constructs are case-sensitive, so capitalization must match either what is in the database (properties), what is already defined in the query (variables, parameters, aliases), or Cypher definitions (functions).

dateOfBirth // Property key
largestCountry // Variable
size() // Function
countryOne // Alias
Enter fullscreen mode Exit fullscreen mode

Clauses

Clauses should be defined with capital letters, even if they consist of two or more words. Each new clause should be placed at the beginning of a new line to ensure complete readability. While clauses are not case sensitive, we strongly discourage you from using any other style to avoid confusion.

MATCH (c:Country)
WHERE c.name = 'UK'
RETURN c;

WITH "2021-01-01" as currentDate
MATCH (p:Person)
WHERE p.birthdate > currentDate
RETURN p.name;
Enter fullscreen mode Exit fullscreen mode

Keywords

Aside from clauses, there is a number of keywords that should be in upper case even though they are not case sensitive. These include: DISTINCT, IN, STARTS WITH, CONTAINS, NOT, AND, OR and AS.

MATCH (c:Country)
WHERE c.name CONTAINS 'United' AND c.population > 9000000
RETURN c AS Country;
Enter fullscreen mode Exit fullscreen mode

Indentations and line breaks

Sometimes it's helpful to separate new clauses with an indent. Even though they are in a new line, subqueries should be indented to ensure readability.
If there are multiple subqueries, they can be further grouped by using curly brackets.

//Indent 2 spaces on lines with ON CREATE or ON MATCH subqueries
MATCH (p:Person {name: 'Helga'})
MERGE (c:Country {name: 'UK'})
MERGE (p)-[l:LIVES_IN]->(c)
  ON CREATE SET l.movedIn = date({year: 2020})
  ON MATCH SET l.modified = date()
RETURN p, l, c;

//Indent 2 spaces with braces for subqueries
MATCH (p:Person)
WHERE EXISTS {
  MATCH (p)-->(c:Country)
  WHERE c.name = 'UK'
}
RETURN p;
Enter fullscreen mode Exit fullscreen mode

An exception to this rule would be a one-line subquery where you don't need to use a new line or an indent.

MATCH (p:Person)
WHERE EXISTS { MATCH (p)-->(c:Country {name: 'UK'}) }
RETURN p
Enter fullscreen mode Exit fullscreen mode

Metacharacters

Quotes

When it comes to quotes, a simple rule is to use whichever provides the fewest escaped characters in the string. If escaped characters are not needed or their number is the same for both single and double quotes, then single quotes should be favored.

// Bad syntax
RETURN 'Memgraph\'s mission is: ', "A very famous quote is: \"Astra inclinant, sed non obligant.\""

// Recommended syntax
RETURN "Memgraph's mission is: ", 'A very famous quote is: "Astra inclinant, sed non obligant."'
Enter fullscreen mode Exit fullscreen mode

Semicolons

In most cases, a semicolon at the end of a Cypher query is unnecessary. The exception is when you have a script or a block with multiple separate Cypher queries that should be executed independently.

MATCH (c:Country {name: 'UK'})
RETURN c;

MATCH (c:Country {name: 'Germany'})
RETURN c;
Enter fullscreen mode Exit fullscreen mode

Null and Boolean Values

Boolean literals and null values should always be lower case.

// Bad syntax
MATCH (c:Country)
WHERE c.island = NULL
  SET islandCountry = True
RETURN c

// Recommended syntax
MATCH (c:Country)
WHERE c.island = null
  SET islandCountry = true
RETURN c
Enter fullscreen mode Exit fullscreen mode

Pattern styling

  • When you have a pattern that is too long for one line, the recommended practice is to break after an arrow, not before it.
// Bad syntax
MATCH (:Country)-->(:Person)-->(:Person)
      <--(c:Country)
RETURN c.name

// Recommended syntax
MATCH (:Country)-->(:Person)-->(:Person)<--
      (c:Country)
RETURN c.name
Enter fullscreen mode Exit fullscreen mode
  • If you don't plan on using a variable in the query, it's better to use anonymous nodes and relationships instead.
// Bad syntax
MATCH (c:Country {name: 'UK'})<-[l:LIVES_IN]-(p:Person)
RETURN p.name

// Recommended syntax
MATCH (:Country {name: 'UK'})<-[:LIVES_IN]-(p:Person)
RETURN p.name
Enter fullscreen mode Exit fullscreen mode
  • Nodes with assigned variables should come before anonymous nodes and relationships if possible. The same goes for nodes that are starting points or the central focus of the query.
// Bad syntax
MATCH (:Person)-[:LIVES_IN]->(c:Country {name: 'UK'})
RETURN c

// Recommended syntax
MATCH (c:Country {name: 'UK'})<-[:LIVES_IN]-(:Person)
RETURN c
Enter fullscreen mode Exit fullscreen mode
  • Patterns should be ordered so that left-to-right relationships (arrows) come at the beginning of the query.
// Bad syntax
MATCH (c:Country)<-[:BORDERS_WITH]-(:Country)<-[:LIVES_IN]-(:Person)
RETURN c

// Recommended syntax
MATCH (:Person)-[:LIVES_IN]->(:Country)-[:BORDERS_WITH]->(c:Country)
RETURN c
Enter fullscreen mode Exit fullscreen mode

Spacing

Spacing has a big impact on the readability of queries. Some of the recommended practices when it comes to spacing are:

  • There should be one space between property predicates and label/type predicates.
// Bad syntax
MATCH (:Country   {name: 'UK'})<-[:LIVES_IN{since: 2010}]-(p:Person)
RETURN p.name

// Recommended syntax
MATCH (:Country {name: 'UK'})<-[:LIVES_IN {since: 2010}]-(p:Person)
RETURN p.name
Enter fullscreen mode Exit fullscreen mode
  • There should be no spaces in label predicates.
// Bad syntax
MATCH (c: Country:  City)
RETURN c.name

// Recommended syntax
MATCH (c:Country:City)
RETURN c.name
Enter fullscreen mode Exit fullscreen mode
  • There should be no spaces in patterns.
// Bad syntax
MATCH (c:Country) --> (:City) 
RETURN c.name

// Recommended syntax
MATCH (c:Country)-->(:City) 
RETURN c.name
Enter fullscreen mode Exit fullscreen mode
  • There should be one space on both sides of an operator.
// Bad syntax
MATCH (c:Country)
WHERE population>100000
RETURN c.name

// Recommended syntax
MATCH (c:Country)
WHERE population > 100000
RETURN c.name
Enter fullscreen mode Exit fullscreen mode
  • There should be one space between elements in a list (after each comma).
// Bad syntax
WITH ['UK','US','Germany'] as list
MATCH (c:Country)
WHERE c.name IN list
RETURN c.name

// Recommended syntax
WITH ['UK', 'US', 'Germany'] as list
MATCH (c:Country)
WHERE c.name IN list
RETURN c.name
Enter fullscreen mode Exit fullscreen mode
  • Function call parentheses should only have one space after each comma.
// Bad syntax
RETURN split( 'A', 'B' , 'C' )

// Recommended syntax
RETURN split('A', 'B', 'C')
Enter fullscreen mode Exit fullscreen mode
  • Map literals should only have one space after each comma and one space separating a colon and a value.
// Bad syntax
WITH { name :'UK' ,population  :  70000000 } AS country
RETURN country

// Recommended syntax
WITH {name: 'UK', population: 70000000} AS country
RETURN country
Enter fullscreen mode Exit fullscreen mode

Conclusion

Having a well-defined style for writing queries is a technical must-have. It makes it easier and faster to understand queries that other people have written while also enabling everyone to contribute in a meaningful way without having to worry about the format. Whenever you are not sure about a naming convention or the structure of your query, just take a quick look at this guide.

If you have trouble writing a specific query or would just like to learn about the concepts that are available in Cypher, go through our Cypher Cheat Sheet.

Top comments (0)