Node.js中用Sequelize将CSV自动导入SQL Server并实现upsert的问题
自动生成Sequelize Model实现
你已经完成了CSV字段类型识别和表头读取,只需要把识别到的字段类型映射到Sequelize内置类型,即可动态生成Model:
const { DataTypes } = require('sequelize'); // 以下两个变量是你已完成的csv解析产出的结果 const csvHeaders = ['id', 'goods_name', 'price', 'sale_time']; // 读取到的csv表头 const fieldTypes = { id: 'integer', goods_name: 'string', price: 'float', sale_time: 'date' }; // 你cast后识别到的每个字段的类型 // CSV识别类型和Sequelize类型的映射规则,可按需扩展 const typeMapping = { integer: DataTypes.INTEGER, float: DataTypes.FLOAT, date: DataTypes.DATE, string: DataTypes.STRING }; // 动态生成模型配置 const modelAttributes = {}; csvHeaders.forEach(field => { // 可自定义规则,比如id字段设为主键自增 if (field === 'id') { modelAttributes[field] = { type: typeMapping[fieldTypes[field]] || DataTypes.STRING, primaryKey: true, autoIncrement: true } } else { modelAttributes[field] = { type: typeMapping[fieldTypes[field]] || DataTypes.STRING, allowNull: true // 若csv字段存在空值可设为true } } }); // 动态定义模型,表名可直接用csv文件名自定义 const CsvImportModel = sequelize.define('your_table_name', modelAttributes, { timestamps: false // 不需要Sequelize自动生成createdAt、updatedAt字段就关闭 }); // 同步表结构到数据库,alter设为true会自动调整已有表的字段结构,生产环境谨慎使用 await CsvImportModel.sync({ alter: true });
小提示:识别字段类型时建议扫描CSV前50-100行判断,只要某列出现过非数字/日期的内容,就兜底设为STRING类型,避免写入时类型不兼容报错。
Upsert功能实现
Sequelize原生支持upsert能力,单条写入和批量写入分别用对应方法即可:
单条数据upsert
// singleRow是你cast后的单条csv数据,格式为{id:1, goods_name: '测试商品', price: 12.5, sale_time: new Date('2024-01-01')} await CsvImportModel.upsert(singleRow, { conflictFields: ['id'] // 指定冲突判断字段,该字段值重复时触发更新,否则触发插入 });
批量数据upsert(性能远高于循环单条upsert)
// allRows是你cast后的所有csv数据数组 await CsvImportModel.bulkCreate(allRows, { updateOnDuplicate: ['goods_name', 'price', 'sale_time'] // 指定冲突时需要更新的字段,填除了冲突判断字段之外的所有字段即可 });
批量写入时建议按1000条/批次拆分数据写入,避免数据量过大导致请求超时。
内容的提问来源于stack exchange,提问作者Pieter Geelen
相关产品推荐
相关产品推荐

