数据模型设计:报价引擎的骨架

做报价引擎,说白了就是在做数据模型的设计。我见过太多团队,一上来就写业务逻辑,结果数据模型没想清楚,后面改得死去活来。嗯,今天我们就聊聊这个核心话题。

核心观点:数据模型决定了报价引擎的扩展性和维护成本。模型设计得好,后面加规则、加商品、加客户分层,就像搭积木一样简单。

商品/服务模型:报价的基础单元

商品模型是报价引擎的「原子」。我习惯把它拆成三层:基础信息层、定价属性层、扩展属性层

层级 字段示例 说明
基础信息层 product_id, name, category, unit 唯一标识、名称、分类、计量单位
定价属性层 base_price, cost_price, min_price, max_price 定价相关的核心数值
扩展属性层 attributes (JSON), tags, version 灵活扩展,比如颜色、尺寸、地区

为什么这么分?我在项目中遇到过一个问题:某次客户要求对「同一款商品在不同地区报不同价格」。如果定价属性写死在商品表里,那就得复制商品记录,数据冗余不说,维护起来简直噩梦。后来我把地区相关的属性放到了扩展属性层,用 JSON 存储,配合价格规则模型,轻松搞定。

// 商品模型示例(简化版)
{
  "product_id": "PROD_001",
  "name": "企业版云服务器",
  "category": "compute",
  "unit": "台/月",
  "base_price": 299.00,
  "cost_price": 180.00,
  "min_price": 220.00,
  "attributes": {
    "region": ["cn-east", "cn-south"],
    "spec": "8C16G",
    "os": ["linux", "windows"]
  }
}

我的经验:扩展属性层用 JSON 字段,但一定要加索引。否则查询时全表扫描,性能会崩。我曾经吃过这个亏,后来加了虚拟列 + 函数索引才解决。

价格规则模型:报价的「大脑」

价格规则模型,说白了就是「在什么条件下,怎么算价格」。我把它设计成规则引擎 + 规则参数的组合。

规则引擎负责「条件判断」,规则参数负责「计算逻辑」。举个例子:

// 价格规则模型
{
  "rule_id": "RULE_001",
  "name": "新客首月5折",
  "priority": 10,           // 优先级,数字越小越优先
  "conditions": {            // 条件:客户分层 + 商品分类
    "customer_tier": "new",
    "product_category": "compute"
  },
  "action": {                // 动作:打折
    "type": "percentage",
    "value": 50
  },
  "effective_date": "2024-01-01",
  "expiry_date": "2024-12-31"
}

你想想看,如果规则写死在代码里,每次改价都要发版,多痛苦。用这种模型,规则可以动态加载,甚至支持 A/B 测试。

注意:规则优先级一定要设计好。我曾经遇到过一个场景:两条规则同时命中,结果价格算出来是负数。后来我加了一条「规则互斥检查」,才避免了这个坑。

客户分层模型:报价的「瞄准镜」

客户分层模型,决定了「谁该得到什么价格」。我习惯用标签体系 + 分层规则来实现。

  • 标签体系:动态打标,比如「高价值客户」「流失风险客户」「新注册用户」
  • 分层规则:根据标签组合,映射到具体的价格策略

举个例子:

// 客户分层模型
{
  "customer_id": "CUST_001",
  "tier": "gold",           // 固定分层:silver, gold, platinum
  "tags": ["high_value", "long_term", "referral"],
  "score": 85,              // 客户价值评分
  "price_strategy": "premium_discount"  // 关联的价格策略
}

为什么用标签体系?因为固定分层太死板了。我记得有一次,一个客户上个月还是「silver」,这个月突然签了大单,如果按固定分层,他得等下个月才能享受优惠。用标签体系,我们可以实时更新标签,报价立刻生效。

报价请求与响应模型:报价的「出入口」

报价请求和响应模型,是报价引擎对外的接口。设计得好,前端和后端对接就顺畅;设计得不好,联调时天天吵架。

我建议把请求模型拆成必填字段可选字段

字段类型 字段名 说明
必填 customer_id, product_id, quantity 客户、商品、数量
可选 coupon_code, promotion_id, custom_params 优惠券、活动、自定义参数
// 报价请求示例
{
  "request_id": "REQ_001",
  "customer_id": "CUST_001",
  "items": [
    {
      "product_id": "PROD_001",
      "quantity": 10,
      "custom_params": {
        "region": "cn-east",
        "duration": 12
      }
    }
  ],
  "coupon_code": "NEW_USER_50"
}

// 报价响应示例
{
  "request_id": "REQ_001",
  "status": "success",
  "total_price": 1495.00,
  "items": [
    {
      "product_id": "PROD_001",
      "unit_price": 149.50,
      "original_price": 299.00,
      "discount": 50,
      "rules_applied": ["RULE_001"]
    }
  ],
  "valid_until": "2024-01-31T23:59:59Z"
}

避坑指南:响应模型一定要带上 rules_applied 字段。我曾经遇到客户投诉说「价格不对」,结果查了半天,发现是两条规则同时生效,但前端只显示了一条。加上这个字段后,客户可以清楚看到哪些规则影响了价格,透明度大大提升。

核心逻辑:四层模型如何协同工作

这四个模型不是孤立的,它们像齿轮一样咬合在一起。我画了一张图,帮你理解它们的关系:

报价引擎数据模型协同关系图 商品/服务模型 基础信息 定价属性 价格规则模型 条件判断 计算逻辑 客户分层模型 标签体系 分层规则 报价请求/响应 请求参数 响应结果 提供定价基础 提供分层信息 执行报价计算 查询商品信息 查询客户分层 实线:核心流程 | 虚线:查询依赖

从这张图你可以看到:

  • 报价请求进来后,先查商品模型拿到基础价格
  • 再查客户分层模型拿到客户标签和分层
  • 然后交给价格规则模型,根据条件匹配规则,计算最终价格
  • 最后组装成报价响应返回给调用方

这个流程看起来简单,但实际落地时有很多细节。比如规则匹配的顺序、缓存策略、并发控制等等。嗯,这些我们后面会慢慢聊。

总结一下:数据模型设计是报价引擎的基石。商品模型提供「是什么」,客户分层模型提供「是谁」,价格规则模型提供「怎么算」,报价请求/响应模型提供「怎么交互」。四个模型各司其职,协同工作,才能支撑起一个灵活、可扩展的报价引擎。

专注资料整理