在nodejs中执行多个可靠的mysql查询
我正在从事一个项目,在这个项目中,我必须为用户创建团队,但在此之前,我需要检查该团队名称是否已被该用户占用在nodejs中执行多个可靠的mysql查询,mysql,node.js,Mysql,Node.js,我正在从事一个项目,在这个项目中,我必须为用户创建团队,但在此之前,我需要检查该团队名称是否已被该用户占用 var mysql=require('../../config/mysql_connect.js'); var dateFormat = require('dateformat'); var functions={ createTeam:function(data,cb){ this.checkifExists(data,function(err,res
var mysql=require('../../config/mysql_connect.js');
var dateFormat = require('dateformat');
var functions={
createTeam:function(data,cb){
this.checkifExists(data,function(err,result){
if(err)
{
cb(err);
}
else
{
if(result.length)
{
cb(null,0); // Team name exists
}
else
{
mysql.getConnectionFromPool(function(err,con){
if(err)
{
cb(err);
}
else
{
var query=con.query("Insert into team SET ? ",data,function(err,result){
if(err)
{
cb(err);
}
else
{
cb(null,result.insertId);
}
con.release();
});
}
});
}
}
});
},
checkifExists:function(data,cb){
mysql.getConnectionFromPool(function(err,con){
if(err)
{
cb(err);
}
else
{
var sql="Select id from team where user_id = ? and team_name like "+ con.escape('%'+data.team_name+'%') ;
var query=con.query(sql,[data.user_id,data.team_name],function(err,result){
if(err)
{
cb(err);
}
else
{
cb(null,result);
}
con.release();
});
console.log(query.sql);
}
});
}
};
module.exports=functions;
一切正常,但有没有更简单的方法以更易于管理的方式编写这种可靠的查询,因为有时有3-4个以上的查询,代码变得复杂和不可管理
我知道通过mysql unique index也可以实现同样的功能,但是如果有3-4个以上的查询,并且在某些情况下索引不能满足我的需要,那该怎么办呢?正如我所看到的,有两个问题
团队
,第二个连接用于用户
等。要避免回调,请使用async
模块或承诺
这是草稿
// db.js
var mysql=require('../../config/mysql_connect.js');
var connections = {};
// No, that code don't solve problems, because transaction can't started inside other.
// Block mechanism by transaction property `is_busy` seems a bulky.
function DB(name) {
if (!name)
// unnamed connection. Must be released on query end.
return mysql.getConnectionFromPool();
if (!connections[name])
// create always open connection
connections[name] = mysql.getConnectionFromPool();
return connections[name];
}
module.exports = DB;
// team.js
var dateFormat = require('dateformat');
var async = require('async');
var db = require('db')('team'); // get always-open connection for team-entity from pool
function create (data, cb) {
// Here async is not necessary but used as example
async.waterfall([
function(cb) {
isExists(data.user_id, data.team_name, cb);
},
function(isTeamExists, cb) {
if (!isTeamExists)
return cb(); // go to end of waterfall
// is a bad statement; use enum of fields
db.query('insert into team SET ?', data, cb);
}],
// end waterfall chain
function(err, team_id) {
if (err)
return cb(err); // pass error to original cb-func
...do-smth and call cb without error...
}
);
}
function isExists (user_id, team_name, cb) {
// You can use ?? to masked input
db.query('select 1 from team where user_id = ?? and team_name like "%??%"',
[user_id, team_name],
function(err, res) {
cb(err, !err && res.length > 0);
}
);
}
module.exports = {
create,
isExists
};
这是JavaScript的基本问题。多年来,我尝试了许多不同的方法来解决这个问题 在尝试了许多选项之后,我认为最好的方法(目前被广泛接受)是使用
babel
和async/await
关键字。如果使用es2017
预设,这是确保可用的一种方法
现在的免责声明是,你仍然需要学习承诺。如果您试图跳过对async/await
的承诺,您会很快发现一堆基于承诺的代码毫无意义。而且,async/await
需要承诺……所以你需要教会自己这一点。要适应它需要一点时间
另一个对JavaScript有帮助的方法是使用两个空格,而不是四个空格或一个制表符。这确实使您的代码更具可读性。另外,将大括号放在同一行上,不要在任何地方添加额外的空行,只在代码更容易阅读的地方添加空行
因此,这不是确切的代码,而是我将如何做的概述:
async function existsTeam(data) {
const id = await query('select id ..', data);
return id;
}
async function createTeam(data) {
const existingId = await existsTeam(data);
if (existingId) return existingId;
const result = await query('insert into team ..', data);
return result.insertId;
}
对于MySQL的特定情况,您正在尝试强制执行一个约束,我认为MySQL不支持db上的外键约束——但您可能会仔细检查,因为如果它这样做,可能会简化事情。但是,使用Sequelize或Bookshelf Forms,这些类型的查询/更新可能更容易。您的问题令人费解。请澄清。你是指你写的可靠的依赖查询吗?很难从你的代码中分辨出你想做什么。您是否考虑过使用唯一索引来强制执行诸如唯一团队名称之类的事情?我不想在表上添加索引。可靠意味着一个查询的结果将被其他查询使用,等等。在这里,我检查了是否存在唯一的团队名称,以及其他查询是否为true,但在某些情况下,我可能需要发出其他一些查询。这方面的行话是约束。大多数SQL开发人员都使用唯一的索引。显然,您的需求与大多数SQL开发人员的需求不同。您将需要学习如何使用事务。谢谢,伙计,只有一件事是正确的和优化的方法用于此任务,请使用异步或类似q的承诺。如果异步间接使用承诺,那么学习承诺到底是不是更好。为了确保,我们必须小心关键字
async
,因为在您使用它时,并不清楚。它通常可以指异步代码(即节点始终如何工作,异步与同步),或异步模块,或async
和wait
关键字。async
和await
代码(对我来说)显然更干净。性能通常相似。不要建议q
使用本地承诺或bluebird
。我建议学习承诺,然后按照我所展示的那样去做。关于在这种情况下的“优化”。您必须意识到,网络访问数据库的时间可能比任何计算都多100-1000倍你必须仔细阅读。话虽如此,如果您在一个循环中执行这些类型的函数而没有网络开销,那么精确的实现(最终传输输出)和节点/v8引擎版本可以使JIT编译器进行的优化类型发生巨大的变化。这在这种情况下是不相关的——您等待网络,CPU可以忽略不计。