neo4j-modeling-skill

Design, review, and refactor Neo4j graph data models. Use when choosing node labels vs relationship types vs properties, migrating relational/document schemas to graph, detecting anti-patterns (generic labels, supernodes, missing constraints), designing intermediate nodes for n-ary relationships, en

By neo4j-contrib · 810 installs

npx skills add neo4j-contrib/neo4j-skills --skill neo4j-modeling-skill

Source repository · Upstream listing

When to Use Designing graph model from scratch (domain → nodes, rels, props) Reviewing existing model for anti patterns Deciding node vs property vs relationship vs label Migrating relational or document schema to graph Designing intermediate nodes for n ary or complex relationships Detecting and mitigating supernode / high fanout problems Choosing and creating constraints + indexes for a model When NOT to Use Writing or optimizing Cypher → neo4j cypher skill Spring Data Neo4j (@Node, @Relationship) → neo4j spring data skill GraphQL type definitions → neo4j graphql skill Importing data (LOAD CSV, APOC import) → neo4j import skill Inspect Before Designing On existing database, run first — never propose changes without current state: If APOC available: MCP tool map: Operation Tool Inspect schema get schema SHOW CONSTRAINTS , SHOW INDEXES read cypher CREATE CONSTRAINT ... IF NOT EXISTS write cypher (show + confirm first) Defaults — Apply to Every Model 1. Use case first — list 5+ queries the model must answer before designing 2. Nodes = entities (nouns) with identity; rels = connections (verbs) with direction 3. Labels PascalCase; rel types SCREAMING SNAKE CASE; properties camelCase 4. Every node type used in MERGE has a uniqueness constraint on its key property 5. Add property type constraints ( REQUIRE n.prop IS :: STRING ) where the type is known — helps the query planner and catches bad writes early 6. No generic labels ( :Entity , :Node , :Thing ); no generic rel types ( :RELATED TO , :HAS ) 7. Security labels (used for row level access control) should start with a common prefix (e.g. Sec ) so application code can reliably filter them out of the domain schema 8. Rel direction encodes semantic meaning — not arbitrary 9. Inspect schema before proposing any change on an existing database 10. All constraint/index DDL uses IF NOT EXISTS — safe to rerun 11. On Neo4j 2026.06+ (Enterprise/Aura, GA): declare the full model in one block with ALTER CURRENT GRAPH TYPE SET { … } , extend it with ALTER CURRENT GRAPH TYPE ADD { … } , instead of individual CREATE CONSTRAINT statements — see neo4j cypher skill/references/graph type.md . On 2026.02–2026.05 the same syntax is preview. Key Patterns Node vs Relationship vs Property — Decision Table Question Answer Model as Is it a thing with identity, queried as entry point? Yes Node Is it a connection between two things with direction? Yes Relationship Does the connection have its own properties or multiple targets? Yes Intermediate node Is it a scalar always returned with its parent, never filtered alone? Yes Property on parent Is it a category used for type based filtering or path traversal? Yes Label (not a property) Does the same attribute value repeat across many nodes (low cardinality)? Yes Label, not a property node Is it a fact connecting 2 entities? Yes Intermediate node Property vs Label — Decision Table Use label when Use property when Values are few, fixed, used as traversal filters ( WHERE n:Active ) Values are many, dynamic, or unique per node You traverse by type ( MATCH (n:VIPCustomer) ) You filter by value ( WHERE n.tier = 'vip' ) Category drives index selection Fine grained value drives range scans Example: :Active , :Verified , :Premium Example: status , score , email Rule: adding a label is cheap; scanning all :Label nodes is fast. Never model high cardinality values as labels. Intermediate Node Pattern Use when a relationship needs its own properties, connects 2 entities, or is independently queryable. Before (relationship with property — limited): After (intermediate node — queryable, extensible): Employment overlap example: Promote relationship to intermediate node when: Relationship has 2 properties Relationship is the subject of another query Multiple entities share the same connection context You need to connect 2 entities in one fact Relational → Graph Migration Table Relational construct Graph equivalent Notes Table row Node One label per table (add more as needed) Column (scalar) Node property Primary key Uniqueness constraint property Use tmdbId , not id (too generic) Foreign key Relationship Direction: from dependent → referenced Many to many junction table Intermediate node Especially if junction has own columns Junction table (no own columns) Direct relationship Simpler; upgrade to intermediate node later NULL FK (optional relation) Absent relationship No node created; absence is the signal Polymorphic FK (Rails style) Multiple labels or relationship types Split into type specific rels Self referential FK Same label relationship :Employee {managerId} → (e) [:REPORTS TO] (m) Audit/history columns Intermediate versioning node See References for versioning pattern Supernode Detection and Mitigation Detect: Node with degree median for its label = supernode candidate. Any node with 100K relationships will degrade traversal queries that pass through it. Causes: Domain supernodes: airports, celebrities, popular hashtags — unavoidable Modeling supernodes: gender, country, status modeled as nodes with millions of edges — avoidable Mitigation strategies (in priority order): Strategy When to use Implementation Query direction Directional asymmetry exists Query from low degree side; exploit direction Relationship type split Supernode serves multiple roles :FOLLOWS + :FAN instead of single :RELATED TO Label segregation Supernode conflates entity types :Celebrity vs :User → query only relevant subtype Bucket pattern Time series or high volume event nodes See below Avoid modeling Low cardinality categoricals Use label instead of node ( :Active not (:Status {name:"Active"}) ) Join hint Query tuning last resort USING JOIN ON n in Cypher Bucket pattern (time series / high volume): Naming Conventions Element Convention Good Bad Node label PascalCase, singular noun :Person , :BlogPost :person , :blog posts , :Entity Relationship type SCREAMING SNAKE CASE, verb phrase :ACTED IN , :WORKS FOR :actedin , :relatedTo , :HAS Property key camelCase firstName , createdAt FirstName , first name Constraint name snake case descriptive person id unique constraint1 Index name snake case descriptive person name idx index2 Schema Enforcement — What to Create for Each Element Run all DDL with IF NOT EXISTS . Apply before importing data. After creating indexes, poll until ONLINE: Do NOT use an index until state = ONLINE . Vector / Embedding Property Modeling Store embeddings on dedicated :Chunk nodes, never on business nodes: Rules: Chunk node: text (source text), embedding (float array), chunkIndex (int) Parent document: metadata only (title, url, createdAt) Vector index on c.embedding only Chunk size 200–500 tokens with 20% overlap is production default [field] Do NOT put embedding on :Document — makes the node too large and pollutes traversal Anti Patterns Table Anti pattern Problem Fix Generic labels :Entity , :Node No filtering benefit; all nodes scan Use domain labels :Person , :Product Generic rel types :RELATED TO , :HAS Can't filter by relationship type Use semantic types :PURCHASED , :AUTHORED Low cardinality value as node Supernode ( :Status {name:"active"} → millions of edges) Use label :Active instead Property as label ( n.type = 'VIP' + :VIP label both exist) Inconsistency, duplication Pick one; prefer label if used in traversal Storing embeddings on business node Node bloat, slow traversal Dedicated :Chunk node MERGE without uniqueness constraint Duplicate nodes silently created Add constraint before any MERGE Missing relationship direction meaning Arbitrary direction; confusing model Direction = semantic flow of action Junction table modeled as bare property Loses history and extensibility Intermediate node with its own properties id as property name id(n) is a deprecated Cypher function (use elementId(n) ); bare id is fine as a property name in practice, but domain qualified names ( personId , movieId ) are clearer and avoid any future ambiguity Prefer personId , movieId , tmdbId where it aids readability All dates as strings No range queries; no temporal operators Use Neo4j date() or datetime() type Output Format — Schema Assessment When reviewing an existing model: Severity semantics: Severity Meaning Action ERROR Model correctness failure (duplicates possible, data loss risk) Stop; fix before proceeding WARNING Performance or extensibility risk Report; ask user before proceeding INFO Style or convention deviation Surface; continue Provenance Labels [official] — stated directly in Neo4j docs [derived] — follows from documented behavior [field] — community heuristic; treat as default but validate Checklist [ ] Use cases (≥5 queries) defined before modeling [ ] Schema inspected on existing database before changes proposed [ ] Every MERGE target node label has a uniqueness constraint [ ] No generic labels ( :Entity , :Node , :Thing ) [ ] No generic relationship types ( :RELATED TO , :HAS , :CONNECTED TO ) [ ] Relationship direction encodes semantic meaning [ ] N ary or propertied relationships use intermediate nodes [ ] High cardinality values stored as properties, not nodes [ ] Low cardinality categoricals used as labels, not property nodes [ ] Embeddings on dedicated :Chunk nodes, not business nodes [ ] Supernode candidates identified and mitigated [ ] All DDL uses IF NOT EXISTS [ ] Indexes polled to ONLINE before use [ ] Assessment output follows the structured format above [ ] Every prohibition paired with a concrete fix References Load on demand: [references/modeling patterns.md](references/modeling patterns.md) — time series, versioning, multi tenancy, linked list, access control patterns [Neo4j Data Modeling Guide](https://neo4j.com/docs/getting started/data modeling/guide data modeling/) [Neo4j Modeling Tips](https://neo4j.com/docs/getting started/data modeling/modeling tips/) [GraphAcademy: Graph Data Modeling Fundamentals](https://graphacademy.neo4j.com/courses/modeling fundamentals/) [Super Nodes — All About Super Nodes (David Allen)](https://medium.com/neo4j/graph modeling all about super nodes d6ad7e11015b)