存储SQL命令以供执行的位置

m4m*_*bax 10 mysql node.js

由于内联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)


Gaa*_*far 5

我建议您将查询存储在.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