返回博客

InterfaceType 与 StructType:类型系统高级特性

场景:多种实体都有"地理位置"

Coomia发布于 2025年8月10日17 分钟阅读
分享本文Twitter / X

InterfaceType 与 StructType:类型系统高级特性

系列:S4 本体建模 · 第 6 篇 | 难度:中级 | 阅读时间:18 分钟

#TL;DR

  • InterfaceType 让 Ontology 拥有面向对象的"接口继承"能力——多个 ObjectType 可以实现同一个 Interface,支持多态查询("查所有可定位的对象"而不用关心是设备、仓库还是车辆)。
  • StructType 是轻量级的"值对象"——不像 ObjectType 有独立身份和生命周期,Struct 是嵌入在属性中的复合数据结构,支持多层嵌套,适合地址、坐标、联系人信息等场景。
  • 接口继承 + 结构体嵌套 + 多态查询三者协同,让 Ontology 的表达力从简单的"表→行→列"跃升到类型安全的领域建模。

#1. 为什么需要 InterfaceType

#1.1 问题:类型之间的共性如何表达?

Code
场景:多种实体都有"地理位置"

┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│ Equipment│  │ Warehouse│  │ Vehicle  │  │ Employee │
│          │  │          │  │          │  │          │
│ lat: 31.2│  │ lat: 39.9│  │ lat: 22.3│  │ lat: 30.6│
│ lng: 121 │  │ lng: 116 │  │ lng: 114 │  │ lng: 104 │
│ address  │  │ address  │  │ address  │  │ address  │
└──────────┘  └──────────┘  └──────────┘  └──────────┘

问题:
├── 如何查询"距离我 10 公里内的所有可定位对象"?
├── 传统做法:分别查 4 张表 → UNION ALL → 客户端合并
├── 如果新增了 ObjectType(如 Sensor),查询逻辑又要改
└── 没有办法在 Schema 层面表达"这些类型有共同的能力"

解决:InterfaceType

┌──────────────────────────────────┐
│    InterfaceType: Locatable      │
│                                  │
│    properties:                   │
│    ├── latitude:  DOUBLE         │
│    ├── longitude: DOUBLE         │
│    └── address:   STRING         │
│                                  │
│    implementedBy:                │
│    ├── Equipment                 │
│    ├── Warehouse                 │
│    ├── Vehicle                   │
│    └── Employee                  │
└──────────────────────────────────┘

现在可以:
  client.objects.search("Locatable", filters={"nearPoint": ...})
  → 自动跨所有实现类查询,返回混合结果

#1.2 InterfaceType vs 传统继承

Code
┌────────────────┬───────────────────────┬─────────────────────┐
│                │  传统 OOP 继承          │  InterfaceType       │
├────────────────┼───────────────────────┼─────────────────────┤
│  多继承        │  通常不支持/菱形问题    │  ✅ 一个类型可实现    │
│                │                       │     多个 Interface    │
├────────────────┼───────────────────────┼─────────────────────┤
│  数据存储      │  通常映射到表继承       │  各 ObjectType 独立  │
│                │  (STI/MTI)            │  存储,无共享表       │
├────────────────┼───────────────────────┼─────────────────────┤
│  查询方式      │  查父类表              │  多态查询自动聚合     │
│                │                       │  各实现类结果         │
├────────────────┼───────────────────────┼─────────────────────┤
│  运行时耦合    │  紧耦合               │  松耦合              │
│                │                       │  Interface 变更不影响│
│                │                       │  实现类存储          │
└────────────────┴───────────────────────┴─────────────────────┘

#2. InterfaceType 数据模型

#2.1 定义 Interface

Python
from ontology_sdk import OntologyClient

client = OntologyClient(base_url="http://localhost:8080")

# 创建 InterfaceType
interface = client.schema.create_interface_type({
    "apiName": "Locatable",
    "displayName": "可定位",
    "description": "表示具有地理位置的实体",

    # 接口定义的属性(实现类必须具备)
    "properties": {
        "latitude": {
            "type": "DOUBLE",
            "required": True,
            "description": "纬度",
            "validations": [
                {"rule": "min", "value": -90},
                {"rule": "max", "value": 90},
            ],
        },
        "longitude": {
            "type": "DOUBLE",
            "required": True,
            "description": "经度",
            "validations": [
                {"rule": "min", "value": -180},
                {"rule": "max", "value": 180},
            ],
        },
        "address": {
            "type": "STRING",
            "required": False,
            "description": "人类可读地址",
        },
    },

    # 接口定义的方法/操作(可选)
    "actions": [
        {
            "apiName": "updateLocation",
            "parameters": {
                "newLatitude": {"type": "DOUBLE", "required": True},
                "newLongitude": {"type": "DOUBLE", "required": True},
            },
        },
    ],
})

#2.2 ObjectType 实现 Interface

Python
# 让 Equipment 实现 Locatable 接口
client.schema.create_object_type({
    "name": "Equipment",
    "primaryKey": "equipmentId",

    # 声明实现的接口列表
    "implements": ["Locatable", "Auditable", "Maintainable"],

    "properties": {
        "equipmentId": {"type": "STRING", "required": True},
        "name": {"type": "STRING", "required": True},
        "model": {"type": "STRING"},

        # Locatable 接口要求的属性
        "latitude": {"type": "DOUBLE", "required": True},
        "longitude": {"type": "DOUBLE", "required": True},
        "address": {"type": "STRING"},

        # Auditable 接口要求的属性
        "createdAt": {"type": "TIMESTAMP", "required": True},
        "updatedAt": {"type": "TIMESTAMP", "required": True},
        "createdBy": {"type": "STRING", "required": True},

        # Maintainable 接口要求的属性
        "lastMaintenanceDate": {"type": "DATE"},
        "nextMaintenanceDate": {"type": "DATE"},
        "maintenanceStatus": {"type": "ENUM", "enumValues": ["NORMAL", "DUE", "OVERDUE"]},

        # Equipment 自己的属性
        "serialNumber": {"type": "STRING"},
        "purchaseDate": {"type": "DATE"},
        "warrantyExpiry": {"type": "DATE"},
    },
})

#2.3 接口合规性检查

Python
# 系统自动验证 ObjectType 是否满足 Interface 的所有要求
try:
    client.schema.create_object_type({
        "name": "Sensor",
        "primaryKey": "sensorId",
        "implements": ["Locatable"],
        "properties": {
            "sensorId": {"type": "STRING", "required": True},
            "latitude": {"type": "DOUBLE", "required": True},
            # 缺少 longitude!
        },
    })
except InterfaceComplianceError as e:
    print(f"接口合规性检查失败: {e}")
    # "ObjectType 'Sensor' does not satisfy interface 'Locatable':
    #  Missing required property: longitude (DOUBLE)"
    print(f"缺失属性: {e.missing_properties}")
    print(f"类型不匹配: {e.type_mismatches}")

#3. 多态查询

#3.1 基于 Interface 的跨类型查询

Python
# 查询所有实现了 Locatable 接口的对象
# 无需知道具体有哪些 ObjectType
results = client.objects.search_by_interface("Locatable", {
    "filters": {
        "nearPoint": {
            "latitude": 31.23,
            "longitude": 121.47,
            "radiusKm": 10,
        },
    },
    "orderBy": "distance",
    "maxResults": 50,
})

for obj in results:
    print(f"[{obj.object_type}] {obj.display_name}")
    print(f"  位置: ({obj.latitude}, {obj.longitude})")
    print(f"  距离: {obj.distance_km:.1f} km")

# 输出示例:
# [Equipment] CNC-001 数控机床
#   位置: (31.24, 121.48)
#   距离: 1.2 km
# [Warehouse] 浦东仓库
#   位置: (31.22, 121.50)
#   距离: 2.8 km
# [Vehicle] 沪A-12345 运输车
#   位置: (31.20, 121.45)
#   距离: 3.5 km

#3.2 多态查询的执行原理

Code
多态查询执行流程:

1. 解析 Interface
   ┌─────────────────┐
   │  Locatable      │
   │  ├── Equipment  │
   │  ├── Warehouse  │
   │  ├── Vehicle    │
   │  └── Employee   │
   └─────────────────┘

2. 并行查询各实现类(Fan-out)
   ┌─────────────┐
   │ Equipment   │──── Query with filters ──── Results[0..n]
   │ Warehouse   │──── Query with filters ──── Results[0..m]
   │ Vehicle     │──── Query with filters ──── Results[0..k]
   │ Employee    │──── Query with filters ──── Results[0..j]
   └─────────────┘

3. 合并排序(Fan-in)
   Results[0..n] ─┐
   Results[0..m] ─┼── Merge Sort by distance ── Final Results
   Results[0..k] ─┤
   Results[0..j] ─┘

性能特征:
├── 并行度 = 实现类数量(通常 3-10 个)
├── 响应时间 ≈ 最慢的实现类查询时间
├── 结果数量 = 各实现类结果之和(受 maxResults 限制)
└── 自动优化:如果某实现类不可能满足过滤条件,跳过查询

#3.3 Interface 继承

Python
# InterfaceType 也可以继承其他 InterfaceType
client.schema.create_interface_type({
    "apiName": "TrackableAsset",
    "displayName": "可追踪资产",

    # 继承 Locatable(拥有位置属性)
    "extends": ["Locatable"],

    # 额外的属性
    "properties": {
        "assetTag": {
            "type": "STRING",
            "required": True,
            "description": "资产标签编号",
        },
        "assetValue": {
            "type": "DOUBLE",
            "required": True,
            "description": "资产价值(元)",
        },
        "depreciationRate": {
            "type": "DOUBLE",
            "description": "年折旧率",
        },
    },
})

# Equipment 同时满足 Locatable 和 TrackableAsset
# 查询 TrackableAsset 时也能找到 Equipment

#4. StructType:值对象建模

#4.1 为什么需要 StructType

Code
场景:地址信息的建模

方案 A:扁平属性(Bad)
┌─────────────────────────────────┐
│  Employee                       │
│  ├── homeCountry: STRING        │
│  ├── homeProvince: STRING       │
│  ├── homeCity: STRING           │
│  ├── homeStreet: STRING         │
│  ├── homePostcode: STRING       │
│  ├── workCountry: STRING        │  ← 属性爆炸!
│  ├── workProvince: STRING       │
│  ├── workCity: STRING           │
│  ├── workStreet: STRING         │
│  └── workPostcode: STRING       │
└─────────────────────────────────┘

方案 B:独立 ObjectType(Overkill)
┌──────────┐  1:N  ┌──────────┐
│ Employee │──────►│ Address  │
└──────────┘       └──────────┘
├── 地址需要独立 ID?不需要
├── 地址需要独立生命周期?不需要
├── 地址需要被其他对象引用?不需要
└── 多余的关系管理开销

方案 C:StructType(Just Right)
┌─────────────────────────────────┐
│  Employee                       │
│  ├── homeAddress: Address       │  ← 嵌入式复合结构
│  └── workAddress: Address       │
└─────────────────────────────────┘

┌─────────────────────────────────┐
│  StructType: Address            │
│  ├── country: STRING            │
│  ├── province: STRING           │
│  ├── city: STRING               │
│  ├── street: STRING             │
│  └── postcode: STRING           │
└─────────────────────────────────┘

#4.2 定义 StructType

Python
# 创建 StructType
client.schema.create_struct_type({
    "apiName": "Address",
    "displayName": "地址",
    "description": "表示一个邮寄地址",
    "properties": {
        "country": {
            "type": "STRING",
            "required": True,
            "defaultValue": "中国",
        },
        "province": {"type": "STRING", "required": True},
        "city": {"type": "STRING", "required": True},
        "district": {"type": "STRING"},
        "street": {"type": "STRING", "required": True},
        "postcode": {
            "type": "STRING",
            "validations": [
                {"rule": "pattern", "value": "^[0-9]{6}$", "message": "邮编必须为 6 位数字"},
            ],
        },
        "isDefault": {"type": "BOOLEAN", "defaultValue": "false"},
    },
})

# 创建 GeoPoint StructType
client.schema.create_struct_type({
    "apiName": "GeoPoint",
    "displayName": "地理坐标",
    "properties": {
        "latitude": {
            "type": "DOUBLE",
            "required": True,
            "validations": [
                {"rule": "min", "value": -90},
                {"rule": "max", "value": 90},
            ],
        },
        "longitude": {
            "type": "DOUBLE",
            "required": True,
            "validations": [
                {"rule": "min", "value": -180},
                {"rule": "max", "value": 180},
            ],
        },
        "altitude": {"type": "DOUBLE", "description": "海拔(米)"},
        "accuracy": {"type": "DOUBLE", "description": "精度(米)"},
    },
})

#4.3 在 ObjectType 中使用 StructType

Python
# 在 ObjectType 属性中引用 StructType
client.schema.create_object_type({
    "name": "Employee",
    "primaryKey": "employeeId",
    "properties": {
        "employeeId": {"type": "STRING", "required": True},
        "name": {"type": "STRING", "required": True},

        # 使用 StructType 作为属性类型
        "homeAddress": {
            "type": "STRUCT",
            "structType": "Address",
            "required": True,
        },
        "workAddress": {
            "type": "STRUCT",
            "structType": "Address",
        },

        # StructType 数组
        "emergencyContacts": {
            "type": "ARRAY",
            "itemType": "STRUCT",
            "structType": "ContactInfo",
            "maxItems": 3,
        },
    },
})

# 创建对象时直接嵌入 Struct 值
employee = client.objects.create("Employee", {
    "employeeId": "emp-001",
    "name": "张三",
    "homeAddress": {
        "country": "中国",
        "province": "上海市",
        "city": "上海市",
        "district": "浦东新区",
        "street": "张江高科技园区碧波路 100 号",
        "postcode": "201203",
        "isDefault": True,
    },
    "workAddress": {
        "country": "中国",
        "province": "上海市",
        "city": "上海市",
        "street": "陆家嘴环路 1000 号",
        "postcode": "200120",
    },
    "emergencyContacts": [
        {"name": "李四", "phone": "13800138001", "relationship": "配偶"},
        {"name": "王五", "phone": "13800138002", "relationship": "父母"},
    ],
})

#4.4 嵌套查询

Python
# 查询嵌套 Struct 中的字段
results = client.objects.search("Employee", {
    "filters": {
        "homeAddress.city": {"eq": "上海市"},
        "homeAddress.district": {"eq": "浦东新区"},
    },
})

# 查询 Struct 数组中的字段
results = client.objects.search("Employee", {
    "filters": {
        "emergencyContacts.relationship": {"eq": "配偶"},
    },
})

#5. Struct 嵌套:多层复合结构

#5.1 多层嵌套定义

Python
# 三层嵌套示例:订单 → 行项目 → 价格明细

# 第一层:PriceBreakdown
client.schema.create_struct_type({
    "apiName": "PriceBreakdown",
    "properties": {
        "basePrice": {"type": "DOUBLE", "required": True},
        "discount": {"type": "DOUBLE", "defaultValue": "0"},
        "discountReason": {"type": "STRING"},
        "tax": {"type": "DOUBLE", "required": True},
        "taxRate": {"type": "DOUBLE", "required": True},
        "finalPrice": {"type": "DOUBLE", "required": True},
    },
})

# 第二层:OrderLineItem(包含 PriceBreakdown)
client.schema.create_struct_type({
    "apiName": "OrderLineItem",
    "properties": {
        "productId": {"type": "STRING", "required": True},
        "productName": {"type": "STRING", "required": True},
        "quantity": {"type": "INTEGER", "required": True, "validations": [{"rule": "min", "value": 1}]},
        "unit": {"type": "STRING", "defaultValue": "件"},
        "pricing": {
            "type": "STRUCT",
            "structType": "PriceBreakdown",  # 嵌套引用
            "required": True,
        },
        "notes": {"type": "STRING"},
    },
})

# 第三层:在 Order ObjectType 中使用
client.schema.create_object_type({
    "name": "Order",
    "primaryKey": "orderId",
    "properties": {
        "orderId": {"type": "STRING", "required": True},
        "customerId": {"type": "STRING", "required": True},
        "lineItems": {
            "type": "ARRAY",
            "itemType": "STRUCT",
            "structType": "OrderLineItem",
            "minItems": 1,
            "maxItems": 100,
        },
        "shippingAddress": {
            "type": "STRUCT",
            "structType": "Address",
        },
        "totalAmount": {"type": "DOUBLE"},
    },
})

#5.2 嵌套限制与最佳实践

Code
嵌套深度限制:

coomia-dip 支持最多 5 层嵌套:
  ObjectType
    └── Struct Level 1
        └── Struct Level 2
            └── Struct Level 3
                └── Struct Level 4
                    └── Struct Level 5 (最大深度)

超过 5 层时的替代方案:
├── 拆分为独立的 ObjectType + RelationType
├── 重新审视数据模型是否过于复杂
└── 考虑使用 JSON 类型存储半结构化数据

最佳实践:
├── 嵌套深度控制在 2-3 层
├── Struct 属性不超过 15 个字段
├── Struct 数组不超过 50 个元素
├── 对频繁查询的嵌套字段建立索引
└── 避免在 Struct 中放大文本字段(影响存储效率)

#6. InterfaceType + StructType 组合使用

Python
# 组合示例:可监控设备

# StructType:传感器读数
client.schema.create_struct_type({
    "apiName": "SensorReading",
    "properties": {
        "sensorId": {"type": "STRING", "required": True},
        "value": {"type": "DOUBLE", "required": True},
        "unit": {"type": "STRING", "required": True},
        "timestamp": {"type": "TIMESTAMP", "required": True},
        "quality": {"type": "ENUM", "enumValues": ["GOOD", "UNCERTAIN", "BAD"]},
    },
})

# InterfaceType:可监控
client.schema.create_interface_type({
    "apiName": "Monitorable",
    "displayName": "可监控",
    "properties": {
        "healthStatus": {
            "type": "ENUM",
            "enumValues": ["HEALTHY", "WARNING", "CRITICAL", "UNKNOWN"],
            "required": True,
        },
        "lastHeartbeat": {"type": "TIMESTAMP", "required": True},
        "currentReadings": {
            "type": "ARRAY",
            "itemType": "STRUCT",
            "structType": "SensorReading",
        },
    },
    "actions": [
        {"apiName": "resetHealth", "parameters": {}},
        {"apiName": "acknowledgeAlert", "parameters": {
            "alertId": {"type": "STRING", "required": True},
        }},
    ],
})

# ObjectType 同时使用 InterfaceType 和 StructType
client.schema.create_object_type({
    "name": "IndustrialRobot",
    "primaryKey": "robotId",
    "implements": ["Locatable", "Monitorable", "TrackableAsset"],
    "properties": {
        "robotId": {"type": "STRING", "required": True},
        "name": {"type": "STRING", "required": True},
        "model": {"type": "STRING"},
        "manufacturer": {"type": "STRING"},

        # 来自 Locatable
        "latitude": {"type": "DOUBLE", "required": True},
        "longitude": {"type": "DOUBLE", "required": True},
        "address": {"type": "STRING"},

        # 来自 Monitorable
        "healthStatus": {"type": "ENUM", "enumValues": ["HEALTHY", "WARNING", "CRITICAL", "UNKNOWN"], "required": True},
        "lastHeartbeat": {"type": "TIMESTAMP", "required": True},
        "currentReadings": {
            "type": "ARRAY",
            "itemType": "STRUCT",
            "structType": "SensorReading",
        },

        # 来自 TrackableAsset
        "assetTag": {"type": "STRING", "required": True},
        "assetValue": {"type": "DOUBLE", "required": True},
        "depreciationRate": {"type": "DOUBLE"},

        # 自有属性
        "operatingHours": {"type": "DOUBLE"},
        "jointConfiguration": {
            "type": "STRUCT",
            "structType": "RobotJointConfig",
        },
    },
})

#7. 类型系统对比:何时用什么

Code
┌─────────────────┬────────────────┬────────────────┬───────────────┐
│     特征         │  ObjectType    │  InterfaceType │  StructType   │
├─────────────────┼────────────────┼────────────────┼───────────────┤
│  有独立身份(PK)  │  ✅ 有         │  ❌ 无         │  ❌ 无        │
│  可独立存在      │  ✅ 是         │  ❌ 否         │  ❌ 否        │
│  可被引用(关系)  │  ✅ 可以       │  ❌ 不可以     │  ❌ 不可以    │
│  有生命周期      │  ✅ DRAFT→...  │  ✅ DRAFT→...  │  ✅ DRAFT→... │
│  可独立查询      │  ✅ 可以       │  ✅ 多态查询   │  ❌ 不可以    │
│  可嵌套          │  ❌ 不可以     │  ❌ 不可以     │  ✅ 可以      │
│  存储方式        │  独立表/分区   │  无存储        │  嵌入宿主对象 │
│  典型用途        │  业务实体      │  共性抽象      │  值对象       │
└─────────────────┴────────────────┴────────────────┴───────────────┘

决策树:

需要建模一个概念?
  │
  ├── 它有独立身份和生命周期?
  │   ├── Yes → ObjectType
  │   └── No  → 它代表多个类型的共性?
  │             ├── Yes → InterfaceType
  │             └── No  → 它是一个复合值?
  │                       ├── Yes → StructType
  │                       └── No  → 简单属性(STRING/DOUBLE/...)

#8. Protobuf 定义

PROTOBUF
message InterfaceType {
    string api_name = 1;
    string display_name = 2;
    string description = 3;

    // 继承的父接口
    repeated string extends = 4;

    // 接口定义的属性
    map<string, PropertyDef> properties = 5;

    // 接口定义的操作
    repeated ActionSignature actions = 6;

    // 实现此接口的 ObjectType 列表(自动维护)
    repeated string implemented_by = 7;

    LifecycleState lifecycle = 8;
}

message StructType {
    string api_name = 1;
    string display_name = 2;
    string description = 3;

    // 结构体字段
    map<string, PropertyDef> properties = 4;

    // 被哪些类型引用(自动维护)
    repeated StructUsage usages = 5;

    LifecycleState lifecycle = 6;
}

message StructUsage {
    string object_type = 1;
    string property_name = 2;
    bool is_array = 3;
}

#9. 实战案例:智能工厂类型体系

Python
# 完整的智能工厂类型系统设计

# === StructTypes ===

# 维护记录
client.schema.create_struct_type({
    "apiName": "MaintenanceRecord",
    "properties": {
        "date": {"type": "DATE", "required": True},
        "technician": {"type": "STRING", "required": True},
        "type": {"type": "ENUM", "enumValues": ["PREVENTIVE", "CORRECTIVE", "PREDICTIVE"]},
        "description": {"type": "STRING", "required": True},
        "duration_hours": {"type": "DOUBLE"},
        "cost": {"type": "DOUBLE"},
        "parts_replaced": {"type": "ARRAY", "itemType": "STRING"},
    },
})

# 告警规则
client.schema.create_struct_type({
    "apiName": "AlertRule",
    "properties": {
        "metric": {"type": "STRING", "required": True},
        "operator": {"type": "ENUM", "enumValues": ["GT", "LT", "EQ", "GTE", "LTE"]},
        "threshold": {"type": "DOUBLE", "required": True},
        "severity": {"type": "ENUM", "enumValues": ["INFO", "WARNING", "CRITICAL"]},
        "cooldownMinutes": {"type": "INTEGER", "defaultValue": "15"},
    },
})

# === InterfaceTypes ===

# 可审计
client.schema.create_interface_type({
    "apiName": "Auditable",
    "properties": {
        "createdAt": {"type": "TIMESTAMP", "required": True},
        "updatedAt": {"type": "TIMESTAMP", "required": True},
        "createdBy": {"type": "STRING", "required": True},
        "updatedBy": {"type": "STRING"},
    },
})

# 可维护
client.schema.create_interface_type({
    "apiName": "Maintainable",
    "extends": ["Auditable"],
    "properties": {
        "lastMaintenanceDate": {"type": "DATE"},
        "nextMaintenanceDate": {"type": "DATE"},
        "maintenanceHistory": {
            "type": "ARRAY",
            "itemType": "STRUCT",
            "structType": "MaintenanceRecord",
        },
        "alertRules": {
            "type": "ARRAY",
            "itemType": "STRUCT",
            "structType": "AlertRule",
        },
    },
    "actions": [
        {"apiName": "scheduleMaintenance", "parameters": {
            "date": {"type": "DATE", "required": True},
            "type": {"type": "STRING", "required": True},
        }},
    ],
})

# === ObjectTypes ===

# CNC 机床
client.schema.create_object_type({
    "name": "CNCMachine",
    "primaryKey": "machineId",
    "implements": ["Locatable", "Monitorable", "Maintainable", "TrackableAsset"],
    "properties": {
        "machineId": {"type": "STRING", "required": True},
        "name": {"type": "STRING", "required": True},
        # ... Locatable 属性
        "latitude": {"type": "DOUBLE", "required": True},
        "longitude": {"type": "DOUBLE", "required": True},
        "address": {"type": "STRING"},
        # ... Monitorable 属性
        "healthStatus": {"type": "ENUM", "enumValues": ["HEALTHY", "WARNING", "CRITICAL", "UNKNOWN"], "required": True},
        "lastHeartbeat": {"type": "TIMESTAMP", "required": True},
        "currentReadings": {"type": "ARRAY", "itemType": "STRUCT", "structType": "SensorReading"},
        # ... Maintainable 属性
        "createdAt": {"type": "TIMESTAMP", "required": True},
        "updatedAt": {"type": "TIMESTAMP", "required": True},
        "createdBy": {"type": "STRING", "required": True},
        "updatedBy": {"type": "STRING"},
        "lastMaintenanceDate": {"type": "DATE"},
        "nextMaintenanceDate": {"type": "DATE"},
        "maintenanceHistory": {"type": "ARRAY", "itemType": "STRUCT", "structType": "MaintenanceRecord"},
        "alertRules": {"type": "ARRAY", "itemType": "STRUCT", "structType": "AlertRule"},
        # ... TrackableAsset 属性
        "assetTag": {"type": "STRING", "required": True},
        "assetValue": {"type": "DOUBLE", "required": True},
        "depreciationRate": {"type": "DOUBLE"},
        # CNC 专有属性
        "spindleSpeed": {"type": "INTEGER", "description": "主轴转速 RPM"},
        "axisCount": {"type": "INTEGER", "description": "轴数(3/4/5)"},
        "maxWorkpieceSize": {"type": "STRUCT", "structType": "Dimensions3D"},
    },
})

# 多态查询示例
print("=== 所有需要维护的设备 ===")
overdue = client.objects.search_by_interface("Maintainable", {
    "filters": {
        "nextMaintenanceDate": {"lt": "2026-03-24"},
        "healthStatus": {"in": ["WARNING", "CRITICAL"]},
    },
    "orderBy": "nextMaintenanceDate",
})

for item in overdue:
    print(f"[{item.object_type}] {item.name}")
    print(f"  下次维护: {item.nextMaintenanceDate}")
    print(f"  健康状态: {item.healthStatus}")
    print(f"  维护历史: {len(item.maintenanceHistory)} 条记录")

#10. 版本演进与兼容性

Python
# InterfaceType 的版本演进

# 安全变更(向后兼容):
# ✅ 添加可选属性
# ✅ 添加新的 Action
# ✅ 放宽验证规则(如增大 max 值)

# 破坏性变更(需要走 Schema Change 流程):
# ❌ 删除已有属性
# ❌ 添加必填属性(已有实现类可能不满足)
# ❌ 修改属性类型
# ❌ 收紧验证规则

# StructType 的版本演进同理
# 额外注意:StructType 被多个 ObjectType 引用时,变更影响面更大

#Key Takeaways

  1. InterfaceType 实现了 Ontology 级别的多态——一次查询跨多个 ObjectType,无需硬编码类型列表,新增实现类自动纳入查询范围。
  2. StructType 是属性级别的复合类型——避免了属性爆炸(扁平化)和过度建模(独立 ObjectType),支持最多 5 层嵌套。
  3. 一个 ObjectType 可以实现多个 Interface——类似多重继承但无菱形问题,各 Interface 的属性独立,不存在冲突。
  4. 类型系统三要素协同:ObjectType(业务实体) + InterfaceType(共性抽象) + StructType(值对象) = 完整的领域建模能力。
  5. 接口合规性自动检查——创建或修改 ObjectType 时,系统验证是否满足所有声明的 Interface 要求。

#Next Article

下一篇 S4-07 派生属性 将介绍如何让数据"自己算出来"——通过 9 种 Reducer、表达式求值和 SQL 支撑的派生属性机制,实现"定义一次,自动更新"。

#ontology #interface-type #struct-type #polymorphic-query #type-system #inheritance #value-object