由于内联mysql查询,我们面临代码质量问题.使用自编写的mysql查询会使代码混乱并增加代码库等.
我们的代码杂乱无章
/* beautify ignore:start */
/* jshint ignore:start */
var sql = "SELECT *"
+" ,DATE_ADD(sc.created_at,INTERVAL 14 DAY) AS duedate"
+" ,distance_mail(?,?,lat,lon) as distance,count(pks.skill_id) c1"
+" ,count(ps.profile_id) c2"
+" FROM TABLE sc"
+" JOIN "
+" PACKAGE_V psc on sc.id = psc.s_id "
+" JOIN "
+" PACKAGE_SKILL pks on pks.package_id = psc.package_id "
+" LEFT JOIN PROFILE_SKILL ps on ps.skill_id = pks.skill_id and ps.profile_id = ?"
+" WHERE sc.type in "
+" ('a',"
+" 'b',"
+" 'c' ,"
+" 'd',"
+" 'e',"
+" 'f',"
+" 'g',"
+" 'h')"
+" AND sc.status = 'open'"
+" AND sc.crowd_type = ?"
+" AND sc.created_at < DATE_SUB(NOW(),INTERVAL 10 MINUTE) "
+" AND sc.created_at > DATE_SUB(NOW(),INTERVAL 14 DAY)"
+" AND distance_mail(?, ?,lat,lon) < 500"
+" GROUP BY sc.id"
+" HAVING c1 = c2 "
+" ORDER BY distance;";
/* jshint ignore:end */
/* beautify ignore:end */
Run Code Online (Sandbox Code Playgroud)
我不得不模糊一点代码.
正如您所看到的,在您的代码中重复使用它是不可读的.另外因为atm我们不能去ES6,由于多行字符串,这至少会使字符串变得漂亮.
现在的问题是,有没有办法将SQL程序存储在一个地方?作为附加信息,我们使用node(~0.12)和express来公开API,访问MySQL数据库.
我已经考虑过,使用JSON,这将导致更大的混乱.另外,它甚至可能是不可能的,因为JSON的字符集有点严格,JSON可能也不喜欢有多行字符串.
然后我想出了将SQL存储在文件中并在启动节点应用程序时加载的想法.现在,这是我在一个地方获取SQL查询并将其提供给其余节点模块的最好机会.这里的问题是,使用ONE文件?每个查询使用一个文件?每个数据库表使用一个文件?
任何帮助表示赞赏,我不能成为地球上第一个解决这个问题的人,所以也许有人有一个有效的解决方案!
PS:我尝试使用像squel这样的库,但这并没有什么帮助,因为我们的查询很复杂,你可以看到.它主要是将我们的查询转换为"查询中心".
Joh*_*erz 11
我更喜欢将每个更大的查询放在一个文件中.这样,您可以使用语法突出显示,并且可以在服务器启动时轻松加载.为了构建这个,我通常有一个文件夹用于所有查询,并在每个模型的一个文件夹内.
# queries/mymodel/select.mymodel.sql
SELECT * FROM mymodel;
// in mymodel.js
const fs = require('fs');
const queries = {
select: fs.readFileSync(__dirname + '/queries/mymodel/select.mymodel.sql', 'utf8')
};
Run Code Online (Sandbox Code Playgroud)
小智 5
在需要时,将查询放入数据库过程并在代码中调用过程.
create procedure sp_query()
select * from table1;
Run Code Online (Sandbox Code Playgroud)
我建议您将查询存储在.sql远离js代码的文件中.这将分离关注点,使代码和查询更具可读性.根据您的业务,您应该具有嵌套结构的不同目录.
例如:
queries
??? global.sql
??? products
? ??? select.sql
??? users
??? select.sql
Run Code Online (Sandbox Code Playgroud)
现在,您只需要在应用程序启动时需要所有这些文件.您可以手动执行也可以使用某些逻辑.下面的代码将读取所有文件(同步)并生成与上述文件夹具有相同层次结构的对象
var glob = require('glob')
var _ = require('lodash')
var fs = require('fs')
// directory containing all queries (in nested folders)
var queriesDirectory = 'queries'
// get all sql files in dir and sub dirs
var files = glob.sync(queriesDirectory + '/**/*.sql', {})
// create object to store all queries
var queries = {}
_.each(files, function(file){
// 1. read file text
var queryText = fs.readFileSync(__dirname + '/' + file, 'utf8')
// 2. store into object
// create regex for directory name
var directoryNameReg = new RegExp("^" + queriesDirectory + "/")
// get the property path to set in the final object, eg: model.queryName
var queryPath = file
// remove directory name
.replace(directoryNameReg,'')
// remove extension
.replace(/\.sql/,'')
// replace '/' with '.'
.replace(/\//g, '.')
// use lodash to set the nested properties
_.set(queries, queryPath, queryText)
})
// final object with all queries according to nested folder structure
console.log(queries)
Run Code Online (Sandbox Code Playgroud)
日志输出
{
global: '-- global query if needed\n',
products: {
select: 'select * from products\n'
},
users: {
select: 'select * from users\n'
}
}
Run Code Online (Sandbox Code Playgroud)
所以你可以访问这样的所有查询 queries.users.select