Files
steel_prices_service/docs/DATA_SOURCE_IDENTIFICATION.md
2026-01-06 18:00:43 +08:00

11 KiB
Raw Permalink Blame History

数据源标识系统说明

概述

为了清晰区分来自三个不同接口的数据,我们为每个数据源添加了明确的标识字段。这样可以:

  1. 清晰区分数据来源 - 知道数据来自哪个接口
  2. 便于数据筛选 - 按数据源查询和统计
  3. 数据溯源 - 追踪数据的采集方式(本地文件或 API
  4. 避免数据混淆 - 即使数据相似也能区分来源

数据源配置

三个接口的标识

接口端点 数据来源 标识码 颜色标签 描述
DEFAULT 云南钢协 YUNNAN_STEEL_ASSOC 🔴 #FF6B6B 云南钢协指导价API
BACKUP 我的钢铁 MY_STEEL 🔵 #4ECDC4 我的钢铁网价格API
EXTENDED 德钢指导价 DE_STEEL_FACTORY 🟢 #95E1D3 德钢钢厂指导价API

本地文件映射

文件名 数据来源 标识码 颜色标签 描述
刚协指导价.json 云南钢协 YUNNAN_STEEL_ASSOC 🔴 #FF6B6B 云南钢协指导价
钢材网架.json 我的钢铁 MY_STEEL 🔵 #4ECDC4 我的钢铁网价格
钢厂指导价.json 德钢指导价 DE_STEEL_FACTORY 🟢 #95E1D3 德钢钢厂指导价

数据库字段说明

新增字段

-- 数据源代码(唯一标识)
price_source_code VARCHAR(32) NOT NULL
-- 可能的值: 'YUNNAN_STEEL_ASSOC', 'MY_STEEL', 'DE_STEEL_FACTORY'

-- 数据源描述
price_source_desc VARCHAR(64) NOT NULL
-- 例如: '云南钢协指导价API', '我的钢铁网价格API'

-- 数据来源标识
data_origin VARCHAR(32) NOT NULL
-- 格式:
--   - 'LOCAL_FILE'     - 从本地文件导入
--   - 'API:DEFAULT'    - 从 DEFAULT 接口导入
--   - 'API:BACKUP'     - 从 BACKUP 接口导入
--   - 'API:EXTENDED'   - 从 EXTENDED 接口导入

完整表结构

CREATE TABLE prices (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  price_id VARCHAR(64) UNIQUE NOT NULL,
  goods_material VARCHAR(32) NOT NULL,
  goods_spec VARCHAR(16) NOT NULL,
  partsname_name VARCHAR(32) NOT NULL,
  productarea_name VARCHAR(64) NOT NULL,

  -- 数据源标识字段
  price_source VARCHAR(32) NOT NULL,           -- 原有字段:价格来源名称
  price_source_code VARCHAR(32) NOT NULL,       -- 新增:数据源代码
  price_source_desc VARCHAR(64) NOT NULL,       -- 新增:数据源描述
  data_origin VARCHAR(32) NOT NULL,             -- 新增:数据来源标识

  price_region VARCHAR(32) NOT NULL,
  pntree_name VARCHAR(32) NOT NULL,
  price_date DATETIME NOT NULL,
  make_price INT DEFAULT NULL,
  hang_price INT NOT NULL,
  last_make_price INT DEFAULT NULL,
  last_hang_price INT DEFAULT NULL,
  make_price_updw VARCHAR(8) DEFAULT NULL,
  hang_price_updw VARCHAR(8) DEFAULT NULL,
  operator_code VARCHAR(16) DEFAULT NULL,
  operator_name VARCHAR(32) DEFAULT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  -- 索引
  INDEX idx_price_date (price_date),
  INDEX idx_region_material (price_region, goods_material),
  INDEX idx_source_date (price_source, price_date),
  INDEX idx_source_code (price_source_code),        -- 新增:按数据源代码查询
  INDEX idx_data_origin (data_origin),              -- 新增:按数据来源查询
  INDEX idx_goods_spec (goods_spec)
);

使用示例

1. 数据库迁移(为现有表添加新字段)

npm run db:migrate

输出示例:

🔄 开始数据库迁移:添加数据源标识字段

✅ 数据源字段迁移成功

============================================================
✅ 数据库迁移完成!
============================================================

📊 新增字段说明:
  - price_source_code:  数据源代码YUNNAN_STEEL_ASSOC / MY_STEEL / DE_STEEL_FACTORY
  - price_source_desc:  数据源描述
  - data_origin:        数据来源标识LOCAL_FILE 或 API:ENDPOINT

🎨 数据源标识:
  🔴 YUNNAN_STEEL_ASSOC  - 云南钢协指导价DEFAULT 接口)
  🔵 MY_STEEL           - 我的钢铁网价格BACKUP 接口)
  🟢 DE_STEEL_FACTORY   - 德钢钢厂指导价EXTENDED 接口)

2. 从 API 接口导入数据(带标识)

# 导入云南钢协数据DEFAULT 接口)
node scripts/import-data.js single-api DEFAULT

# 导入我的钢铁数据BACKUP 接口)
node scripts/import-data.js single-api BACKUP

# 导入德钢指导价数据EXTENDED 接口)
node scripts/import-data.js single-api EXTENDED

# 从所有 API 接口导入
npm run db:import:api

导入过程示例:

🌐 正在从 API 接口获取数据: DEFAULT
   📊 数据源: 云南钢协指导价API
   🏷️  标识码: YUNNAN_STEEL_ASSOC
   🎨 标签: #FF6B6B
   📅 查询参数: {
  "startDate": "2025-01-06",
  "endDate": "2026-01-06",
  "page": 1,
  "pageSize": 100000
}
🔐 正在获取 Token...
✅ Token 获取成功
🔄 切换到接口: 默认钢材价格查询
   Page ID: PG-D615-D8E2-2FD84B8D
   Menu ID: MK-A8B8-109E-13D34116
✅ 解析到 1250 条有效数据
  进度: 1000/1250 条
  进度: 1250/1250 条
✅ 成功导入 1250 条数据

3. 从本地文件导入数据(带标识)

# 从本地文件导入
npm run db:import:local

导入过程示例:

📄 正在读取本地文件: 刚协指导价.json
   📊 数据源: 云南钢协指导价
   🏷️  标识码: YUNNAN_STEEL_ASSOC
   🎨 标签: #FF6B6B
✅ 解析到 900 条有效数据
  进度: 900/900 条
✅ 成功导入 900 条数据

数据查询示例

SQL 查询

1. 查询所有数据源统计

SELECT
  price_source_code AS '数据源代码',
  price_source_desc AS '数据源描述',
  data_origin AS '数据来源',
  COUNT(*) AS '记录数',
  AVG(hang_price) AS '平均价格',
  MIN(hang_price) AS '最低价格',
  MAX(hang_price) AS '最高价格'
FROM prices
GROUP BY price_source_code, price_source_desc, data_origin
ORDER BY price_source_code;

结果示例:

+---------------------+----------------------+----------------+----------+----------+----------+----------+
| 数据源代码          | 数据源描述           | 数据来源       | 记录数   | 平均价格 | 最低价格 | 最高价格 |
+---------------------+----------------------+----------------+----------+----------+----------+----------+
| YUNNAN_STEEL_ASSOC  | 云南钢协指导价API | API:DEFAULT    | 1250     | 4500.50  | 3800     | 5200     |
| YUNNAN_STEEL_ASSOC  | 云南钢协指导价       | LOCAL_FILE     | 900      | 4480.30  | 3850     | 5180     |
| MY_STEEL            | 我的钢铁网价格API | API:BACKUP     | 850      | 4420.80  | 3700     | 5150     |
| MY_STEEL            | 我的钢铁网价格       | LOCAL_FILE     | 211      | 4400.60  | 3750     | 5120     |
| DE_STEEL_FACTORY    | 德钢钢厂指导价API| API:EXTENDED   | 15000    | 4550.20  | 3900     | 5300     |
| DE_STEEL_FACTORY    | 德钢钢厂指导价       | LOCAL_FILE     | 29987    | 4530.90  | 3880     | 5280     |
+---------------------+----------------------+----------------+----------+----------+----------+----------+

2. 按数据源筛选

-- 查询云南钢协的数据
SELECT * FROM prices
WHERE price_source_code = 'YUNNAN_STEEL_ASSOC'
ORDER BY price_date DESC;

-- 查询从 API 导入的数据
SELECT * FROM prices
WHERE data_origin LIKE 'API:%'
ORDER BY price_date DESC;

-- 查询特定接口的数据
SELECT * FROM prices
WHERE data_origin = 'API:DEFAULT'
ORDER BY price_date DESC;

3. 对比不同数据源的价格

SELECT
  DATE(price_date) AS '日期',
  price_source_code AS '数据源',
  AVG(hang_price) AS '平均价格'
FROM prices
WHERE DATE(price_date) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY DATE(price_date), price_source_code
ORDER BY DATE(price_date), price_source_code;

Node.js 查询

// 查询特定数据源的数据
const yunnanSteelPrices = await Price.search({
  material: 'HRB400E',
  startDate: '2025-01-01',
  endDate: '2025-01-31'
});

// 过滤云南钢协数据
const filtered = yunnanSteelPrices.filter(item =>
  item.price_source_code === 'YUNNAN_STEEL_ASSOC'
);

// 按数据源分组统计
const statsBySource = await Price.getStats({
  /* 可以扩展 getStats 方法支持按数据源统计 */
});

API 接口返回数据格式

导入数据时,每条记录将包含以下标识字段:

{
  "price_id": "abc123...",
  "goods_material": "HRB400E",
  "goods_spec": "Φ18",
  "partsname_name": "螺纹钢",
  "productarea_name": "云南德胜",
  "price_source": "云南钢协",
  "price_source_code": "YUNNAN_STEEL_ASSOC",        // 数据源代码
  "price_source_desc": "云南钢协指导价API",      // 数据源描述
  "data_origin": "API:DEFAULT",                      // 数据来源标识
  "price_region": "昆明",
  "pntree_name": "钢筋",
  "price_date": "2025-01-06 00:00:00",
  "make_price": 4450,
  "hang_price": 4500,
  "last_make_price": 4400,
  "last_hang_price": 4450,
  "make_price_updw": "+50",
  "hang_price_updw": "+50"
}

颜色标签使用建议

这些颜色标签可以在前端界面中使用,帮助用户直观区分数据来源:

const SOURCE_COLORS = {
  YUNNAN_STEEL_ASSOC: '#FF6B6B',  // 红色 - 云南钢协
  MY_STEEL: '#4ECDC4',            // 蓝绿色 - 我的钢铁
  DE_STEEL_FACTORY: '#95E1D3'     // 绿色 - 德钢指导价
};

// 在 React/Vue 等前端框架中使用
<div style={{ color: SOURCE_COLORS[item.price_source_code] }}>
  {item.price_source_desc}
</div>

注意事项

  1. 唯一性: price_source_code 是数据源的唯一标识,建议在业务逻辑中使用
  2. 兼容性: 原有的 price_source 字段保留,用于显示中文名称
  3. 索引优化: 已为 price_source_codedata_origin 添加索引,查询性能更好
  4. 数据迁移: 如果已有数据,运行迁移脚本会自动添加新字段并设置默认值

故障排查

问题 1: 迁移后新字段为空

原因: 旧数据没有标识字段信息

解决方案:

-- 更新旧数据的标识字段
UPDATE prices SET
  price_source_code = CASE
    WHEN price_source = '云南钢协' THEN 'YUNNAN_STEEL_ASSOC'
    WHEN price_source = '我的钢铁' THEN 'MY_STEEL'
    WHEN price_source = '德钢指导价' THEN 'DE_STEEL_FACTORY'
    ELSE 'UNKNOWN'
  END,
  price_source_desc = price_source,
  data_origin = 'LOCAL_FILE'
WHERE data_origin = '' OR data_origin IS NULL;

问题 2: 导入数据时字段未填充

原因: 导入脚本版本过旧

解决方案:

# 确保使用最新的 import-data.js
git pull origin main
npm run db:import:api

相关文档