/** * 数据库模型基类 * @file BaseModel.js * @description 提供所有模型的基础功能和通用方法 */ const { Model, DataTypes } = require('sequelize'); const queryOptimizer = require('../utils/query-optimizer'); class BaseModel extends Model { /** * 初始化模型 * @param {Object} sequelize Sequelize实例 * @param {Object} attributes 模型属性 * @param {Object} options 模型选项 */ static init(attributes, options = {}) { // 确保options中包含sequelize实例 if (!options.sequelize) { throw new Error('必须提供sequelize实例'); } // 默认配置 const defaultOptions = { // 使用下划线命名法 underscored: true, // 默认时间戳字段 timestamps: true, createdAt: 'created_at', updatedAt: 'updated_at', // 默认不使用软删除 paranoid: false, // 字符集和排序规则 charset: 'utf8mb4', collate: 'utf8mb4_unicode_ci' }; // 合并选项 const mergedOptions = { ...defaultOptions, ...options }; // 调用父类的init方法 return super.init(attributes, mergedOptions); } /** * 分页查询 * @param {Object} options 查询选项 * @param {Number} page 页码 * @param {Number} pageSize 每页记录数 * @returns {Promise} 分页结果 */ static async paginate(options = {}, page = 1, pageSize = 10) { // 确保页码和每页记录数为正整数 page = Math.max(1, parseInt(page)); pageSize = Math.max(1, parseInt(pageSize)); // 计算偏移量 const offset = (page - 1) * pageSize; // 合并分页参数 const paginateOptions = { ...options, limit: pageSize, offset }; // 执行查询 const { count, rows } = await this.findAndCountAll(paginateOptions); // 计算总页数 const totalPages = Math.ceil(count / pageSize); // 返回分页结果 return { data: rows, pagination: { total: count, page, pageSize, totalPages, hasMore: page < totalPages } }; } /** * 批量创建或更新记录 * @param {Array} records 记录数组 * @param {Array|String} uniqueFields 唯一字段或字段数组 * @returns {Promise} 创建或更新的记录 */ static async bulkUpsert(records, uniqueFields) { if (!Array.isArray(records) || records.length === 0) { return []; } // 确保uniqueFields是数组 const fields = Array.isArray(uniqueFields) ? uniqueFields : [uniqueFields]; // 获取所有字段 const allFields = Object.keys(this.rawAttributes); // 批量创建或更新 const result = await this.bulkCreate(records, { updateOnDuplicate: allFields.filter(field => { // 排除主键和时间戳字段 return ( field !== 'id' && field !== 'created_at' && field !== 'updated_at' && field !== 'deleted_at' ); }), // 返回创建或更新后的记录 returning: true }); return result; } /** * 执行原始SQL查询 * @param {String} sql SQL语句 * @param {Object} replacements 替换参数 * @param {String} type 查询类型 * @returns {Promise} 查询结果 */ static async rawQuery(sql, replacements = {}, type = 'SELECT') { const sequelize = this.sequelize; const QueryTypes = sequelize.QueryTypes; // 执行查询前分析查询性能 if (process.env.NODE_ENV === 'development') { try { const explainResult = await queryOptimizer.explainQuery(sql, replacements); console.log('查询分析结果:', explainResult); } catch (error) { console.warn('查询分析失败:', error.message); } } // 执行查询 return sequelize.query(sql, { replacements, type: QueryTypes[type], model: this, mapToModel: type === 'SELECT' }); } /** * 获取模型的表信息 * @returns {Promise} 表信息 */ static async getTableInfo() { const tableName = this.getTableName(); return queryOptimizer.getTableInfo(tableName); } /** * 获取模型的索引信息 * @returns {Promise} 索引信息 */ static async getIndexes() { const tableName = this.getTableName(); return queryOptimizer.getTableIndexes(tableName); } /** * 分析表结构 * @returns {Promise} 分析结果 */ static async analyzeTable() { const tableName = this.getTableName(); return queryOptimizer.analyzeTable(tableName); } /** * 优化表 * @returns {Promise} 优化结果 */ static async optimizeTable() { const tableName = this.getTableName(); return queryOptimizer.optimizeTable(tableName); } } module.exports = BaseModel;