Skip to content

muotai-spg 数据库设计与技术文档 ​

文档说明 ​

项目名称: muotai-spg 知识图谱持久层 版本: v1.0 创建日期: 2025-12-15 数据库: MySQL 8.0+, Neo4j 5.x ORM框架: MyBatis-Plus 3.5.x


目录 ​


一、数据库架构概览 ​

1.1 架构设计理念 ​

muotai-spg采用双数据库架构:

  • MySQL: 存储Schema元数据、项目配置、版本管理
  • Neo4j: 存储实际的知识图谱数据(节点和关系)
┌─────────────────────────────────────────────────────┐
│                   Application Layer                  │
│              (Spring Boot + MyBatis-Plus)            │
└─────────────────────────────────────────────────────┘
                         │
        ┌────────────────┴────────────────┐
        │                                 │
        ▼                                 ▼
┌──────────────────┐            ┌──────────────────┐
│      MySQL       │            │      Neo4j       │
│  (Schema Meta)   │            │  (Graph Data)    │
├──────────────────┤            ├──────────────────┤
│ • Project Info   │            │ • Nodes          │
│ • Entity Types   │            │ • Relationships  │
│ • Properties     │            │ • Properties     │
│ • Constraints    │            │ • Indexes        │
│ • Versions       │            │                  │
└──────────────────┘            └──────────────────┘

1.2 数据库职责划分 ​

数据类型MySQLNeo4j说明
Schema定义✅❌实体类型、属性定义、约束
元数据管理✅❌项目、业务域、用户权限
版本管理✅❌Schema版本、发布历史
图谱实例数据❌✅实际的实体节点和关系边
图查询❌✅多跳查询、路径查询
全文搜索✅✅MySQL: 元数据搜索, Neo4j: 内容搜索

1.3 表分类 ​

A. 项目与租户管理(2张表)

  • kg_biz_domain - 业务域表
  • kg_project_info - 项目信息表

B. 本体Schema管理(4张表)

  • kg_ontology_entity - 实体类型表
  • kg_ontology_entity_parent - 继承关系表
  • kg_ontology_entity_property_range - 属性范围表(SPO三元组)
  • kg_ontology_property_constraint - 属性约束表

C. 项目关联与版本(2张表)

  • kg_project_entity - 项目-实体关联表
  • kg_ontology_release - Schema发布版本表

二、详细表设计 ​

2.1 kg_biz_domain (业务域表) ​

表名: kg_biz_domain用途: 多租户管理,一个业务域可包含多个项目,实现数据隔离

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
nameVARCHAR(100)NOT NULL业务域名称
descriptionVARCHAR(1024)NULL业务域描述
global_configTEXTNULL全局配置(JSON格式)
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
KEY idx_status (status)

字段详解 ​

global_config (JSON格式示例):

json
{
  "max_projects": 100,
  "storage_quota": "100GB",
  "features": ["multi_version", "graph_query"],
  "notification": {
    "email": "admin@example.com",
    "webhook": "https://api.example.com/webhook"
  }
}

业务规则 ​

  1. 默认业务域: 系统初始化时自动创建 default 业务域
  2. 软删除: 删除业务域时设置 status='9',不物理删除
  3. 级联影响: 删除业务域时,需先处理其下所有项目

示例数据 ​

sql
INSERT INTO kg_biz_domain (name, description, status)
VALUES ('default', '默认业务域', '1');

INSERT INTO kg_biz_domain (name, description, global_config, status)
VALUES (
  'medical',
  '医疗行业业务域',
  '{"max_projects": 50, "industry": "healthcare"}',
  '1'
);

2.2 kg_project_info (项目信息表) ​

表名: kg_project_info用途: 知识图谱项目管理,每个项目对应一个独立的知识图谱

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
nameVARCHAR(255)NOT NULL, UNIQUE项目名称(唯一)
descriptionVARCHAR(1024)NULL项目描述
namespaceVARCHAR(64)NOT NULL, DEFAULT ''命名空间
biz_domain_idBIGINT(20)NULL, FK业务域ID
configTEXTNULL项目配置(JSON格式)
visibilityVARCHAR(64)DEFAULT 'PRIVATE'可见性: PRIVATE/PUBLIC
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间
creatorVARCHAR(64)NULL创建人
modifierVARCHAR(64)NULL修改人

索引设计 ​

sql
PRIMARY KEY (id)
UNIQUE KEY uk_name (name)
KEY idx_biz_domain_id (biz_domain_id)
KEY idx_namespace (namespace)

字段详解 ​

namespace命名规范:

  • 格式: 小写字母、数字、下划线
  • 示例: medical, finance, e_commerce
  • 用途: Schema唯一命名空间,避免类型冲突

config (JSON格式示例):

json
{
  "graph_db": {
    "type": "neo4j",
    "database": "medical_kg",
    "connection": {
      "uri": "bolt://localhost:7687",
      "username": "neo4j"
    }
  },
  "storage": {
    "max_entities": 1000000,
    "max_relations": 5000000
  },
  "features": {
    "version_control": true,
    "full_text_search": true,
    "reasoning": false
  },
  "permissions": {
    "public_read": false,
    "allow_export": true
  }
}

visibility可选值:

  • PRIVATE: 私有项目,仅项目成员可见
  • PUBLIC: 公开项目,所有人可读

业务规则 ​

  1. 唯一性: 项目名称全局唯一
  2. 命名空间: 同一命名空间下的类型名称必须唯一
  3. 软删除: 删除项目时设置 status='9'
  4. 权限控制: 通过 visibility 和权限表控制访问

示例数据 ​

sql
INSERT INTO kg_project_info (name, description, namespace, biz_domain_id, visibility, creator)
VALUES (
  'Medical Knowledge Graph',
  '医疗领域知识图谱',
  'medical',
  1,
  'PRIVATE',
  'admin'
);

2.3 kg_ontology_entity (本体实体类型表) ​

表名: kg_ontology_entity用途: 存储本体中所有实体类型定义,支持多版本管理

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID(版本相关)
original_idBIGINT(20)NOT NULL, DEFAULT 0原始ID(版本无关)
nameVARCHAR(255)NOT NULL, UNIQUE实体类型名称(英文)
name_zhVARCHAR(255)NOT NULL实体类型中文名称
entity_categoryVARCHAR(20)NOT NULL实体类别
layerVARCHAR(20)NULL层级: CORE/EXTENSION
descriptionVARCHAR(1024)NULL英文描述
description_zhVARCHAR(1024)NULL中文描述
with_indexVARCHAR(20)NOT NULL, DEFAULT 'TRUE'是否建索引: TRUE/FALSE
scopeVARCHAR(20)NULL作用域: PUBLIC/PRIVATE
versionINT(11)NOT NULL, DEFAULT 0版本号
version_statusVARCHAR(50)NOT NULL, DEFAULT 'ONLINE'版本状态
transformer_idBIGINT(20)NULL转换器ID
operator_configTEXTNULL操作配置(JSON)
configMEDIUMTEXTNULL扩展配置(JSON)
unique_nameVARCHAR(255)NULL唯一名称(namespace.name)
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
UNIQUE KEY uk_name (name)
UNIQUE KEY uk_original_id_version (original_id, version)
KEY idx_version_status (version_status)
KEY idx_original_id_version_status (original_id, version_status)
KEY idx_category_status (entity_category, status)

字段详解 ​

entity_category (实体类别):

值说明示例
BASIC基本类型Text, Integer, Float, Date
STANDARD标准类型Email, Phone, URL
ADVANCED高级类型(自定义)Person, Company, Product
CONCEPT_TYPE概念类型HighValueCustomer, VIPMember
EVENT_TYPE事件类型Transaction, Login, Purchase

version_status (版本状态):

值说明使用场景
ONLINE线上版本生产环境正在使用
LATEST最新版本开发中的最新版本
EFFICIENT生效版本已生效但未上线
HISTORY历史版本已下线的旧版本
DISCARDED废弃版本已废弃不再使用

版本管理机制:

Entity "Person" 的版本演进:
┌────────┬─────────────┬─────────┬────────────────┐
│ id     │ original_id │ version │ version_status │
├────────┼─────────────┼─────────┼────────────────┤
│ 1001   │ 1000        │ 1       │ HISTORY        │ ← 历史版本
│ 1002   │ 1000        │ 2       │ HISTORY        │ ← 历史版本
│ 1003   │ 1000        │ 3       │ ONLINE         │ ← 当前线上版本
│ 1004   │ 1000        │ 4       │ LATEST         │ ← 最新开发版本
└────────┴─────────────┴─────────┴────────────────┘

config (JSON格式示例):

json
{
  "icon": "person",
  "color": "#3498db",
  "display": {
    "label_property": "name",
    "title_property": "title",
    "description_property": "description"
  },
  "validation": {
    "required_properties": ["name", "id"],
    "unique_properties": ["id", "email"]
  },
  "storage": {
    "index_type": "BTREE",
    "partition": "by_year"
  },
  "business": {
    "audit_log": true,
    "data_masking": ["email", "phone"]
  }
}

业务规则 ​

  1. 版本唯一性: (original_id, version) 组合唯一
  2. 名称唯一性: name 在当前版本中唯一
  3. 版本递增: 新版本号 = MAX(version) + 1
  4. 状态转换:
    LATEST → EFFICIENT → ONLINE
             ↓
           HISTORY/DISCARDED

示例数据 ​

sql
-- 基本类型
INSERT INTO kg_ontology_entity
(original_id, name, name_zh, entity_category, layer, version_status, status)
VALUES
(1, 'Thing', '事物', 'BASIC', 'CORE', 'ONLINE', '1'),
(2, 'Text', '文本', 'BASIC', 'CORE', 'ONLINE', '1'),
(3, 'Integer', '整数', 'BASIC', 'CORE', 'ONLINE', '1');

-- 自定义类型
INSERT INTO kg_ontology_entity
(original_id, name, name_zh, entity_category, layer, description, unique_name, version_status, status)
VALUES
(1000, 'Person', '人物', 'ADVANCED', 'EXTENSION', '人物实体类型', 'medical.Person', 'ONLINE', '1'),
(1001, 'Disease', '疾病', 'ADVANCED', 'EXTENSION', '疾病实体类型', 'medical.Disease', 'ONLINE', '1');

2.4 kg_ontology_entity_parent (实体继承关系表) ​

表名: kg_ontology_entity_parent用途: 存储实体类型之间的继承关系,支持单继承和多继承

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
entity_idBIGINT(20)NOT NULL, FK子类型ID
parent_idBIGINT(20)NOT NULL, FK父类型ID(根节点为-1)
pathVARCHAR(4096)NULL继承路径
deep_inheritCHAR(1)DEFAULT 'N'是否深度继承: Y/N
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
UNIQUE KEY uk_entity_parent (entity_id, parent_id)
KEY idx_parent_id (parent_id)
KEY idx_entity_id (entity_id)

字段详解 ​

继承路径 (path): 存储从根节点到当前节点的完整路径,格式: /parent1_id/parent2_id/entity_id

示例:

Thing (id=1)
  └── Person (id=1000)
      └── Doctor (id=1010)

Doctor的path: /1/1000/1010

深度继承 (deep_inherit):

  • Y: 深度继承,继承所有祖先的属性
  • N: 浅继承,只继承直接父类的属性

继承关系图示 ​

                    Thing (根类型)
                      │
          ┌───────────┼───────────┐
          │           │           │
        Person     Product    Location
          │           │           │
    ┌─────┼─────┐     │      ┌────┼────┐
    │     │     │     │      │    │    │
 Doctor Student Customer  City Province Country

业务规则 ​

  1. 根节点: parent_id = -1 表示根节点
  2. 无循环: 不允许循环继承(A→B→A)
  3. 路径唯一: 同一子类型到同一父类型只能有一条路径
  4. 属性继承: 子类型自动继承父类型的所有属性

示例数据 ​

sql
-- Person 继承自 Thing
INSERT INTO kg_ontology_entity_parent (entity_id, parent_id, path, deep_inherit)
VALUES (1000, 1, '/1/1000', 'Y');

-- Doctor 继承自 Person
INSERT INTO kg_ontology_entity_parent (entity_id, parent_id, path, deep_inherit)
VALUES (1010, 1000, '/1/1000/1010', 'Y');

-- 多继承示例: Student 同时继承 Person 和 Learner
INSERT INTO kg_ontology_entity_parent (entity_id, parent_id, path, deep_inherit)
VALUES
(1020, 1000, '/1/1000/1020', 'Y'),  -- 继承Person
(1020, 2000, '/2000/1020', 'Y');     -- 继承Learner

2.5 kg_ontology_entity_property_range (属性范围表 - SPO三元组) ​

表名: kg_ontology_entity_property_range用途: 存储实体类型的属性定义,采用RDF三元组模型(Subject-Predicate-Object)

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
original_idBIGINT(20)NOT NULL, DEFAULT 0原始ID(版本无关)
domain_idBIGINT(20)NOT NULL, FK主体实体ID(Subject)
property_nameVARCHAR(255)NOT NULL属性名称(Predicate)
property_name_zhVARCHAR(255)NOT NULL属性中文名称
range_idBIGINT(20)NOT NULL, FK目标实体ID(Object)
property_categoryVARCHAR(20)NOT NULL属性类别
constraint_idBIGINT(20)NULL, FK约束ID
property_descVARCHAR(1024)NULL属性描述
property_desc_zhVARCHAR(1024)NULL属性中文描述
directionVARCHAR(10)NULL方向: BOTH(双向)
index_typeVARCHAR(1024)NULL索引类型
versionINT(11)NOT NULL, DEFAULT 0版本号
version_statusVARCHAR(50)DEFAULT 'ONLINE'版本状态
unique_nameVARCHAR(255)NULL唯一名称
configTEXTNULL扩展配置(JSON)
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
UNIQUE KEY uk_spo_version (domain_id, property_name, range_id, version)
KEY idx_original_id (original_id)
KEY idx_version_status (version_status)
KEY idx_property_name (property_name)
KEY idx_domain_id (domain_id)

字段详解 ​

SPO三元组模型:

Subject(主体) --Predicate(谓词)--> Object(客体)
   ↓                ↓                  ↓
domain_id      property_name       range_id

示例:
Person --name--> Text
Person --age--> Integer
Person --worksFor--> Company
Drug --treats--> Disease

property_category (属性类别):

值说明示例
PROPERTY数据属性name: Text, age: Integer
RELATION对象属性(关系)worksFor: Company, friendOf: Person

direction (方向):

  • NULL 或 FORWARD: 单向关系 A → B
  • BOTH: 双向关系 A ↔ B

index_type (索引类型):

json
{
  "type": "BTREE",           // BTREE, HASH, FULLTEXT
  "unique": false,
  "fields": ["name"],
  "analyzer": "standard"     // 全文索引分词器
}

三元组示例 ​

Person (实体类型)
  ├── name: Text              [数据属性]
  ├── age: Integer            [数据属性]
  ├── email: Text             [数据属性]
  ├── worksFor: Company       [对象属性/关系]
  └── friendOf: Person        [对象属性/关系,双向]

SPO三元组表示:
┌───────────┬───────────────┬──────────┬──────────────────┐
│ domain_id │ property_name │ range_id │ property_category│
├───────────┼───────────────┼──────────┼──────────────────┤
│ Person    │ name          │ Text     │ PROPERTY         │
│ Person    │ age           │ Integer  │ PROPERTY         │
│ Person    │ worksFor      │ Company  │ RELATION         │
│ Person    │ friendOf      │ Person   │ RELATION         │
└───────────┴───────────────┴──────────┴──────────────────┘

业务规则 ​

  1. 唯一性: (domain_id, property_name, range_id, version) 组合唯一
  2. 类型检查: range_id 必须指向有效的实体类型
  3. 版本同步: 属性版本号应与所属实体版本号同步
  4. 约束关联: constraint_id 指向属性约束表

示例数据 ​

sql
-- Person的属性定义
INSERT INTO kg_ontology_entity_property_range
(original_id, domain_id, property_name, property_name_zh, range_id, property_category, version_status)
VALUES
-- 数据属性
(5001, 1000, 'name', '姓名', 2, 'PROPERTY', 'ONLINE'),        -- Person.name: Text
(5002, 1000, 'age', '年龄', 3, 'PROPERTY', 'ONLINE'),         -- Person.age: Integer
(5003, 1000, 'email', '邮箱', 2, 'PROPERTY', 'ONLINE'),       -- Person.email: Text
-- 对象属性(关系)
(5004, 1000, 'worksFor', '工作于', 1001, 'RELATION', 'ONLINE'), -- Person.worksFor: Company
(5005, 1000, 'friendOf', '朋友', 1000, 'RELATION', 'ONLINE');   -- Person.friendOf: Person

-- Disease的属性定义
INSERT INTO kg_ontology_entity_property_range
(original_id, domain_id, property_name, property_name_zh, range_id, property_category, version_status)
VALUES
(6001, 1001, 'name', '疾病名称', 2, 'PROPERTY', 'ONLINE'),
(6002, 1001, 'icd_code', 'ICD编码', 2, 'PROPERTY', 'ONLINE'),
(6003, 1001, 'symptom', '症状', 2, 'PROPERTY', 'ONLINE');

2.6 kg_ontology_property_constraint (属性约束表) ​

表名: kg_ontology_property_constraint用途: 定义属性的约束规则,如必填、唯一、取值范围等

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
nameVARCHAR(255)NOT NULL约束名称
name_zhVARCHAR(255)NULL约束中文名称
is_requiredCHAR(1)NOT NULL, DEFAULT 'N'是否必填: Y/N
is_uniqueCHAR(1)DEFAULT 'N'是否唯一: Y/N
max_valueVARCHAR(255)NULL最大值(数值类型)
min_valueVARCHAR(255)NULL最小值(数值类型)
value_patternVARCHAR(1024)NULL正则表达式(文本类型)
is_enumCHAR(1)DEFAULT 'N'是否枚举: Y/N
enum_valueTEXTNULL枚举值(JSON数组)
is_multi_valueCHAR(1)DEFAULT 'N'是否多值: Y/N
descriptionVARCHAR(1024)NULL描述
description_zhVARCHAR(1024)NULL中文描述
configTEXTNULL扩展配置(JSON)
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
KEY idx_name (name)

约束类型说明 ​

1. 必填约束 (is_required)

json
{
  "is_required": "Y",
  "error_message": "该字段不能为空"
}

2. 唯一性约束 (is_unique)

json
{
  "is_unique": "Y",
  "scope": "global",  // global(全局唯一) 或 project(项目内唯一)
  "error_message": "该值已存在"
}

3. 数值范围约束

json
{
  "min_value": "0",
  "max_value": "120",
  "inclusive": true,  // 包含边界值
  "error_message": "年龄必须在0-120之间"
}

4. 正则表达式约束 (value_pattern)

javascript
// Email格式
"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"

// 手机号格式(中国)
"^1[3-9]\\d{9}$"

// ICD编码格式
"^[A-Z]\\d{2}(\\.\\d{1,2})?$"

5. 枚举值约束 (enum_value)

json
{
  "is_enum": "Y",
  "enum_value": [
    {"value": "MALE", "label": "男性"},
    {"value": "FEMALE", "label": "女性"},
    {"value": "OTHER", "label": "其他"}
  ]
}

6. 多值约束 (is_multi_value)

json
{
  "is_multi_value": "Y",
  "min_count": 1,
  "max_count": 10,
  "separator": ";"
}

示例数据 ​

sql
-- 必填+唯一约束
INSERT INTO kg_ontology_property_constraint
(name, name_zh, is_required, is_unique, description)
VALUES
('person_id_constraint', '人物ID约束', 'Y', 'Y', '人物ID必填且唯一');

-- 数值范围约束
INSERT INTO kg_ontology_property_constraint
(name, name_zh, is_required, min_value, max_value, description)
VALUES
('age_constraint', '年龄约束', 'N', '0', '120', '年龄范围0-120岁');

-- 正则表达式约束
INSERT INTO kg_ontology_property_constraint
(name, name_zh, value_pattern, description)
VALUES
('email_constraint', '邮箱约束',
 '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
 'Email格式验证');

-- 枚举约束
INSERT INTO kg_ontology_property_constraint
(name, name_zh, is_enum, enum_value, description)
VALUES
('gender_constraint', '性别约束', 'Y',
 '[{"value":"MALE","label":"男"},{"value":"FEMALE","label":"女"}]',
 '性别枚举值');

-- 多值约束
INSERT INTO kg_ontology_property_constraint
(name, name_zh, is_multi_value, config, description)
VALUES
('tags_constraint', '标签约束', 'Y',
 '{"min_count":1,"max_count":10,"separator":","}',
 '标签多值约束');

2.7 kg_project_entity (项目-实体关联表) ​

表名: kg_project_entity用途: 关联项目和实体类型,支持实体类型在多个项目间共享或引用

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
project_idBIGINT(20)NOT NULL, FK项目ID
entity_idBIGINT(20)NOT NULL, FK实体ID
versionINT(11)NOT NULL, DEFAULT 0版本号
version_statusVARCHAR(50)NOT NULL, DEFAULT 'ONLINE'版本状态
referencedCHAR(1)NOT NULL, DEFAULT 'N'是否引用: Y/N
statusCHAR(1)NOT NULL, DEFAULT '1'状态: 1-有效, 9-删除
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
UNIQUE KEY uk_project_entity_version (project_id, entity_id, version)
KEY idx_version_status (version_status)
KEY idx_project_id_version_status (project_id, version_status)

字段详解 ​

referenced (引用标志):

  • N: 自有实体,在本项目中定义
  • Y: 引用实体,引用自其他项目或公共库

使用场景 ​

场景1: 项目独立定义实体

医疗项目A:
  └── Disease (自有实体, referenced='N')
      └── 在项目A中定义和维护

场景2: 项目引用公共实体

公共类型库:
  └── Person (公共实体)

电商项目:
  └── Person (引用, referenced='Y')
      └── 引用自公共类型库

金融项目:
  └── Person (引用, referenced='Y')
      └── 引用自公共类型库

场景3: 项目间共享实体

项目A:
  └── Company (自有实体, referenced='N')

项目B:
  └── Company (引用, referenced='Y')
      └── 引用自项目A

业务规则 ​

  1. 唯一性: (project_id, entity_id, version) 组合唯一
  2. 引用规则: referenced='Y' 时,不允许修改实体定义
  3. 版本同步: 引用实体时,可选择引用的版本
  4. 删除保护: 被引用的实体不能删除

示例数据 ​

sql
-- 项目1 自有实体
INSERT INTO kg_project_entity (project_id, entity_id, version, version_status, referenced)
VALUES
(1, 1000, 1, 'ONLINE', 'N'),  -- Person
(1, 1001, 1, 'ONLINE', 'N');  -- Disease

-- 项目2 引用项目1的实体
INSERT INTO kg_project_entity (project_id, entity_id, version, version_status, referenced)
VALUES
(2, 1000, 1, 'ONLINE', 'Y');  -- 引用Person

2.8 kg_ontology_release (Schema发布版本表) ​

表名: kg_ontology_release用途: 管理Schema的版本发布,保存每个版本的完整快照

字段说明 ​

字段名类型约束说明
idBIGINT(20)PK, AUTO_INCREMENT主键ID
project_idBIGINT(20)NOT NULL, FK项目ID
versionINT(11)NOT NULL版本号
schema_viewMEDIUMTEXTNULLSchema快照(JSON格式)
statusVARCHAR(50)NOT NULL, DEFAULT 'DRAFT'状态
descriptionVARCHAR(1024)NULL版本描述
user_idVARCHAR(64)NULL发布用户ID
publish_timeTIMESTAMPNULL发布时间
gmt_createTIMESTAMPNOT NULL, DEFAULT CURRENT_TIMESTAMP创建时间
gmt_modifiedTIMESTAMPNOT NULL, AUTO UPDATE修改时间

索引设计 ​

sql
PRIMARY KEY (id)
UNIQUE KEY uk_project_version (project_id, version)
KEY idx_status (status)
KEY idx_project_id_status (project_id, status)

字段详解 ​

status (版本状态):

值说明操作
DRAFT草稿可编辑、删除
ONLINE线上只读,生产环境使用
HISTORY历史只读,已下线
DISCARDED废弃已废弃不再使用

状态转换流程:

DRAFT → ONLINE → HISTORY
  ↓
DISCARDED

schema_view (Schema快照) JSON格式:

json
{
  "version": 1,
  "namespace": "medical",
  "timestamp": "2025-12-15T10:00:00Z",
  "entities": [
    {
      "id": 1000,
      "name": "Person",
      "nameZh": "人物",
      "category": "ADVANCED",
      "properties": [
        {
          "name": "name",
          "nameZh": "姓名",
          "type": "Text",
          "required": true,
          "unique": false
        },
        {
          "name": "age",
          "nameZh": "年龄",
          "type": "Integer",
          "min": 0,
          "max": 120
        }
      ],
      "parents": ["Thing"],
      "indexes": ["name"]
    },
    {
      "id": 1001,
      "name": "Disease",
      "nameZh": "疾病",
      "category": "ADVANCED",
      "properties": [
        {
          "name": "name",
          "nameZh": "疾病名称",
          "type": "Text",
          "required": true
        },
        {
          "name": "icd_code",
          "nameZh": "ICD编码",
          "type": "Text",
          "pattern": "^[A-Z]\\d{2}(\\.\\d{1,2})?$"
        }
      ]
    }
  ],
  "relations": [
    {
      "name": "treats",
      "nameZh": "治疗",
      "subjectType": "Drug",
      "objectType": "Disease",
      "properties": [
        {
          "name": "effectiveness",
          "nameZh": "有效性",
          "type": "Float",
          "min": 0.0,
          "max": 1.0
        }
      ]
    }
  ],
  "constraints": [
    {
      "id": 1,
      "name": "person_id_unique",
      "type": "unique",
      "entity": "Person",
      "property": "id"
    }
  ]
}

版本管理流程 ​

1. 创建草稿版本

sql
INSERT INTO kg_ontology_release (project_id, version, status, description, user_id)
VALUES (1, 1, 'DRAFT', '初始版本', 'admin');

2. 发布版本

sql
-- 更新当前版本为线上
UPDATE kg_ontology_release
SET status = 'ONLINE',
    publish_time = NOW()
WHERE project_id = 1 AND version = 1;

-- 将旧版本设为历史
UPDATE kg_ontology_release
SET status = 'HISTORY'
WHERE project_id = 1 AND version < 1 AND status = 'ONLINE';

3. 回滚版本

sql
-- 下线当前版本
UPDATE kg_ontology_release
SET status = 'HISTORY'
WHERE project_id = 1 AND version = 2 AND status = 'ONLINE';

-- 重新激活旧版本
UPDATE kg_ontology_release
SET status = 'ONLINE',
    publish_time = NOW()
WHERE project_id = 1 AND version = 1 AND status = 'HISTORY';

业务规则 ​

  1. 版本递增: 新版本号 = MAX(version) + 1
  2. 唯一线上版本: 同一项目同时只能有一个ONLINE版本
  3. 快照完整性: schema_view 必须包含完整的Schema定义
  4. 不可篡改: ONLINE和HISTORY状态的版本不可修改

示例数据 ​

sql
INSERT INTO kg_ontology_release
(project_id, version, schema_view, status, description, user_id, publish_time)
VALUES
(1, 1,
 '{"version":1,"namespace":"medical","entities":[...],"relations":[...]}',
 'HISTORY',
 '初始版本',
 'admin',
 '2025-01-01 10:00:00'),

(1, 2,
 '{"version":2,"namespace":"medical","entities":[...],"relations":[...]}',
 'ONLINE',
 '增加疾病类型',
 'admin',
 '2025-12-15 10:00:00');

三、数据模型关系 ​

3.1 ER关系图 ​

┌─────────────────┐
│  kg_biz_domain  │ 业务域
└────────┬────────┘
         │ 1
         │
         │ N
┌────────┴────────┐
│kg_project_info  │ 项目
└────────┬────────┘
         │ 1
         ├────────────────────────────┐
         │ N                          │ 1
┌────────┴────────┐          ┌────────┴──────────┐
│kg_project_entity│          │kg_ontology_release│
│  (项目实体关联)  │          │  (版本发布)        │
└────────┬────────┘          └───────────────────┘
         │ N
         │
         │ 1
┌────────┴───────────┐
│kg_ontology_entity  │ 实体类型
└────────┬───────────┘
         │ 1
         ├───────────────────────┐
         │ N                     │ N
┌────────┴────────────────┐  ┌──┴─────────────────────┐
│kg_ontology_entity_parent│  │kg_ontology_property    │
│     (继承关系)           │  │    _range (SPO三元组)  │
└─────────────────────────┘  └──┬─────────────────────┘
                                │ N
                                │
                                │ 1
                     ┌──────────┴──────────────────┐
                     │kg_ontology_property         │
                     │   _constraint (属性约束)    │
                     └─────────────────────────────┘

3.2 核心关系说明 ​

关系1: 业务域 → 项目 (1:N) ​

sql
SELECT d.name as domain_name, p.name as project_name
FROM kg_biz_domain d
LEFT JOIN kg_project_info p ON d.id = p.biz_domain_id
WHERE d.status = '1' AND p.status = '1';

关系2: 项目 → 实体 (N:M, 通过kg_project_entity) ​

sql
SELECT p.name as project_name, e.name as entity_name
FROM kg_project_info p
INNER JOIN kg_project_entity pe ON p.id = pe.project_id
INNER JOIN kg_ontology_entity e ON pe.entity_id = e.id
WHERE p.status = '1' AND e.status = '1' AND pe.status = '1';

关系3: 实体 → 属性 (1:N) ​

sql
SELECT e.name as entity_name,
       pr.property_name,
       r.name as range_type
FROM kg_ontology_entity e
INNER JOIN kg_ontology_entity_property_range pr ON e.id = pr.domain_id
INNER JOIN kg_ontology_entity r ON pr.range_id = r.id
WHERE e.status = '1' AND pr.status = '1';

关系4: 实体 → 父类 (N:M) ​

sql
SELECT child.name as child_entity,
       parent.name as parent_entity,
       ep.path
FROM kg_ontology_entity child
INNER JOIN kg_ontology_entity_parent ep ON child.id = ep.entity_id
INNER JOIN kg_ontology_entity parent ON ep.parent_id = parent.id
WHERE ep.status = '1';

3.3 完整的Schema查询 ​

查询项目的完整Schema(包含所有实体、属性、继承关系):

sql
SELECT
    p.name as project_name,
    e.name as entity_name,
    e.name_zh as entity_name_zh,
    pr.property_name,
    pr.property_name_zh,
    r.name as property_type,
    c.is_required,
    c.is_unique,
    parent.name as parent_entity
FROM kg_project_info p
INNER JOIN kg_project_entity pe ON p.id = pe.project_id
INNER JOIN kg_ontology_entity e ON pe.entity_id = e.id
LEFT JOIN kg_ontology_entity_property_range pr ON e.id = pr.domain_id AND pr.status = '1'
LEFT JOIN kg_ontology_entity r ON pr.range_id = r.id
LEFT JOIN kg_ontology_property_constraint c ON pr.constraint_id = c.id
LEFT JOIN kg_ontology_entity_parent ep ON e.id = ep.entity_id AND ep.status = '1'
LEFT JOIN kg_ontology_entity parent ON ep.parent_id = parent.id
WHERE p.id = 1
  AND p.status = '1'
  AND pe.status = '1'
  AND e.status = '1'
  AND pe.version_status = 'ONLINE'
ORDER BY e.name, pr.property_name;

四、代码示例 ​

4.1 Entity类示例 ​

KgProjectInfo.java (完整代码) ​

java
package com.aroundix.spg.api.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 知识图谱项目信息表
 *
 * @author Aroundix SPG Team
 * @since 2025-12-15
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("kg_project_info")
@Schema(description = "知识图谱项目信息")
public class KgProjectInfo extends Model<KgProjectInfo> implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    @Schema(description = "主键ID")
    private Long id;

    @Schema(description = "项目名称")
    private String name;

    @Schema(description = "项目描述")
    private String description;

    @Schema(description = "命名空间")
    private String namespace;

    @Schema(description = "业务域ID")
    private Long bizDomainId;

    @Schema(description = "项目配置(JSON格式)")
    private String config;

    @Schema(description = "可见性(PRIVATE/PUBLIC)")
    private String visibility;

    @Schema(description = "状态(1-有效,9-删除)")
    private String status;

    @TableField(fill = FieldFill.INSERT)
    @Schema(description = "创建时间")
    private LocalDateTime gmtCreate;

    @TableField(fill = FieldFill.UPDATE)
    @Schema(description = "修改时间")
    private LocalDateTime gmtModified;

    @TableField(fill = FieldFill.INSERT)
    @Schema(description = "创建人")
    private String creator;

    @TableField(fill = FieldFill.UPDATE)
    @Schema(description = "修改人")
    private String modifier;

}

4.2 Mapper接口示例 ​

KgOntologyEntityMapper.java (完整代码) ​

java
package com.aroundix.spg.mapper;

import com.aroundix.spg.api.entity.KgOntologyEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 本体实体类型表 Mapper接口
 *
 * @author Aroundix SPG Team
 * @since 2025-12-15
 */
@Mapper
public interface KgOntologyEntityMapper extends BaseMapper<KgOntologyEntity> {

    /**
     * 根据实体名称查询实体
     *
     * @param name 实体名称
     * @return 实体信息
     */
    KgOntologyEntity selectByName(@Param("name") String name);

    /**
     * 根据唯一名称查询实体
     *
     * @param uniqueName 唯一名称(namespace.name)
     * @return 实体信息
     */
    KgOntologyEntity selectByUniqueName(@Param("uniqueName") String uniqueName);

    /**
     * 根据原始ID和版本状态查询实体
     *
     * @param originalId 原始ID
     * @param versionStatus 版本状态
     * @return 实体信息
     */
    KgOntologyEntity selectByOriginalIdAndStatus(
        @Param("originalId") Long originalId,
        @Param("versionStatus") String versionStatus
    );

    /**
     * 根据实体类别查询实体列表
     *
     * @param entityCategory 实体类别
     * @return 实体列表
     */
    List<KgOntologyEntity> selectByCategory(@Param("entityCategory") String entityCategory);

    /**
     * 根据版本状态查询实体列表
     *
     * @param versionStatus 版本状态
     * @return 实体列表
     */
    List<KgOntologyEntity> selectByVersionStatus(@Param("versionStatus") String versionStatus);

    /**
     * 批量插入实体
     *
     * @param entities 实体列表
     * @return 插入数量
     */
    int batchInsert(@Param("entities") List<KgOntologyEntity> entities);

}

4.3 MyBatis XML示例 ​

KgOntologyEntityMapper.xml (完整代码) ​

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aroundix.spg.mapper.KgOntologyEntityMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="baseResultMap" type="com.aroundix.spg.api.entity.KgOntologyEntity">
        <id column="id" property="id"/>
        <result column="original_id" property="originalId"/>
        <result column="name" property="name"/>
        <result column="name_zh" property="nameZh"/>
        <result column="entity_category" property="entityCategory"/>
        <result column="layer" property="layer"/>
        <result column="description" property="description"/>
        <result column="description_zh" property="descriptionZh"/>
        <result column="with_index" property="withIndex"/>
        <result column="scope" property="scope"/>
        <result column="version" property="version"/>
        <result column="version_status" property="versionStatus"/>
        <result column="transformer_id" property="transformerId"/>
        <result column="operator_config" property="operatorConfig"/>
        <result column="config" property="config"/>
        <result column="unique_name" property="uniqueName"/>
        <result column="status" property="status"/>
        <result column="gmt_create" property="gmtCreate"/>
        <result column="gmt_modified" property="gmtModified"/>
    </resultMap>

    <!-- 根据实体名称查询实体 -->
    <select id="selectByName" resultMap="baseResultMap">
        SELECT * FROM kg_ontology_entity
        WHERE name = #{name} AND status = '1'
        LIMIT 1
    </select>

    <!-- 根据唯一名称查询实体 -->
    <select id="selectByUniqueName" resultMap="baseResultMap">
        SELECT * FROM kg_ontology_entity
        WHERE unique_name = #{uniqueName} AND status = '1'
        LIMIT 1
    </select>

    <!-- 根据原始ID和版本状态查询实体 -->
    <select id="selectByOriginalIdAndStatus" resultMap="baseResultMap">
        SELECT * FROM kg_ontology_entity
        WHERE original_id = #{originalId}
          AND version_status = #{versionStatus}
          AND status = '1'
        LIMIT 1
    </select>

    <!-- 根据实体类别查询实体列表 -->
    <select id="selectByCategory" resultMap="baseResultMap">
        SELECT * FROM kg_ontology_entity
        WHERE entity_category = #{entityCategory} AND status = '1'
        ORDER BY gmt_create DESC
    </select>

    <!-- 根据版本状态查询实体列表 -->
    <select id="selectByVersionStatus" resultMap="baseResultMap">
        SELECT * FROM kg_ontology_entity
        WHERE version_status = #{versionStatus} AND status = '1'
        ORDER BY gmt_create DESC
    </select>

    <!-- 批量插入实体 -->
    <insert id="batchInsert">
        INSERT INTO kg_ontology_entity (
            original_id, name, name_zh, entity_category, layer,
            description, description_zh, with_index, scope, version,
            version_status, transformer_id, operator_config, config,
            unique_name, status, gmt_create, gmt_modified
        ) VALUES
        <foreach collection="entities" item="item" separator=",">
            (
                #{item.originalId}, #{item.name}, #{item.nameZh},
                #{item.entityCategory}, #{item.layer}, #{item.description},
                #{item.descriptionZh}, #{item.withIndex}, #{item.scope},
                #{item.version}, #{item.versionStatus}, #{item.transformerId},
                #{item.operatorConfig}, #{item.config}, #{item.uniqueName},
                #{item.status}, NOW(), NOW()
            )
        </foreach>
    </insert>

</mapper>

4.4 Service层示例 ​

ProjectService接口 ​

java
package com.aroundix.spg.service;

import com.aroundix.spg.api.entity.KgProjectInfo;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * 项目管理服务
 */
public interface ProjectService extends IService<KgProjectInfo> {

    /**
     * 创建项目
     */
    Long createProject(String name, String namespace, Long bizDomainId, String creator);

    /**
     * 根据名称查询项目
     */
    KgProjectInfo getByName(String name);

    /**
     * 删除项目(软删除)
     */
    boolean deleteProject(Long projectId);

}

ProjectServiceImpl实现 ​

java
package com.aroundix.spg.service.impl;

import com.aroundix.spg.api.entity.KgProjectInfo;
import com.aroundix.spg.mapper.KgProjectInfoMapper;
import com.aroundix.spg.service.ProjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 项目管理服务实现
 */
@Service
public class ProjectServiceImpl
    extends ServiceImpl<KgProjectInfoMapper, KgProjectInfo>
    implements ProjectService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProject(String name, String namespace, Long bizDomainId, String creator) {
        KgProjectInfo project = new KgProjectInfo();
        project.setName(name);
        project.setNamespace(namespace);
        project.setBizDomainId(bizDomainId);
        project.setCreator(creator);
        project.setStatus("1");

        this.save(project);
        return project.getId();
    }

    @Override
    public KgProjectInfo getByName(String name) {
        return this.baseMapper.selectByName(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteProject(Long projectId) {
        KgProjectInfo project = this.getById(projectId);
        if (project != null) {
            project.setStatus("9");
            return this.updateById(project);
        }
        return false;
    }

}

4.5 Controller层示例 ​

java
package com.aroundix.spg.controller;

import com.aroundix.spg.api.entity.KgProjectInfo;
import com.aroundix.spg.service.ProjectService;
import com.pig4cloud.pigx.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

/**
 * 项目管理控制器
 */
@RestController
@RequestMapping("/project")
@RequiredArgsConstructor
@Tag(name = "项目管理", description = "知识图谱项目管理接口")
public class ProjectController {

    private final ProjectService projectService;

    @PostMapping
    @Operation(summary = "创建项目")
    public R<Long> createProject(@RequestBody CreateProjectRequest request) {
        Long projectId = projectService.createProject(
            request.getName(),
            request.getNamespace(),
            request.getBizDomainId(),
            request.getCreator()
        );
        return R.ok(projectId);
    }

    @GetMapping("/{id}")
    @Operation(summary = "查询项目详情")
    public R<KgProjectInfo> getProject(@PathVariable Long id) {
        KgProjectInfo project = projectService.getById(id);
        return R.ok(project);
    }

    @GetMapping("/by-name/{name}")
    @Operation(summary = "根据名称查询项目")
    public R<KgProjectInfo> getProjectByName(@PathVariable String name) {
        KgProjectInfo project = projectService.getByName(name);
        return R.ok(project);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除项目")
    public R<Boolean> deleteProject(@PathVariable Long id) {
        boolean result = projectService.deleteProject(id);
        return R.ok(result);
    }

}

4.6 使用示例 ​

示例1: 创建项目并添加实体 ​

java
@Service
@RequiredArgsConstructor
public class SchemaManagementService {

    private final ProjectService projectService;
    private final EntityService entityService;

    /**
     * 创建医疗项目并初始化Schema
     */
    @Transactional(rollbackFor = Exception.class)
    public void createMedicalProject() {
        // 1. 创建项目
        Long projectId = projectService.createProject(
            "Medical KG",
            "medical",
            1L,
            "admin"
        );

        // 2. 创建Disease实体类型
        KgOntologyEntity disease = new KgOntologyEntity();
        disease.setOriginalId(1001L);
        disease.setName("Disease");
        disease.setNameZh("疾病");
        disease.setEntityCategory("ADVANCED");
        disease.setLayer("EXTENSION");
        disease.setUniqueName("medical.Disease");
        disease.setVersionStatus("ONLINE");
        disease.setStatus("1");
        entityService.save(disease);

        // 3. 关联项目和实体
        KgProjectEntity projectEntity = new KgProjectEntity();
        projectEntity.setProjectId(projectId);
        projectEntity.setEntityId(disease.getId());
        projectEntity.setVersion(1);
        projectEntity.setVersionStatus("ONLINE");
        projectEntity.setReferenced("N");
        projectEntity.setStatus("1");
        projectEntityService.save(projectEntity);

        // 4. 添加属性
        addProperty(disease.getId(), "name", "疾病名称", 2L, "PROPERTY");
        addProperty(disease.getId(), "icd_code", "ICD编码", 2L, "PROPERTY");
    }

    private void addProperty(Long domainId, String propertyName,
                           String propertyNameZh, Long rangeId,
                           String category) {
        KgOntologyPropertyRange property = new KgOntologyPropertyRange();
        property.setDomainId(domainId);
        property.setPropertyName(propertyName);
        property.setPropertyNameZh(propertyNameZh);
        property.setRangeId(rangeId);
        property.setPropertyCategory(category);
        property.setVersionStatus("ONLINE");
        property.setStatus("1");
        propertyRangeService.save(property);
    }

}

示例2: 查询完整Schema ​

java
@Service
@RequiredArgsConstructor
public class SchemaQueryService {

    private final EntityService entityService;
    private final PropertyRangeService propertyRangeService;

    /**
     * 查询项目的完整Schema
     */
    public ProjectSchema getProjectSchema(Long projectId) {
        ProjectSchema schema = new ProjectSchema();

        // 1. 查询项目的所有实体
        List<KgOntologyEntity> entities = entityService.getByProjectId(projectId);

        for (KgOntologyEntity entity : entities) {
            EntitySchema entitySchema = new EntitySchema();
            entitySchema.setName(entity.getName());
            entitySchema.setNameZh(entity.getNameZh());
            entitySchema.setCategory(entity.getEntityCategory());

            // 2. 查询实体的所有属性
            List<KgOntologyPropertyRange> properties =
                propertyRangeService.getByDomainId(entity.getId());

            for (KgOntologyPropertyRange property : properties) {
                PropertySchema propSchema = new PropertySchema();
                propSchema.setName(property.getPropertyName());
                propSchema.setNameZh(property.getPropertyNameZh());
                propSchema.setType(getTypeName(property.getRangeId()));
                propSchema.setCategory(property.getPropertyCategory());

                entitySchema.addProperty(propSchema);
            }

            schema.addEntity(entitySchema);
        }

        return schema;
    }

}

示例3: 发布新版本 ​

java
@Service
@RequiredArgsConstructor
public class VersionManagementService {

    private final OntologyReleaseService releaseService;
    private final EntityService entityService;

    /**
     * 发布新版本
     */
    @Transactional(rollbackFor = Exception.class)
    public void publishNewVersion(Long projectId, String description, String userId) {
        // 1. 获取最新版本号
        Integer maxVersion = releaseService.getMaxVersion(projectId);
        Integer newVersion = (maxVersion == null ? 1 : maxVersion + 1);

        // 2. 生成Schema快照
        String schemaView = generateSchemaSnapshot(projectId);

        // 3. 创建发布记录
        KgOntologyRelease release = new KgOntologyRelease();
        release.setProjectId(projectId);
        release.setVersion(newVersion);
        release.setSchemaView(schemaView);
        release.setStatus("ONLINE");
        release.setDescription(description);
        release.setUserId(userId);
        release.setPublishTime(LocalDateTime.now());
        releaseService.save(release);

        // 4. 将旧版本设为历史
        releaseService.markAsHistory(projectId, newVersion);
    }

    private String generateSchemaSnapshot(Long projectId) {
        // 查询完整Schema并序列化为JSON
        ProjectSchema schema = schemaQueryService.getProjectSchema(projectId);
        return JSON.toJSONString(schema);
    }

}

五、使用场景 ​

5.1 场景1: 医疗知识图谱 ​

需求: 构建医疗领域知识图谱,包括疾病、药物、症状等实体

Schema设计:

json
{
  "namespace": "medical",
  "entities": [
    {
      "name": "Disease",
      "nameZh": "疾病",
      "properties": [
        {"name": "name", "type": "Text", "required": true},
        {"name": "icd_code", "type": "Text"},
        {"name": "symptoms", "type": "Text", "multiValue": true}
      ]
    },
    {
      "name": "Drug",
      "nameZh": "药物",
      "properties": [
        {"name": "name", "type": "Text", "required": true},
        {"name": "approval_date", "type": "Date"}
      ]
    }
  ],
  "relations": [
    {
      "name": "treats",
      "nameZh": "治疗",
      "subjectType": "Drug",
      "objectType": "Disease",
      "properties": [
        {"name": "effectiveness", "type": "Float"}
      ]
    }
  ]
}

5.2 场景2: 企业组织架构图谱 ​

需求: 管理企业的人员、部门、项目等关系

Schema设计:

json
{
  "namespace": "enterprise",
  "entities": [
    {
      "name": "Employee",
      "nameZh": "员工",
      "properties": [
        {"name": "name", "type": "Text", "required": true},
        {"name": "email", "type": "Text", "unique": true},
        {"name": "phone", "type": "Text"}
      ]
    },
    {
      "name": "Department",
      "nameZh": "部门",
      "properties": [
        {"name": "name", "type": "Text", "required": true},
        {"name": "code", "type": "Text", "unique": true}
      ]
    }
  ],
  "relations": [
    {
      "name": "worksIn",
      "nameZh": "所属部门",
      "subjectType": "Employee",
      "objectType": "Department"
    },
    {
      "name": "manages",
      "nameZh": "管理",
      "subjectType": "Employee",
      "objectType": "Employee"
    }
  ]
}

5.3 场景3: 电商商品图谱 ​

需求: 构建商品、品牌、类目等关系图谱

Schema设计:

json
{
  "namespace": "ecommerce",
  "entities": [
    {
      "name": "Product",
      "nameZh": "商品",
      "properties": [
        {"name": "title", "type": "Text", "required": true},
        {"name": "price", "type": "Float", "min": 0},
        {"name": "stock", "type": "Integer", "min": 0}
      ]
    },
    {
      "name": "Brand",
      "nameZh": "品牌",
      "properties": [
        {"name": "name", "type": "Text", "required": true, "unique": true},
        {"name": "country", "type": "Text"}
      ]
    },
    {
      "name": "Category",
      "nameZh": "类目",
      "properties": [
        {"name": "name", "type": "Text", "required": true}
      ]
    }
  ],
  "relations": [
    {
      "name": "belongsToBrand",
      "nameZh": "所属品牌",
      "subjectType": "Product",
      "objectType": "Brand"
    },
    {
      "name": "inCategory",
      "nameZh": "所属类目",
      "subjectType": "Product",
      "objectType": "Category"
    }
  ]
}

六、性能优化 ​

6.1 索引优化 ​

已创建的核心索引:

sql
-- kg_ontology_entity
CREATE INDEX idx_version_status ON kg_ontology_entity(version_status);
CREATE INDEX idx_original_id_version_status ON kg_ontology_entity(original_id, version_status);

-- kg_ontology_entity_property_range
CREATE INDEX idx_domain_id ON kg_ontology_entity_property_range(domain_id);
CREATE INDEX idx_property_name ON kg_ontology_entity_property_range(property_name);

-- kg_project_entity
CREATE INDEX idx_project_id_version_status ON kg_project_entity(project_id, version_status);

建议添加的索引(根据实际查询模式):

sql
-- 如果经常按类别查询实体
CREATE INDEX idx_category_status ON kg_ontology_entity(entity_category, status);

-- 如果经常查询实体的关系属性
CREATE INDEX idx_domain_category ON kg_ontology_entity_property_range(domain_id, property_category);

6.2 查询优化 ​

优化1: 使用覆盖索引

sql
-- 不好的查询
SELECT * FROM kg_ontology_entity WHERE version_status = 'ONLINE';

-- 好的查询(只查询需要的字段)
SELECT id, name, name_zh, entity_category
FROM kg_ontology_entity
WHERE version_status = 'ONLINE';

优化2: 分页查询

sql
-- 使用LIMIT减少数据量
SELECT * FROM kg_ontology_entity
WHERE entity_category = 'ADVANCED'
ORDER BY gmt_create DESC
LIMIT 20 OFFSET 0;

优化3: 批量操作

java
// 不好的做法: 循环插入
for (KgOntologyEntity entity : entities) {
    entityMapper.insert(entity);
}

// 好的做法: 批量插入
entityMapper.batchInsert(entities);

6.3 缓存策略 ​

策略1: Schema缓存

java
@Cacheable(value = "schema", key = "#projectId + '_' + #version")
public ProjectSchema getSchema(Long projectId, Integer version) {
    // 查询Schema
}

@CacheEvict(value = "schema", key = "#projectId + '_*'")
public void publishSchema(Long projectId) {
    // 发布新版本,清除缓存
}

策略2: 实体类型缓存

java
@Cacheable(value = "entity", key = "#name")
public KgOntologyEntity getEntityByName(String name) {
    return entityMapper.selectByName(name);
}

6.4 数据库连接池配置 ​

application.yml:

yaml
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 10
      min-idle: 10
      max-active: 100
      max-wait: 60000
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false

七、总结 ​

7.1 核心特性 ​

✅ 多版本管理: 支持Schema的多版本并存,方便回滚和灰度发布 ✅ SPO三元组: 采用RDF风格的三元组模型,灵活表达复杂关系 ✅ 继承体系: 支持实体类型的单继承和多继承 ✅ 约束系统: 完善的属性约束机制(必填、唯一、范围、正则、枚举) ✅ 项目隔离: 多项目支持,数据完全隔离 ✅ Schema快照: 每个版本保存完整快照,保证数据一致性

7.2 技术亮点 ​

🔹 遵循muotai规范: 完全兼容现有微服务架构 🔹 双数据库架构: MySQL存元数据,Neo4j存图数据 🔹 完整的审计: 所有表都有创建时间、修改时间、创建人、修改人 🔹 软删除机制: 删除数据不物理删除,便于恢复 🔹 JSON扩展字段: 预留config字段,支持未来扩展

7.3 使用建议 ​

  1. 初始化顺序: 业务域 → 项目 → 实体类型 → 属性 → 约束 → 发布版本
  2. 版本管理: 开发环境使用LATEST版本,生产环境使用ONLINE版本
  3. 性能优化: 合理使用索引,启用Redis缓存,使用批量操作
  4. 数据一致性: 关键操作使用事务,Schema发布前做完整性校验
  5. 监控告警: 监控数据库慢查询,及时优化SQL

文档版本: v1.0 最后更新: 2025-12-15 维护团队: Aroundix SPG Team 联系方式: spg-support@aroundix.com