返回 Skill 列表
extension
分类: 开发与工程无需 API Key

lang-cypher-dev

基础的Cypher(Neo4j)模式,涵盖了图模式匹配、MATCH/CREATE/MERGE/DELETE操作、关系、路径模式、聚合、过滤以及常见的图形查询模式。在编写Cypher查询、建模图数据或需要关于图数据库操作指导时使用。这是Cypher开发的入门点。

person作者: jakexiaohubgithub

Cypher Fundamentals

Foundational Cypher patterns and core query language features for Neo4j graph databases. This skill serves as both a reference for common patterns and an index to specialized graph database skills.

Overview

┌─────────────────────────────────────────────────────────────────┐
│                   Cypher Skill Hierarchy                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│                 ┌─────────────────────┐                         │
│                 │  lang-cypher-dev    │ ◄── You are here        │
│                 │    (foundation)     │                         │
│                 └──────────┬──────────┘                         │
│                            │                                    │
│            ┌───────────────┴───────────────┐                    │
│            │                               │                    │
│            ▼                               ▼                    │
│   ┌─────────────────┐            ┌─────────────────┐           │
│   │    patterns     │            │     admin       │           │
│   │      -dev       │            │      -ops       │           │
│   └─────────────────┘            └─────────────────┘           │
│         (future)                       (future)                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

This skill covers:

  • Node and relationship pattern syntax
  • MATCH, CREATE, MERGE, DELETE operations
  • WHERE clauses and filtering
  • Path patterns and traversals
  • Aggregation functions
  • Indexes and constraints
  • Common graph query patterns
  • Query optimization basics

This skill does NOT cover (see specialized skills):

  • Advanced graph algorithms → lang-cypher-patterns-dev (future)
  • Performance tuning and profiling → lang-cypher-patterns-dev (future)
  • Database administration → lang-cypher-admin-ops (future)
  • APOC procedures → lang-cypher-patterns-dev (future)

Quick Reference

| Task | Syntax | |------|--------| | Match node | MATCH (n:Label) | | Match relationship | MATCH (a)-[r:TYPE]->(b) | | Create node | CREATE (n:Label {prop: value}) | | Create relationship | CREATE (a)-[r:TYPE]->(b) | | Merge (upsert) | MERGE (n:Label {id: 1}) | | Delete node | MATCH (n) DELETE n | | Detach delete | MATCH (n) DETACH DELETE n | | Filter | WHERE n.age > 18 | | Return | RETURN n.name AS name | | Order/limit | ORDER BY n.name LIMIT 10 | | Count | RETURN count(n) | | Variable path | MATCH p=(a)-[*1..5]->(b) |


Skill Routing

Use this table to find the right specialized skill:

| When you need to... | Use this skill | |---------------------|----------------| | Advanced graph algorithms (PageRank, community detection) | lang-cypher-patterns-dev (future) | | Performance tuning, query profiling | lang-cypher-patterns-dev (future) | | Database administration, backup/restore | lang-cypher-admin-ops (future) | | APOC procedures and custom extensions | lang-cypher-patterns-dev (future) |


Node Patterns

Basic Node Matching

// Match all nodes
MATCH (n)
RETURN n

// Match nodes with specific label
MATCH (p:Person)
RETURN p

// Match nodes with multiple labels
MATCH (u:User:Admin)
RETURN u

// Match node with properties
MATCH (p:Person {name: 'Alice'})
RETURN p

// Match node with WHERE clause
MATCH (p:Person)
WHERE p.age > 30
RETURN p

Creating Nodes

// Create single node
CREATE (p:Person {name: 'Alice', age: 30})
RETURN p

// Create multiple nodes
CREATE
  (p1:Person {name: 'Alice'}),
  (p2:Person {name: 'Bob'})
RETURN p1, p2

// Create node with multiple labels
CREATE (u:User:Admin {name: 'Alice', role: 'admin'})
RETURN u

// Create and set properties
CREATE (p:Person)
SET p.name = 'Alice', p.age = 30
RETURN p

Merging Nodes (Upsert)

// MERGE: Create if not exists, match if exists
MERGE (p:Person {email: 'alice@example.com'})
ON CREATE SET p.name = 'Alice', p.created = timestamp()
ON MATCH SET p.lastSeen = timestamp()
RETURN p

// MERGE with complex logic
MERGE (u:User {id: 123})
ON CREATE SET
  u.name = 'Alice',
  u.created = timestamp(),
  u.status = 'new'
ON MATCH SET
  u.updated = timestamp(),
  u.loginCount = u.loginCount + 1
RETURN u

Relationship Patterns

Basic Relationship Matching

// Match any relationship
MATCH (a)-[r]->(b)
RETURN a, r, b

// Match specific relationship type
MATCH (a:Person)-[r:KNOWS]->(b:Person)
RETURN a, r, b

// Match undirected relationship
MATCH (a:Person)-[r:KNOWS]-(b:Person)
RETURN a, r, b

// Match relationship with properties
MATCH (a:Person)-[r:KNOWS {since: 2020}]->(b:Person)
RETURN a, r, b

// Match multiple relationship types
MATCH (a)-[r:KNOWS|FOLLOWS]->(b)
RETURN a, type(r), b

Creating Relationships

// Create relationship between existing nodes
MATCH (a:Person {name: 'Alice'})
MATCH (b:Person {name: 'Bob'})
CREATE (a)-[r:KNOWS {since: 2020}]->(b)
RETURN a, r, b

// Create nodes and relationships in one query
CREATE (a:Person {name: 'Alice'})
CREATE (b:Person {name: 'Bob'})
CREATE (a)-[r:KNOWS]->(b)
RETURN a, r, b

// Compact syntax
CREATE (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person {name: 'Bob'})
RETURN a, r, b

Merging Relationships

// MERGE relationship (with nodes)
MATCH (a:Person {name: 'Alice'})
MATCH (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS]->(b)
ON CREATE SET r.since = timestamp()
RETURN a, r, b

// MERGE entire pattern
MERGE (a:Person {email: 'alice@example.com'})-[r:KNOWS]->(b:Person {email: 'bob@example.com'})
ON CREATE SET
  a.name = 'Alice',
  b.name = 'Bob',
  r.created = timestamp()
RETURN a, r, b

Path Patterns

Fixed-Length Paths

// 2-hop path
MATCH (a:Person)-[:KNOWS]->(:Person)-[:KNOWS]->(b:Person)
WHERE a.name = 'Alice'
RETURN b

// Pattern with named intermediate nodes
MATCH (a:Person)-[:KNOWS]->(friend:Person)-[:KNOWS]->(fof:Person)
RETURN a.name, friend.name, fof.name

Variable-Length Paths

// Any path length (use with caution!)
MATCH p=(a:Person)-[:KNOWS*]->(b:Person)
WHERE a.name = 'Alice'
RETURN p

// Path with length bounds (1 to 3 hops)
MATCH p=(a:Person)-[:KNOWS*1..3]->(b:Person)
WHERE a.name = 'Alice'
RETURN b.name, length(p) AS hops

// Shortest path
MATCH p=shortestPath((a:Person)-[:KNOWS*]-(b:Person))
WHERE a.name = 'Alice' AND b.name = 'Charlie'
RETURN length(p) AS distance, nodes(p) AS path

// All shortest paths
MATCH p=allShortestPaths((a:Person)-[:KNOWS*]-(b:Person))
WHERE a.name = 'Alice' AND b.name = 'Charlie'
RETURN p

Path Functions

// Extract path components
MATCH p=(a:Person)-[:KNOWS*1..3]->(b:Person)
WHERE a.name = 'Alice'
RETURN
  length(p) AS pathLength,
  nodes(p) AS allNodes,
  relationships(p) AS allRels,
  [n in nodes(p) | n.name] AS names

Filtering with WHERE

Property Comparisons

// Basic comparisons
MATCH (p:Person)
WHERE p.age > 30
RETURN p

// Multiple conditions (AND)
MATCH (p:Person)
WHERE p.age > 30 AND p.city = 'New York'
RETURN p

// OR conditions
MATCH (p:Person)
WHERE p.age < 20 OR p.age > 60
RETURN p

// NULL checks
MATCH (p:Person)
WHERE p.email IS NOT NULL
RETURN p

// Property exists
MATCH (p:Person)
WHERE exists(p.email)
RETURN p

String Matching

// Case-sensitive contains
MATCH (p:Person)
WHERE p.name CONTAINS 'ali'
RETURN p

// Case-insensitive (convert to lowercase)
MATCH (p:Person)
WHERE toLower(p.name) CONTAINS 'ali'
RETURN p

// Starts with
MATCH (p:Person)
WHERE p.name STARTS WITH 'A'
RETURN p

// Ends with
MATCH (p:Person)
WHERE p.email ENDS WITH '@example.com'
RETURN p

// Regex matching
MATCH (p:Person)
WHERE p.email =~ '.*@example\\.com'
RETURN p

Collection Filtering

// IN operator
MATCH (p:Person)
WHERE p.name IN ['Alice', 'Bob', 'Charlie']
RETURN p

// Check property in list
MATCH (p:Person)
WHERE 'admin' IN p.roles
RETURN p

// ANY predicate
MATCH (p:Person)
WHERE ANY(role IN p.roles WHERE role STARTS WITH 'dev')
RETURN p

// ALL predicate
MATCH (p:Person)
WHERE ALL(x IN p.scores WHERE x > 50)
RETURN p

// NONE predicate
MATCH (p:Person)
WHERE NONE(x IN p.tags WHERE x = 'blocked')
RETURN p

// SINGLE predicate (exactly one match)
MATCH (p:Person)
WHERE SINGLE(x IN p.roles WHERE x = 'admin')
RETURN p

Relationship Filtering

// Filter on relationship properties
MATCH (a:Person)-[r:KNOWS]->(b:Person)
WHERE r.since > 2020
RETURN a, b

// Filter on relationship existence
MATCH (p:Person)
WHERE NOT (p)-[:KNOWS]->()
RETURN p  // People who don't know anyone

// Filter on degree
MATCH (p:Person)
WHERE size((p)-[:KNOWS]->()) > 5
RETURN p  // People who know more than 5 others

Aggregation

Basic Aggregations

// Count
MATCH (p:Person)
RETURN count(p) AS totalPeople

// Count distinct
MATCH (p:Person)
RETURN count(DISTINCT p.city) AS uniqueCities

// Sum
MATCH (p:Person)
RETURN sum(p.age) AS totalAge

// Average
MATCH (p:Person)
RETURN avg(p.age) AS averageAge

// Min/Max
MATCH (p:Person)
RETURN min(p.age) AS youngest, max(p.age) AS oldest

// Collect into list
MATCH (p:Person)
RETURN collect(p.name) AS allNames

// Collect distinct
MATCH (p:Person)
RETURN collect(DISTINCT p.city) AS cities

Grouping

// GROUP BY (implicit via non-aggregated fields)
MATCH (p:Person)
RETURN p.city, count(p) AS population
ORDER BY population DESC

// Multiple grouping fields
MATCH (p:Person)
RETURN p.city, p.age, count(p) AS count

// Aggregation with relationships
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN c.name, count(p) AS employees
ORDER BY employees DESC

WITH Clause (Pipeline Queries)

// Use WITH to chain query parts
MATCH (p:Person)
WITH p.city AS city, count(p) AS population
WHERE population > 100
RETURN city, population
ORDER BY population DESC

// Aggregate then filter
MATCH (p:Person)-[:KNOWS]->(friend:Person)
WITH p, count(friend) AS friendCount
WHERE friendCount > 10
RETURN p.name, friendCount

// Multiple WITH clauses
MATCH (p:Person)
WITH p.city AS city, count(p) AS pop
WHERE pop > 50
WITH city, pop
ORDER BY pop DESC
LIMIT 5
RETURN city, pop

Modifying Data

Updating Properties

// SET property
MATCH (p:Person {name: 'Alice'})
SET p.age = 31
RETURN p

// SET multiple properties
MATCH (p:Person {name: 'Alice'})
SET p.age = 31, p.city = 'Boston', p.updated = timestamp()
RETURN p

// SET from map
MATCH (p:Person {name: 'Alice'})
SET p += {age: 31, city: 'Boston'}
RETURN p

// REMOVE property
MATCH (p:Person {name: 'Alice'})
REMOVE p.age
RETURN p

Adding and Removing Labels

// Add label
MATCH (p:Person {name: 'Alice'})
SET p:Admin
RETURN p

// Remove label
MATCH (p:Person {name: 'Alice'})
REMOVE p:Admin
RETURN p

// Add multiple labels
MATCH (p:Person {name: 'Alice'})
SET p:Admin:Moderator
RETURN p

Deleting Data

// Delete node (must have no relationships)
MATCH (p:Person {name: 'Alice'})
DELETE p

// DETACH DELETE (removes relationships first)
MATCH (p:Person {name: 'Alice'})
DETACH DELETE p

// Delete relationship
MATCH (:Person {name: 'Alice'})-[r:KNOWS]->(:Person {name: 'Bob'})
DELETE r

// Delete all nodes and relationships (DANGEROUS!)
MATCH (n)
DETACH DELETE n

// Conditional delete
MATCH (p:Person)
WHERE p.inactive = true
DETACH DELETE p

Indexes and Constraints

Creating Indexes

// Single-property index
CREATE INDEX person_name FOR (p:Person) ON (p.name)

// Composite index
CREATE INDEX person_name_age FOR (p:Person) ON (p.name, p.age)

// Full-text index
CREATE FULLTEXT INDEX person_search FOR (p:Person) ON EACH [p.name, p.bio]

// Index on relationship
CREATE INDEX knows_since FOR ()-[r:KNOWS]-() ON (r.since)

Creating Constraints

// Unique constraint (automatically creates index)
CREATE CONSTRAINT person_email_unique FOR (p:Person) REQUIRE p.email IS UNIQUE

// Node key (multiple properties must be unique together)
CREATE CONSTRAINT person_key FOR (p:Person) REQUIRE (p.firstName, p.lastName) IS NODE KEY

// Property existence (Enterprise only)
CREATE CONSTRAINT person_name_exists FOR (p:Person) REQUIRE p.name IS NOT NULL

// Relationship existence (Enterprise only)
CREATE CONSTRAINT knows_since_exists FOR ()-[r:KNOWS]-() REQUIRE r.since IS NOT NULL

Managing Indexes and Constraints

// List all indexes
SHOW INDEXES

// List all constraints
SHOW CONSTRAINTS

// Drop index
DROP INDEX person_name

// Drop constraint
DROP CONSTRAINT person_email_unique

Common Graph Patterns

Friend-of-Friend (Recommendation)

// Find friends of friends (2nd degree)
MATCH (me:Person {name: 'Alice'})-[:KNOWS]->(friend)-[:KNOWS]->(fof)
WHERE NOT (me)-[:KNOWS]->(fof) AND me <> fof
RETURN DISTINCT fof.name, count(friend) AS mutualFriends
ORDER BY mutualFriends DESC
LIMIT 10

Hierarchical Data (Tree Traversal)

// Find all descendants
MATCH (root:Category {name: 'Electronics'})-[:PARENT_OF*]->(descendant)
RETURN descendant

// Find path from root to leaf
MATCH path = (root:Category {name: 'Electronics'})-[:PARENT_OF*]->(leaf:Category)
WHERE NOT (leaf)-[:PARENT_OF]->()
RETURN path

// Find depth of each node
MATCH (root:Category {name: 'Electronics'})-[:PARENT_OF*]->(node)
RETURN node.name, length(path) AS depth

Finding Cycles

// Find circular dependencies
MATCH (a:Task)-[:DEPENDS_ON*]->(b:Task)-[:DEPENDS_ON*]->(a)
RETURN DISTINCT a.name, b.name

// Find triangles (3-node cycles)
MATCH (a:Person)-[:KNOWS]->(b:Person)-[:KNOWS]->(c:Person)-[:KNOWS]->(a)
WHERE id(a) < id(b) AND id(b) < id(c)
RETURN a.name, b.name, c.name

Social Network Patterns

// Mutual followers
MATCH (me:Person {name: 'Alice'})-[:FOLLOWS]->(person:Person)
WHERE (person)-[:FOLLOWS]->(me)
RETURN person.name

// Most influential (most followers)
MATCH (p:Person)<-[:FOLLOWS]-(follower)
RETURN p.name, count(follower) AS followers
ORDER BY followers DESC
LIMIT 10

// Activity feed (posts from followed users)
MATCH (me:Person {name: 'Alice'})-[:FOLLOWS]->(user:Person)-[:POSTED]->(post:Post)
RETURN post.content, post.timestamp, user.name
ORDER BY post.timestamp DESC
LIMIT 20

Collaborative Filtering

// Users who liked similar items
MATCH (me:User {id: 123})-[:LIKED]->(item:Item)<-[:LIKED]-(other:User)
WITH other, count(item) AS commonItems
WHERE commonItems > 3
RETURN other.name, commonItems
ORDER BY commonItems DESC

// Recommend items liked by similar users
MATCH (me:User {id: 123})-[:LIKED]->(myItem:Item)<-[:LIKED]-(other:User)
MATCH (other)-[:LIKED]->(rec:Item)
WHERE NOT (me)-[:LIKED]->(rec)
RETURN rec.title, count(DISTINCT other) AS recommendations
ORDER BY recommendations DESC
LIMIT 10

Query Optimization

Using EXPLAIN and PROFILE

// EXPLAIN: Shows query plan without executing
EXPLAIN
MATCH (p:Person {name: 'Alice'})
RETURN p

// PROFILE: Executes and shows actual performance metrics
PROFILE
MATCH (p:Person)
WHERE p.age > 30
RETURN p

Optimization Tips

// BAD: Cartesian product
MATCH (a:Person), (b:Company)
WHERE a.companyId = b.id
RETURN a, b

// GOOD: Use relationship
MATCH (a:Person)-[:WORKS_AT]->(b:Company)
RETURN a, b

// BAD: Property lookup without index
MATCH (p:Person)
WHERE p.email = 'alice@example.com'
RETURN p

// GOOD: Create index first
CREATE INDEX person_email FOR (p:Person) ON (p.email)
// Then query
MATCH (p:Person {email: 'alice@example.com'})
RETURN p

// BAD: Unbounded variable-length path
MATCH (a)-[*]->(b)
RETURN a, b

// GOOD: Add upper bound
MATCH (a)-[*..5]->(b)
RETURN a, b

// Use LIMIT for large result sets
MATCH (p:Person)
RETURN p
LIMIT 100

Using Parameters

// Use parameters for better performance and security
// Parameter syntax: $paramName

// In neo4j driver or browser
:param name => 'Alice'
:param age => 30

// Query using parameters
MATCH (p:Person {name: $name})
WHERE p.age > $age
RETURN p

// Useful for batch operations
UNWIND $batchData AS data
MERGE (p:Person {id: data.id})
SET p.name = data.name, p.age = data.age

Troubleshooting

"Node not found" or Empty Results

// Check if nodes exist
MATCH (n:Person)
RETURN count(n)

// Check labels
CALL db.labels()

// Check for typos in property names
MATCH (n:Person)
RETURN keys(n)
LIMIT 1

Performance Issues

// Check for missing indexes
SHOW INDEXES

// Profile slow query
PROFILE
MATCH (p:Person)-[:KNOWS*1..3]->(friend)
WHERE p.name = 'Alice'
RETURN friend

// Look for:
// - DB Hits (lower is better)
// - Rows (indicates cardinality)
// - EstimatedRows vs Rows (large difference = poor stats)

Accidental Cartesian Products

// BAD: Creates cartesian product
MATCH (a:Person)
MATCH (b:Company)
RETURN a, b

// Warning: "This query builds a cartesian product between disconnected patterns"

// FIX: Add relationship or WHERE clause
MATCH (a:Person)
MATCH (b:Company)
WHERE a.companyId = b.id
RETURN a, b

Memory Issues

// BAD: Loads all nodes into memory
MATCH (n)
RETURN collect(n)

// GOOD: Process in batches
MATCH (n)
RETURN n
SKIP 0 LIMIT 1000

// Use WITH for intermediate aggregation
MATCH (p:Person)-[:KNOWS]->(friend)
WITH p, collect(friend)[0..10] AS topFriends
RETURN p.name, topFriends

References