neo4j-modeling-skill

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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
  • 从零开始设计图模型(领域 → 节点、关系、属性)
  • 评审现有模型,检测反模式
  • 决定使用节点、属性、关系还是标签
  • 将关系型或文档型schema迁移为图模型
  • 为n元或复杂关系设计中间节点
  • 检测并缓解超级节点/高扇出问题
  • 为模型选择并创建约束与索引

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

  • 编写或优化Cypher
    neo4j-cypher-skill
  • Spring Data Neo4j(@Node、@Relationship)
    neo4j-spring-data-skill
  • GraphQL类型定义
    neo4j-graphql-skill
  • 数据导入(LOAD CSV、APOC import)
    neo4j-import-skill

Inspect Before Designing

设计前的检查

On existing database, run first — never propose changes without current state:
cypher
CALL db.schema.visualization() YIELD nodes, relationships RETURN nodes, relationships;
SHOW CONSTRAINTS YIELD name, type, labelsOrTypes, properties RETURN name, type, labelsOrTypes, properties;
SHOW INDEXES YIELD name, type, labelsOrTypes, state WHERE state = 'ONLINE' RETURN name, type, labelsOrTypes;
If APOC available:
cypher
CALL apoc.meta.schema() YIELD value RETURN value;
MCP tool map:
OperationTool
Inspect schema
get-schema
SHOW CONSTRAINTS
,
SHOW INDEXES
read-cypher
CREATE CONSTRAINT ... IF NOT EXISTS
write-cypher
(show + confirm first)

对于现有数据库,先执行以下操作——绝不要在不了解当前状态的情况下提出更改:
cypher
CALL db.schema.visualization() YIELD nodes, relationships RETURN nodes, relationships;
SHOW CONSTRAINTS YIELD name, type, labelsOrTypes, properties RETURN name, type, labelsOrTypes, properties;
SHOW INDEXES YIELD name, type, labelsOrTypes, state WHERE state = 'ONLINE' RETURN name, type, labelsOrTypes;
如果APOC可用:
cypher
CALL apoc.meta.schema() YIELD value RETURN value;
MCP工具映射:
操作工具
检查schema
get-schema
SHOW CONSTRAINTS
,
SHOW INDEXES
read-cypher
CREATE CONSTRAINT ... IF NOT EXISTS
write-cypher
(先展示并确认)

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. No generic labels (
    :Entity
    ,
    :Node
    ,
    :Thing
    ); no generic rel types (
    :RELATED_TO
    ,
    :HAS
    )
  6. Rel direction encodes semantic meaning — not arbitrary
  7. Inspect schema before proposing any change on an existing database
  8. All constraint/index DDL uses
    IF NOT EXISTS
    — safe to rerun

  1. 以用例为先——设计前列出模型必须支持的5个以上查询
  2. 节点 = 具有标识的实体(名词);关系 = 具有方向的连接(动词)
  3. 标签采用PascalCase;关系类型采用SCREAMING_SNAKE_CASE;属性采用camelCase
  4. 所有用于MERGE的节点类型,其关键属性都要有唯一性约束
  5. 禁止使用通用标签(
    :Entity
    :Node
    :Thing
    );禁止使用通用关系类型(
    :RELATED_TO
    :HAS
  6. 关系方向需体现语义——不可随意设定
  7. 对现有数据库提出任何更改前,先检查schema
  8. 所有约束/索引DDL语句都使用
    IF NOT EXISTS
    ——可安全重复执行

Key Patterns

核心模式

Node vs Relationship vs Property — Decision Table

节点、关系、属性的决策表

QuestionAnswerModel as
Is it a thing with identity, queried as entry point?YesNode
Is it a connection between two things with direction?YesRelationship
Does the connection have its own properties or multiple targets?YesIntermediate node
Is it a scalar always returned with its parent, never filtered alone?YesProperty on parent
Is it a category used for type-based filtering or path traversal?YesLabel (not a property)
Does the same attribute value repeat across many nodes (low cardinality)?YesLabel, not a property node
Is it a fact connecting >2 entities?YesIntermediate node
问题答案建模为
它是具有标识、可作为查询入口的事物吗?节点
它是两个事物之间带有方向的连接吗?关系
该连接有自己的属性或多个目标吗?中间节点
它是始终随父节点返回、不会单独被过滤的标量值吗?父节点的属性
它是用于基于类型过滤或路径遍历的分类吗?标签(而非属性)
同一属性值在多个节点中重复出现(低基数)吗?标签,而非属性节点
它是连接2个以上实体的事实吗?中间节点

Property vs Label — Decision Table

属性与标签的决策表

Use label whenUse 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 selectionFine-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.

使用标签的场景使用属性的场景
值数量少、固定,用于遍历过滤(
WHERE n:Active
值数量多、动态,或每个节点唯一
按类型遍历(
MATCH (n:VIPCustomer)
按值过滤(
WHERE n.tier = 'vip'
分类决定索引选择细粒度值驱动范围扫描
示例:
:Active
:Verified
:Premium
示例:
status
score
email
规则:添加标签成本低;扫描所有
:Label
节点速度快。绝不要将高基数值建模为标签。

Intermediate Node Pattern

中间节点模式

Use when a relationship needs its own properties, connects >2 entities, or is independently queryable.
Before (relationship with property — limited):
(Person)-[:ACTED_IN {role: "Neo"}]->(Movie)
// Cannot query roles independent of movies
After (intermediate node — queryable, extensible):
(Person)-[:PLAYED]->(Role {name: "Neo"})-[:IN]->(Movie)
// MATCH (r:Role) WHERE r.name STARTS WITH 'Neo' RETURN r
Employment overlap example:
cypher
// Find colleagues who overlapped at same company
MATCH (p1:Person)-[:WORKED_AT]->(e1:Employment)-[:AT]->(c:Company)<-[:AT]-(e2:Employment)<-[:WORKED_AT]-(p2:Person)
WHERE p1 <> p2
  AND e1.startDate <= e2.endDate AND e2.startDate <= e1.endDate
RETURN p1.name, p2.name, c.name
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

当关系需要拥有自己的属性、连接2个以上实体,或可被独立查询时使用。
优化前(带属性的关系——局限性大):
(Person)-[:ACTED_IN {role: "Neo"}]->(Movie)
// 无法独立于电影查询角色
优化后(中间节点——可查询、可扩展):
(Person)-[:PLAYED]->(Role {name: "Neo"})-[:IN]->(Movie)
// MATCH (r:Role) WHERE r.name STARTS WITH 'Neo' RETURN r
就业重叠示例:
cypher
// 查找在同一家公司有工作重叠的同事
MATCH (p1:Person)-[:WORKED_AT]->(e1:Employment)-[:AT]->(c:Company)<-[:AT]-(e2:Employment)<-[:WORKED_AT]-(p2:Person)
WHERE p1 <> p2
  AND e1.startDate <= e2.endDate AND e2.startDate <= e1.endDate
RETURN p1.name, p2.name, c.name
当出现以下情况时,将关系升级为中间节点:
  • 关系有2个以上属性
  • 关系是其他查询的主体
  • 多个实体共享相同的连接上下文
  • 需要在一个事实中连接2个以上实体

Relational → Graph Migration Table

关系型→图模型迁移对照表

Relational constructGraph equivalentNotes
Table rowNodeOne label per table (add more as needed)
Column (scalar)Node property
Primary keyUniqueness constraint propertyUse
tmdbId
, not
id
(too generic)
Foreign keyRelationshipDirection: from dependent → referenced
Many-to-many junction tableIntermediate nodeEspecially if junction has own columns
Junction table (no own columns)Direct relationshipSimpler; upgrade to intermediate node later
NULL FK (optional relation)Absent relationshipNo node created; absence is the signal
Polymorphic FK (Rails-style)Multiple labels or relationship typesSplit into type-specific rels
Self-referential FKSame-label relationship
:Employee {managerId}
(e)-[:REPORTS_TO]->(m)
Audit/history columnsIntermediate versioning nodeSee References for versioning pattern

关系型结构图模型等价物说明
表行节点每个表对应一个标签(可按需添加更多)
列(标量)节点属性
主键带唯一性约束的属性使用
tmdbId
,而非
id
(过于通用)
外键关系方向:从依赖方→被引用方
多对多连接表中间节点尤其当连接表有自己的列时
连接表(无自有列)直接关系更简单;后续可升级为中间节点
NULL外键(可选关系)不存在的关系不创建节点;缺失即为信号
多态外键(Rails风格)多个标签或关系类型拆分为特定类型的关系
自引用外键同标签关系
:Employee {managerId}
(e)-[:REPORTS_TO]->(m)
审计/历史列中间版本节点参考版本控制模式(见参考文献)

Supernode Detection and Mitigation

超级节点检测与缓解

Detect:
cypher
// Find top-10 highest-degree nodes
MATCH (n)
RETURN labels(n) AS labels, elementId(n) AS id, count{ (n)--() } AS degree
ORDER BY degree DESC LIMIT 10
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):
StrategyWhen to useImplementation
Query directionDirectional asymmetry existsQuery from low-degree side; exploit direction
Relationship type splitSupernode serves multiple roles
:FOLLOWS
+
:FAN
instead of single
:RELATED_TO
Label segregationSupernode conflates entity types
:Celebrity
vs
:User
→ query only relevant subtype
Bucket patternTime-series or high-volume event nodesSee below
Avoid modelingLow-cardinality categoricalsUse label instead of node (
:Active
not
(:Status {name:"Active"})
)
Join hintQuery tuning last resort
USING JOIN ON n
in Cypher
Bucket pattern (time-series / high-volume):
cypher
// Instead of: (:User)-[:VIEWED]->(:Page) (millions of rels per user)
// Bucket by hour:
(u:User)-[:VIEWED_IN]->(b:ViewBucket {userId: u.id, hour: '2025-04-28T14'})-[:VIEWED]->(p:Page)

// Query last hour's views without traversing full history:
MATCH (u:User {id: $uid})-[:VIEWED_IN]->(b:ViewBucket {hour: $hour})-[:VIEWED]->(p)
RETURN p.url

检测:
cypher
// 查找度数最高的前10个节点
MATCH (n)
RETURN labels(n) AS labels, elementId(n) AS id, count{ (n)--() } AS degree
ORDER BY degree DESC LIMIT 10
度数远高于其标签中位数的节点即为超级节点候选。任何关系数超过10万的节点都会降低经过它的遍历查询性能。
原因:
  • 领域超级节点:机场、名人、热门标签——不可避免
  • 建模导致的超级节点:将性别、国家、状态建模为节点,产生数百万条边——可避免
缓解策略(按优先级排序):
策略适用场景实现方式
查询方向调整存在方向不对称性从低度数侧发起查询;利用关系方向
关系类型拆分超级节点承担多种角色
:FOLLOWS
+
:FAN
替代单一的
:RELATED_TO
标签隔离超级节点混淆了实体类型
:Celebrity
vs
:User
→ 仅查询相关子类型
分桶模式时间序列或高容量事件节点见下文
避免建模为节点低基数分类使用标签替代节点(
:Active
而非
(:Status {name:"Active"})
连接提示查询调优的最后手段在Cypher中使用
USING JOIN ON n
分桶模式(时间序列/高容量):
cypher
// 替代方案:(:User)-[:VIEWED]->(:Page)(每个用户有数百万条关系)
// 按小时分桶:
(u:User)-[:VIEWED_IN]->(b:ViewBucket {userId: u.id, hour: '2025-04-28T14'})-[:VIEWED]->(p:Page)

// 查询最近一小时的浏览记录,无需遍历完整历史:
MATCH (u:User {id: $uid})-[:VIEWED_IN]->(b:ViewBucket {hour: $hour})-[:VIEWED]->(p)
RETURN p.url

Naming Conventions

命名规范

ElementConventionGoodBad
Node labelPascalCase, singular noun
:Person
,
:BlogPost
:person
,
:blog_posts
,
:Entity
Relationship typeSCREAMING_SNAKE_CASE, verb phrase
:ACTED_IN
,
:WORKS_FOR
:actedin
,
:relatedTo
,
:HAS
Property keycamelCase
firstName
,
createdAt
FirstName
,
first_name
Constraint namesnake_case descriptive
person_id_unique
constraint1
Index namesnake_case descriptive
person_name_idx
index2

元素规范示例(正确)示例(错误)
节点标签PascalCase,单数名词
:Person
:BlogPost
:person
:blog_posts
:Entity
关系类型SCREAMING_SNAKE_CASE,动词短语
:ACTED_IN
:WORKS_FOR
:actedin
:relatedTo
:HAS
属性键camelCase
firstName
createdAt
FirstName
first_name
约束名称snake_case,描述性命名
person_id_unique
constraint1
索引名称snake_case,描述性命名
person_name_idx
index2

Schema Enforcement — What to Create for Each Element

Schema强制实施——为各元素创建的内容

Run all DDL with
IF NOT EXISTS
. Apply before importing data.
cypher
// 1. Uniqueness constraint — every node type used in MERGE
CREATE CONSTRAINT person_id_unique IF NOT EXISTS
  FOR (p:Person) REQUIRE p.id IS UNIQUE;

// 2. Existence constraint (Enterprise) — mandatory properties
CREATE CONSTRAINT person_name_exists IF NOT EXISTS
  FOR (p:Person) REQUIRE p.name IS NOT NULL;

// 3. Property type constraint (Enterprise) — enforce data type
CREATE CONSTRAINT person_born_integer IF NOT EXISTS
  FOR (p:Person) REQUIRE p.born IS :: INTEGER;

// 4. Key constraint (Enterprise) — unique + exists in one
CREATE CONSTRAINT movie_tmdbid_key IF NOT EXISTS
  FOR (m:Movie) REQUIRE m.tmdbId IS NODE KEY;

// 5. Range index — equality and range filters on properties
CREATE INDEX person_name_idx IF NOT EXISTS
  FOR (p:Person) ON (p.name);

// 6. Fulltext index — CONTAINS, STARTS WITH, free text search
CREATE FULLTEXT INDEX person_fulltext IF NOT EXISTS
  FOR (n:Person) ON EACH [n.name, n.bio];

// 7. Vector index — embedding similarity search
CREATE VECTOR INDEX chunk_embedding_idx IF NOT EXISTS
  FOR (c:Chunk) ON (c.embedding)
  OPTIONS { indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine' } };

// 8. Relationship index — filter on rel properties
CREATE INDEX acted_in_year_idx IF NOT EXISTS
  FOR ()-[r:ACTED_IN]-() ON (r.year);
After creating indexes, poll until ONLINE:
cypher
SHOW INDEXES YIELD name, state WHERE state <> 'ONLINE' RETURN name, state;
Do NOT use an index until state =
ONLINE
.

所有DDL语句都使用
IF NOT EXISTS
。在导入数据前应用。
cypher
// 1. 唯一性约束——所有用于MERGE的节点类型
CREATE CONSTRAINT person_id_unique IF NOT EXISTS
  FOR (p:Person) REQUIRE p.id IS UNIQUE;

// 2. 存在性约束(企业版)——必填属性
CREATE CONSTRAINT person_name_exists IF NOT EXISTS
  FOR (p:Person) REQUIRE p.name IS NOT NULL;

// 3. 属性类型约束(企业版)——强制数据类型
CREATE CONSTRAINT person_born_integer IF NOT EXISTS
  FOR (p:Person) REQUIRE p.born IS :: INTEGER;

// 4. 键约束(企业版)——唯一性+存在性二合一
CREATE CONSTRAINT movie_tmdbid_key IF NOT EXISTS
  FOR (m:Movie) REQUIRE m.tmdbId IS NODE KEY;

// 5. 范围索引——属性的等值与范围过滤
CREATE INDEX person_name_idx IF NOT EXISTS
  FOR (p:Person) ON (p.name);

// 6. 全文索引——CONTAINS、STARTS WITH、自由文本搜索
CREATE FULLTEXT INDEX person_fulltext IF NOT EXISTS
  FOR (n:Person) ON EACH [n.name, n.bio];

// 7. 向量索引——嵌入向量相似度搜索
CREATE VECTOR INDEX chunk_embedding_idx IF NOT EXISTS
  FOR (c:Chunk) ON (c.embedding)
  OPTIONS { indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine' } };

// 8. 关系索引——基于关系属性过滤
CREATE INDEX acted_in_year_idx IF NOT EXISTS
  FOR ()-[r:ACTED_IN]-() ON (r.year);
创建索引后,轮询直到状态变为ONLINE:
cypher
SHOW INDEXES YIELD name, state WHERE state <> 'ONLINE' RETURN name, state;
不要在状态变为
ONLINE
前使用索引。

Vector / Embedding Property Modeling

向量/嵌入属性建模

Store embeddings on dedicated
:Chunk
nodes, never on business nodes:
(:Document)-[:HAS_CHUNK]->(c:Chunk {text: "...", embedding: [...]})
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

将嵌入向量存储在专用的
:Chunk
节点上,绝不要存储在业务节点上:
(:Document)-[:HAS_CHUNK]->(c:Chunk {text: "...", embedding: [...]})
规则:
  • Chunk节点:包含
    text
    (源文本)、
    embedding
    (浮点数组)、
    chunkIndex
    (整数)
  • 父文档:仅存储元数据(标题、url、createdAt)
  • 仅在
    c.embedding
    上创建向量索引
  • 生产环境默认的分块大小为200–500 tokens,重叠率20% [field]
  • 不要将嵌入向量放在
    :Document
    节点上——会导致节点过大,拖慢遍历速度

Anti-Patterns Table

反模式对照表

Anti-patternProblemFix
Generic labels
:Entity
,
:Node
No filtering benefit; all nodes scanUse domain labels
:Person
,
:Product
Generic rel types
:RELATED_TO
,
:HAS
Can't filter by relationship typeUse semantic types
:PURCHASED
,
:AUTHORED
Low-cardinality value as nodeSupernode (
:Status {name:"active"}
→ millions of edges)
Use label
:Active
instead
Property as label (
n.type = 'VIP'
+
:VIP
label both exist)
Inconsistency, duplicationPick one; prefer label if used in traversal
Storing embeddings on business nodeNode bloat, slow traversalDedicated
:Chunk
node
MERGE without uniqueness constraintDuplicate nodes silently createdAdd constraint before any MERGE
Missing relationship direction meaningArbitrary direction; confusing modelDirection = semantic flow of action
Junction table modeled as bare propertyLoses history and extensibilityIntermediate node with its own properties
id
as property name
Conflicts with driver internal
id(n)
Use
personId
,
movieId
,
tmdbId
All dates as stringsNo range queries; no temporal operatorsUse Neo4j
date()
or
datetime()
type

反模式问题修复方案
通用标签
:Entity
:Node
无过滤优势;需扫描所有节点使用领域标签
:Person
:Product
通用关系类型
:RELATED_TO
:HAS
无法按关系类型过滤使用语义化类型
:PURCHASED
:AUTHORED
低基数值建模为节点产生超级节点(
:Status {name:"active"}
→ 数百万条边)
使用标签
:Active
替代
属性与标签重复(同时存在
n.type = 'VIP'
:VIP
标签)
不一致、重复二选一;若用于遍历则优先选择标签
嵌入向量存储在业务节点上节点膨胀,遍历缓慢使用专用
:Chunk
节点
MERGE操作无唯一性约束会静默创建重复节点在执行任何MERGE前添加约束
关系方向无语义方向随意;模型易混淆方向 = 动作的语义流向
连接表建模为普通属性丢失历史信息与扩展性使用带自有属性的中间节点
使用
id
作为属性名
与驱动内部
id(n)
冲突
使用
personId
movieId
tmdbId
所有日期存储为字符串无法执行范围查询;无法使用时间运算符使用Neo4j的
date()
datetime()
类型

Output Format — Schema Assessment

输出格式——Schema评估

When reviewing an existing model:
undefined
评审现有模型时:
undefined

Schema Assessment

Schema评估

Compliant

合规项

  • [constraint / pattern that is correct]
  • [正确的约束/模式]

Issues Found

发现的问题

[Title] — Severity: ERROR / WARNING / INFO

[标题] — 严重程度:ERROR / WARNING / INFO

  • Current: what the model does
  • Problem: why it is an issue
  • Fix: specific Cypher DDL or model change
  • 当前状态:模型的现有做法
  • 问题:为何这是一个问题
  • 修复方案:具体的Cypher DDL语句或模型更改

Recommended Schema

推荐的Schema

Node Labels

节点标签

  • :Label {key: TYPE, prop: TYPE, ...} → constraints: [list]
  • :Label {key: TYPE, prop: TYPE, ...} → 约束:[列表]

Relationships

关系

  • (:LabelA)-[:TYPE {prop: TYPE}]->(:LabelB)
  • (:LabelA)-[:TYPE {prop: TYPE}]->(:LabelB)

Constraints to Create

需创建的约束

[CREATE CONSTRAINT ... statements]
[CREATE CONSTRAINT ... 语句]

Indexes to Create

需创建的索引

[CREATE INDEX ... statements]

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 |

---
[CREATE INDEX ... 语句]

严重程度语义:

| 严重程度 | 含义 | 操作 |
|---|---|---|
| `ERROR` | 模型正确性问题(可能产生重复数据、存在数据丢失风险) | 停止操作;修复后再继续 |
| `WARNING` | 存在性能或扩展性风险 | 上报;继续前需询问用户 |
| `INFO` | 风格或规范偏差 | 告知用户;继续操作 |

---

Provenance Labels

来源标签

  • [official]
    — stated directly in Neo4j docs
  • [derived]
    — follows from documented behavior
  • [field]
    — community heuristic; treat as default but validate

  • [official]
    — 直接来自Neo4j官方文档
  • [derived]
    — 由文档记录的行为推导而来
  • [field]
    — 社区经验法则;作为默认方案但需验证

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

  • 建模前已定义用例(≥5个查询)
  • 对现有数据库提出更改前已检查schema
  • 所有MERGE目标节点标签都有唯一性约束
  • 无通用标签(
    :Entity
    :Node
    :Thing
  • 无通用关系类型(
    :RELATED_TO
    :HAS
    :CONNECTED_TO
  • 关系方向体现语义
  • n元或带属性的关系使用中间节点
  • 高基数值存储为属性,而非节点
  • 低基数分类使用标签,而非属性节点
  • 嵌入向量存储在专用
    :Chunk
    节点上,而非业务节点
  • 已识别并缓解超级节点候选
  • 所有DDL语句使用
    IF NOT EXISTS
  • 索引在状态变为ONLINE后才使用
  • 评估输出遵循上述结构化格式
  • 每个禁止项都配有具体修复方案

References

参考文献

Load on demand:
按需加载: