CREATE always inserts; MERGE upserts
So far you only read the Movie graph. Real applications also write. Cypher’s primary construction clause
is CREATE, which always constructs new nodes and/or relationships.
That is perfect when you know the data is new, or when duplicates are impossible by design. It is
dangerous when users click “save” twice or imports re-run: CREATE will happily insert second Tom Hanks
nodes unless constraints and MERGE stop them.
MERGE is Cypher’s idempotent upsert. It tries to match a pattern; if a
match exists, it binds it; if not, it creates it. For production-grade MERGE on a single node, define a
uniqueness constraint on the property key you merge on (for example Person.name or a business id). Without
a constraint, concurrent MERGEs can still race—constraints make the uniqueness guarantee real.
ON CREATE and ON MATCH attach
SET-style actions depending on which branch MERGE took. Typical pattern: set
createdAt only on create; increment a counter or set
updatedAt on match. This keeps timestamps honest without overwriting
creation metadata every time.
When to prefer CREATE: bulk loading known-unique rows inside a controlled import, or creating relationships between already-resolved nodes where you accept multiples (for example multiple REVIEWED edges with different ratings). When to prefer MERGE: API upserts, re-runnable migrations, and any “ensure this entity exists” workflow. MERGE of multi-node patterns can create partial pieces carefully—read the manual when merging paths, not just single nodes.
MERGE (p:Person {name: "Ada Lovelace"})
ON CREATE SET p.born = 1815, p.createdAt = timestamp()
ON MATCH SET p.updatedAt = timestamp()
RETURN p.name, p.born, p.createdAt, p.updatedAt