2. 领域驱动设计(DDD)核心概念回顾

领域驱动设计(Domain-Driven Design, DDD)是一套应对复杂业务建模的软件方法论。在数据同步与搜索索引场景中,DDD 的五大核心概念——实体、值对象、聚合、领域事件、限界上下文——直接决定了索引结构的设计粒度、同步边界和事件驱动策略。本节逐一回顾这些概念,并给出与搜索索引映射的对照关系。

2.1 实体(Entity)

实体是具有唯一标识且生命周期持续变化的对象。两个实体即使所有属性相同,只要标识不同,就是不同的对象。在搜索索引中,实体通常对应索引文档的 _id 字段。

特征 说明 索引映射示例
唯一标识 ID 不可变,贯穿整个生命周期 Elasticsearch 文档 _id
可变属性 状态、名称、金额等可被修改 索引中可更新的字段
相等性 通过 ID 判断,而非属性值 同步时以 ID 作为主键匹配
索引设计提示: 实体在索引中通常作为根文档存在。例如“订单”实体在索引中就是一个独立的 order 文档,其 ID 与数据库主键一致。

2.2 值对象(Value Object)

值对象通过属性值来定义自身,没有唯一标识,且通常是不可变的。两个值对象如果所有属性相同,则视为同一个对象。值对象非常适合作为索引中的嵌套对象或扁平化字段。

特征 说明 索引映射示例
无标识 不依赖 ID,只依赖属性组合 嵌套对象(nested)或扁平字段
不可变 创建后不允许修改,替换即新建 索引中直接覆盖旧值
相等性 所有属性值完全相等才视为相同 同步时比较全字段决定是否更新
典型场景: “地址”是值对象。在索引中,地址通常被展开为 city、district、street 等扁平字段,或使用 nested 类型保留结构。

2.3 聚合(Aggregate)

聚合是数据一致性边界。一个聚合包含一个聚合根(Aggregate Root)和若干实体/值对象。外部只能通过聚合根访问聚合内部。聚合是数据同步的最小原子单元——要么整个聚合一起同步,要么不同步。

聚合结构示例:订单聚合 聚合边界 聚合根:订单实体 orderId, status, totalAmount 订单项实体 itemId, productId, quantity 收货地址(值对象) city, district, detail 同步原子单元:整个聚合作为一个整体写入索引
同步边界规则: 聚合根 ID 作为索引文档 ID;聚合内部所有变更必须通过聚合根触发;索引更新时,整个聚合文档整体替换,避免部分更新导致数据不一致。

2.4 领域事件(Domain Event)

领域事件是业务领域中发生的、有意义的、已发生的事实。它是事件驱动数据同步的核心载体。当聚合状态发生变化时,聚合根发布领域事件,事件携带变更数据,驱动索引更新。

事件属性 说明 同步场景示例
事件名称 业务语义明确的过去时动词 OrderCreated、OrderShipped
事件时间 事件发生的业务时间戳 用于索引中 updatedAt 字段
事件载荷 携带变更后的关键数据 聚合根 ID + 变更字段 + 新值
事件版本 用于幂等处理和顺序保证 防止重复消费导致索引脏数据
事件驱动同步流程:
1. 业务操作 → 聚合根状态变更
2. 聚合根发布领域事件(如 OrderStatusChanged)
3. 事件总线/消息队列接收事件
4. 索引同步消费者消费事件 → 更新 Elasticsearch 文档

2.5 限界上下文(Bounded Context)

限界上下文是 DDD 中最关键的战略设计概念。它划定了模型边界:每个上下文内部有统一的语言(Ubiquitous Language)和独立的模型实现。不同上下文之间通过上下文映射(Context Map)进行集成。

限界上下文与搜索索引的映射关系 订单上下文 订单实体 订单项实体 收货地址值对象 领域事件:OrderCreated OrderStatusChanged 商品上下文 商品实体 SKU 实体 商品描述值对象 领域事件:ProductUpdated InventoryChanged 搜索索引上下文 订单索引文档 商品索引文档 组合搜索视图 消费多个上下文事件 构建宽表索引 每个限界上下文独立发布领域事件,搜索索引上下文作为消费者统一构建搜索视图

2.6 核心概念对比总结

概念 有无标识 可变性 相等性判断 索引映射角色
实体 有 可变 ID 相等 索引文档根
值对象 无 不可变 属性全等 嵌套/扁平字段
聚合 聚合根有 ID 整体替换 聚合根 ID 相等 同步原子单元
领域事件 有事件 ID 不可变 事件 ID 相等 同步触发信号
限界上下文 有上下文名称 边界固定 名称唯一 索引数据源边界