Skip to main content

Command Palette

Search for a command to run...

Cypher Query Explained with Examples: A Beginner’s Guide

Published
5 min read
Cypher Query Explained with Examples: A Beginner’s Guide
R

🛠️ Building modern web apps with React, Node.js, MongoDB & Express

Cypher is the declarative query language (declarative means you only describe what result you want, not how to get it) for graph databases like Neo4j. A Cypher query describes patterns of nodes and relationships you want to create, find, update or delete — similar to how SQL works for tables, but focused on graph structures (nodes, relationships, properties).

Below is a friendly, step-by-step blog-style guide using your examples and several extra small examples so a beginner can follow along.


Anatomy / syntax quick primer

  • Node: (variable:Label {property: value, ...})
    Example: (p:User {name:'Ritik', bday:'19 feb'})

  • Relationship: -[variable:TYPE]-> (directional) or -[r]- (undirected)
    Use ALL CAPS or snake_case for types: :STUDIED_AT. If you really want spaces or special characters you can escape with backticks (rare): -[:`Studied at`]->.

  • Match pattern: MATCH (a)-[r:TYPE]->(b) finds existing patterns.

  • Create: CREATE (...) makes nodes/relationships.

  • Merge: MERGE (...) find-or-create (like an upsert).

  • Return: RETURN x, x.name selects what to show.

  • Where: WHERE filters results.

  • Set/update: SET node.prop = value.

  • Delete: DELETE node (must delete relationships first if they exist).


Step-by-step examples (with explanations)

1) Create a simple node (your example)

CREATE (p:User {name: 'Ritik', bday: '19 feb'})

What it does

  • Creates a node with label User.

  • The node is assigned to variable p for the scope of this query.

  • Two properties are set: name and bday.

  • If you run this again you'll create another node (duplicate) unless you use MERGE or constraints.

Tip: If you want the birthday as a real date type (not just a string), use:

CREATE (p:User {name: 'Ritik', bday: date('2000-02-19')})

(Replace 2000-02-19 with the actual ISO date.)


2) Search / find the node (your example)

MATCH (x:User {name: 'Ritik'})
RETURN x

What it does

  • MATCH finds nodes with label User and name = 'Ritik'.

  • RETURN x shows the matched node(s) (in Neo4j Browser you’ll see the node and its properties).

Variation — return specific property

MATCH (x:User {name: 'Ritik'})
RETURN x.name, x.bday

3) Create another node — an organization (your example)

CREATE (p:Org {name: 'Arka Jain University'})

What it does

  • Makes an Org node with the name property.

4) Match two existing nodes and create a relationship between them (your example, corrected for relationship type)

MATCH (x:User {name: 'Ritik'})
MATCH (y:Org {name: 'Arka Jain University'})
CREATE (x)-[:STUDIED_AT]->(y)

What it does

  • MATCH finds the User and the Org.

  • CREATE adds a directed relationship from the user to the org.

  • The relationship type is STUDIED_AT (recommended style). If you prefer a human phrase with spaces, you can escape it: CREATE (x)-[:`Studied at`]->(y) — but escaped types are less common.

Output

  • You’ll now have a graph: (Ritik)-[:STUDIED_AT]->(Arka Jain University).

5) Find all nodes in the database (your snippet slightly fixed)

MATCH (n)
RETURN n

What it does

  • MATCH (n) with no label/predicate matches every node.

  • RETURN n lists them. Useful for quick inspection on small datasets; avoid on very large graphs without LIMIT.


6) Find all relationships of a specific node (your example)

// finds all outgoing relationships from Ritik to any node
MATCH (u:User {name: 'Ritik'})-[r]->(y)
RETURN u, r, y

What it does

  • Pattern (u)-[r]->(y) matches u with any outgoing relationship r to node y.

  • Returns the user, the relationship(s), and the target node(s).

  • To include incoming relationships too, use MATCH (u)-[r]-(y) (no arrow direction).


MATCH (n)-[r]->(o:Org {name: 'Arka Jain University'})
RETURN n, o, r

What it does

  • Finds any node n that has an outgoing relationship r to the given Org.

  • Useful when you want to see who or what relates to that organization.


8) Use MERGE to avoid duplicates (upsert)

MERGE (p:User {name: 'Ritik'})
MERGE (o:Org {name: 'Arka Jain University'})
MERGE (p)-[:STUDIED_AT]->(o)
RETURN p, o

What it does

  • MERGE finds existing nodes with matching properties or creates them if not present.

  • Good when you want one canonical node per unique property (e.g., unique user name).

Important: MERGE on a map matches all properties in the map. If you want to merge just by name but add other props only if created, use MERGE on the identity property and then ON CREATE SET / ON MATCH SET.


9) Update a property

MATCH (p:User {name: 'Ritik'})
SET p.bday = date('2001-02-19')
RETURN p

What it does

  • Finds Ritik and changes bday property to a proper date type.

10) Delete a relationship and/or node

// delete the relationship first
MATCH (p:User {name: 'Ritik'})-[r:STUDIED_AT]->(o:Org {name: 'Arka Jain University'})
DELETE r;

// then optionally delete the node (if it has no other relationships)
MATCH (p:User {name: 'Ritik'})
DELETE p;

What it does

  • Neo4j requires relationships to be deleted before deleting a connected node (unless you use DETACH DELETE).

  • You can also DETACH DELETE p to remove a node and all its relationships in one go.


11) Aggregation & counting

MATCH (u:User)-[:STUDIED_AT]->(o:Org {name: 'Arka Jain University'})
RETURN count(u) AS studentsCount

What it does

  • Counts how many users have a STUDIED_AT link to that org.

12) Optional match (include nodes even if they don’t have a certain relation)

MATCH (u:User)
OPTIONAL MATCH (u)-[r:STUDIED_AT]->(o:Org)
RETURN u.name, o.name

What it does

  • For every user, returns the org they studied at if one exists; returns null for o.name if not.

Putting it together — a short recipe (create → link → query)

  1. Create users/orgs:
CREATE (a:User {name:'Ritik', bday:'19 feb'}),
       (b:User {name:'Anya', bday:'02 mar'}),
       (o:Org {name:'Arka Jain University'});
  1. Link Ritik to the org:
MATCH (a:User {name:'Ritik'}), (o:Org {name:'Arka Jain University'})
CREATE (a)-[:STUDIED_AT]->(o);
  1. List Ritik’s connected nodes:
MATCH (a:User {name:'Ritik'})-[r]-(x)
RETURN a, r, x;
  1. Count students for that org:
MATCH (u:User)-[:STUDIED_AT]->(o:Org {name:'Arka Jain University'})
RETURN COUNT(u) AS students;

Quick cheat-sheet (common clauses & symbols)

  • () node, [] relationship

  • :Label node label, :TYPE relationship type

  • CREATE create nodes/relationships

  • MATCH pattern match existing data

  • WHERE filter results (e.g. WHERE u.age > 20)

  • RETURN select output

  • MERGE find or create

  • SET update properties

  • DELETE remove nodes/relationships; DETACH DELETE removes node + relationships

  • OPTIONAL MATCH optional pattern (like LEFT JOIN)

  • WITH pass results between query parts (useful for aggregation + subsequent filters)

  • EXPLAIN / PROFILE see execution plan