308 lines
7.9 KiB
Markdown
308 lines
7.9 KiB
Markdown
# 数据导入脚本使用说明
|
||
|
||
## 概述
|
||
|
||
`scripts/import-data.js` 已升级,现在支持两种数据导入模式:
|
||
|
||
1. **本地文件模式** (`local`): 从 `data/` 目录的 JSON 文件导入
|
||
2. **API 接口模式** (`api`): 从 `commonApi.js` 定义的接口实时获取数据
|
||
|
||
## 接口映射关系
|
||
|
||
| 接口端点 | 数据来源 | 对应文件 | 数据来源标识 |
|
||
|---------|---------|---------|------------|
|
||
| `DEFAULT` | 云南钢协 | 刚协指导价.json | 云南钢协 |
|
||
| `BACKUP` | 我的钢铁 | 钢材网架.json | 我的钢铁 |
|
||
| `EXTENDED` | 德钢指导价 | 钢厂指导价.json | 德钢指导价 |
|
||
|
||
## 使用方法
|
||
|
||
### 1. 本地文件导入(默认模式)
|
||
|
||
```bash
|
||
# 方式 1: 显式指定模式
|
||
node scripts/import-data.js local
|
||
|
||
# 方式 2: 使用默认模式(省略参数)
|
||
npm run db:import
|
||
# 或
|
||
node scripts/import-data.js
|
||
```
|
||
|
||
**功能说明:**
|
||
- 从 `data/` 目录读取所有 JSON 文件
|
||
- 依次导入:刚协指导价.json、钢材网架.json、钢厂指导价.json
|
||
- 跳过不存在的文件
|
||
|
||
### 2. API 接口导入
|
||
|
||
#### 2.1 从所有 API 接口导入
|
||
|
||
```bash
|
||
# 使用默认参数(今天到一年后,每页 10 万条)
|
||
node scripts/import-data.js api
|
||
|
||
# 指定日期范围
|
||
node scripts/import-data.js api --startDate 2025-01-01 --endDate 2025-12-31
|
||
|
||
# 指定每页数量
|
||
node scripts/import-data.js api --pageSize 50000
|
||
|
||
# 组合参数
|
||
node scripts/import-data.js api --startDate 2025-01-01 --endDate 2025-12-31 --pageSize 100000
|
||
```
|
||
|
||
**执行流程:**
|
||
1. 依次调用 DEFAULT、BACKUP、EXTENDED 三个接口
|
||
2. 自动获取 Token
|
||
3. 批量导入数据(每批 1000 条)
|
||
4. 显示导入进度和统计信息
|
||
|
||
#### 2.2 从单个 API 接口导入
|
||
|
||
```bash
|
||
# 仅导入云南钢协数据(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
|
||
|
||
# 带参数的单接口导入
|
||
node scripts/import-data.js single-api DEFAULT --startDate 2025-01-01 --endDate 2025-12-31
|
||
```
|
||
|
||
## 命令行参数
|
||
|
||
| 参数 | 说明 | 示例 | 默认值 |
|
||
|-----|------|-----|-------|
|
||
| `--startDate` | 查询开始日期(YYYY-MM-DD) | `--startDate 2025-01-01` | 今天 |
|
||
| `--endDate` | 查询结束日期(YYYY-MM-DD) | `--endDate 2026-01-01` | 一年后 |
|
||
| `--pageSize` | 每页数据条数 | `--pageSize 100000` | 100000 |
|
||
|
||
## 输出示例
|
||
|
||
### 本地文件导入
|
||
|
||
```
|
||
🚀 开始从本地文件导入钢材价格数据...
|
||
|
||
📄 正在读取本地文件: 刚协指导价.json
|
||
✅ 解析到 900 条有效数据
|
||
进度: 900/900 条
|
||
✅ 成功导入 900 条数据
|
||
|
||
📄 正在读取本地文件: 钢材网架.json
|
||
✅ 解析到 211 条有效数据
|
||
进度: 211/211 条
|
||
✅ 成功导入 211 条数据
|
||
|
||
📄 正在读取本地文件: 钢厂指导价.json
|
||
✅ 解析到 29987 条有效数据
|
||
进度: 1000/29987 条
|
||
进度: 2000/29987 条
|
||
...
|
||
进度: 29987/29987 条
|
||
✅ 成功导入 29987 条数据
|
||
|
||
==================================================
|
||
🎉 本地文件导入完成!总计导入 31098 条数据
|
||
==================================================
|
||
|
||
📊 数据库统计信息:
|
||
总记录数: 31098
|
||
平均价格: 4500.25 元/吨
|
||
最低价格: 3200 元/吨
|
||
最高价格: 5800 元/吨
|
||
|
||
✅ 脚本执行完成
|
||
```
|
||
|
||
### API 接口导入
|
||
|
||
```
|
||
🚀 开始从 API 接口导入钢材价格数据...
|
||
|
||
🌐 正在从 API 接口获取数据: DEFAULT (云南钢协)
|
||
查询参数: {
|
||
"startDate": "2025-01-06",
|
||
"endDate": "2026-01-06",
|
||
"page": 1,
|
||
"pageSize": 100000
|
||
}
|
||
🔐 正在获取 Token...
|
||
✅ Token 获取成功: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||
🔄 切换到接口: 默认钢材价格查询
|
||
Page ID: PG-D615-D8E2-2FD84B8D
|
||
Menu ID: MK-A8B8-109E-13D34116
|
||
✅ 解析到 1250 条有效数据
|
||
进度: 1000/1250 条
|
||
进度: 1250/1250 条
|
||
✅ 成功导入 1250 条数据
|
||
|
||
🌐 正在从 API 接口获取数据: BACKUP (我的钢铁)
|
||
...
|
||
|
||
🌐 正在从 API 接口获取数据: EXTENDED (德钢指导价)
|
||
...
|
||
|
||
==================================================
|
||
🎉 API 接口导入完成!总计导入 15234 条数据
|
||
==================================================
|
||
|
||
📊 数据库统计信息:
|
||
总记录数: 46332
|
||
平均价格: 4450.80 元/吨
|
||
最低价格: 3100 元/吨
|
||
最高价格: 5900 元/吨
|
||
|
||
✅ 脚本执行完成
|
||
```
|
||
|
||
## 编程式调用
|
||
|
||
除了命令行调用,也可以在代码中直接使用:
|
||
|
||
```javascript
|
||
const { importFromAPI, importAllFromAPI, importAllLocalFiles } = require('./scripts/import-data');
|
||
|
||
// 方式 1: 从单个 API 接口导入
|
||
await importFromAPI('DEFAULT', {
|
||
startDate: '2025-01-01',
|
||
endDate: '2025-12-31',
|
||
pageSize: 100000
|
||
});
|
||
|
||
// 方式 2: 从所有 API 接口导入
|
||
await importAllFromAPI({
|
||
startDate: '2025-01-01',
|
||
endDate: '2025-12-31'
|
||
});
|
||
|
||
// 方式 3: 从本地文件导入
|
||
await importAllLocalFiles();
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
脚本包含完善的错误处理机制:
|
||
|
||
1. **文件不存在**: 自动跳过,继续处理其他文件
|
||
2. **API 请求失败**: 显示错误信息,继续处理下一个接口
|
||
3. **数据解析失败**: 显示详细错误,不会中断整个流程
|
||
4. **数据库插入失败**: 记录错误日志,支持批量插入失败重试
|
||
|
||
## 注意事项
|
||
|
||
1. **环境变量**: 确保 `.env` 文件配置正确,包含数据库连接信息
|
||
2. **Token 管理**: API 模式会自动从 `loginApi.js` 获取 Token,确保登录凭证有效
|
||
3. **网络连接**: API 模式需要稳定的网络连接
|
||
4. **数据库性能**: 批量插入每批 1000 条,大数据量导入可能需要较长时间
|
||
5. **重复数据**: 使用 `ON DUPLICATE KEY UPDATE` 策略,避免重复导入
|
||
|
||
## 故障排查
|
||
|
||
### 问题 1: Token 获取失败
|
||
|
||
```
|
||
❌ Token 获取失败: Invalid credentials
|
||
```
|
||
|
||
**解决方案:**
|
||
- 检查 `.env` 中的登录凭证
|
||
- 确认 `loginApi.js` 中的 Token 存储路径正确
|
||
- 手动运行 `node commonApi.js` 测试登录
|
||
|
||
### 问题 2: 数据库连接失败
|
||
|
||
```
|
||
❌ 价格表创建失败: Access denied for user 'root'@'localhost'
|
||
```
|
||
|
||
**解决方案:**
|
||
- 检查 `.env` 中的数据库配置
|
||
- 确认 MySQL 服务已启动
|
||
- 验证用户权限
|
||
|
||
### 问题 3: API 返回空数据
|
||
|
||
```
|
||
⚠️ 没有有效数据可导入
|
||
```
|
||
|
||
**解决方案:**
|
||
- 检查日期范围是否合理
|
||
- 确认 API 接口地址正确
|
||
- 尝试增加 `pageSize` 参数
|
||
|
||
## 最佳实践
|
||
|
||
1. **定期导入**: 使用 `node-cron` 或系统定时任务定期执行 API 导入
|
||
2. **增量更新**: 使用日期参数仅导入最新数据
|
||
3. **数据备份**: 导入前备份现有数据
|
||
4. **监控日志**: 保存导入日志用于审计和问题排查
|
||
|
||
## 示例:定时任务
|
||
|
||
使用 `node-cron` 设置每天凌晨 2 点自动导入:
|
||
|
||
```javascript
|
||
// scripts/schedule-import.js
|
||
const cron = require('node-cron');
|
||
const { exec } = require('child_process');
|
||
|
||
cron.schedule('0 2 * * *', () => {
|
||
console.log('🕰️ 开始定时导入任务...');
|
||
|
||
exec('node scripts/import-data.js api --startDate 2025-01-01 --pageSize 100000',
|
||
(error, stdout, stderr) => {
|
||
if (error) {
|
||
console.error(`执行出错: ${error}`);
|
||
return;
|
||
}
|
||
console.log(stdout);
|
||
}
|
||
);
|
||
});
|
||
|
||
console.log('✅ 定时任务已启动:每天 02:00 执行数据导入');
|
||
```
|
||
|
||
运行定时任务:
|
||
|
||
```bash
|
||
node scripts/schedule-import.js
|
||
```
|
||
|
||
## 技术细节
|
||
|
||
### 数据转换
|
||
|
||
- 原始数据格式: `rawData.data.page.result[]`
|
||
- 过滤条件: `price_date` 存在且 `hang_price > 0`
|
||
- 字段映射: 自动映射 API 字段到数据库字段
|
||
|
||
### 批量插入策略
|
||
|
||
- 批次大小: 1000 条/批
|
||
- 重复处理: 使用 `ON DUPLICATE KEY UPDATE`
|
||
- 事务支持: 每批独立事务
|
||
|
||
### 性能优化
|
||
|
||
- 批量插入优于单条插入
|
||
- 数据库索引优化 (`idx_price_date`, `idx_region_material`)
|
||
- 自动过滤无效数据,减少不必要的数据库操作
|
||
|
||
---
|
||
|
||
## 更新日志
|
||
|
||
### 2026-01-06
|
||
- ✅ 新增 API 接口导入功能
|
||
- ✅ 支持命令行参数配置
|
||
- ✅ 改进错误处理和进度显示
|
||
- ✅ 保持向后兼容性
|