Knex.js如何实现查询时排除指定列?避免重复编写select
在Knex.js中实现
unSelect方法排除指定列 Knex.js本身没有内置反向选择列的unSelectAPI,但你可以通过扩展Knex查询构建器实现这个功能,既能满足链式调用需求,又能避免表结构变更时修改大量查询代码。
方案一:预设列配置(适合结构稳定的表)
提前维护各表的完整列清单和默认排除字段,避免重复编写列名:
// 全局配置:定义各表的列清单与默认排除项 const tableConfig = { invoices: { allColumns: ['id', 'invoice_date', 'product_id', 'qty', 'rate', 'amount', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy'], defaultExcluded: ['createdAt', 'updatedAt', 'createdBy', 'updatedBy'] } // 其他表可在此添加对应配置 }; // 扩展Knex查询构建器,添加unSelect方法 knex.QueryBuilder.extend('unSelect', function(...customExcluded) { const tableName = this._single.table; const config = tableConfig[tableName]; if (!config) throw new Error(`未找到表${tableName}的配置`); // 合并默认排除项与自定义排除项,去重 const columnsToExclude = [...new Set([...config.defaultExcluded, ...customExcluded])]; // 过滤出需要查询的列 const columnsToSelect = config.allColumns.filter(col => !columnsToExclude.includes(col)); return this.select(columnsToSelect); });
方案二:动态获取表列(适合结构频繁变更的表)
通过查询数据库的系统信息表动态获取列清单,无需手动维护列配置:
// 扩展Knex查询构建器 knex.QueryBuilder.extend('unSelect', async function(...columnsToExclude) { const tableName = this._single.table; // 从系统信息表查询当前表的所有列名 const columnRows = await knex('information_schema.columns') .where('table_name', tableName) .select('column_name'); const allColumnNames = columnRows.map(row => row.column_name); // 过滤掉需要排除的列 const columnsToSelect = allColumnNames.filter(col => !columnsToExclude.includes(col)); return this.select(columnsToSelect); });
使用方式
两种方案都支持你想要的链式调用:
// 使用默认排除列(方案一可用) await db('invoices').unSelect().where('id', 4).first(); // 自定义排除列(两种方案通用) await db('invoices') .unSelect('createdAt', 'updatedAt', 'createdBy', 'updatedBy') .where('id', 4).first();
注意事项
- 方案二需要额外查询系统表,有轻微性能损耗,可结合缓存机制优化(比如缓存表列信息);
- 不同数据库的系统信息表结构略有差异(如MySQL与PostgreSQL),需微调查询语句;
- 若表字段有变更,方案一只需更新
tableConfig中的列清单即可,无需修改业务查询代码。
内容的提问来源于stack exchange,提问作者Pash
相关产品推荐
相关产品推荐

