根据 mysql 节点中的第一个结果对表执行查询
Perform query on tables dependent on first result in mysql node
我有一种叫做疫苗的table。对于每种疫苗,都有一定数量的批次和一定数量的病理学,因此我为批次 (VacLots) 创建了一个 table,为病理学 (VacPathologies) 创建了一个 table。
VacLots 和 VacPathologies 都使用疫苗标识符进行索引。
然后,为了创建疫苗,我进行了查询以检索所有疫苗(针对特定国家/地区),并且对于每个标识符,我需要执行两个额外的查询:一个用于识别其批次,另一个用于识别其病理。
代码:
这是用于执行带有指定参数的查询的函数。
executeQueryWithParams(queryToExecute, queryArgs, processRow) {
this.pool.getConnection((err, conn) => {
if (err) {
console.log(`${err} executing the query ${queryToExecute} for database ${this.pool}`);
cb({reason: 'Failed to get connection', err});
} else {
let query = conn.query(queryToExecute, queryArgs, (error, rows) => {
conn.release();
if (error) {
cb({reason: `Failed to execute query ${queryToExecute}`, error});
} else {
cb(null , rows);
}
});
}
这是接收国家 ID 并负责创建疫苗对象的函数。
getVaccinesForCountryID = function (countryID) {
return new Promise((resolve, reject) => {
database.executeQueryWithParams(queries[GET_VACCINE_QUERY_INDEX], [countryID], function(err, rows) {
if (err || rows.length == 0) {
reject(utils.isNullOrUndefined(err) ? new Error('Empty results') : err);
} else {
resolve(processResultRows(rows));
}
});
});
过程结果函数。
function processResultRows(rows) {
const promiseArray = [];
for (const row of rows) {
const vaccine = instantiateVaccine(row);
promiseArray.push(hydrateVaccine(vaccine));
}
return Promise.all(promiseArray);
}
instantiateVaccine 函数除了使用行中已有的一些信息创建疫苗对象外什么都不做。
function hydrateVaccine(vaccine) {
return getLotsForVaccine(vaccine).then(data => getPathologiesForVaccine(data));
}
检索特定疫苗的批次。
function getLotsForVaccine(vaccine) {
return getDetailsVaccine(GET_VACCINE_LOTS_QUERY_INDEX, vaccine, (vac, rows) => {
const lotsArray = [];
for (const row of rows) {
lotsArray.push({lot: row.lot});
}
vac.lots = lotsArray;
});
}
检索特定疫苗的病理。
function getPathologiesForVaccine(vaccine) {
return getDetailsVaccine(GET_VACCINE_PATHOLOGIES_QUERY_INDEX, vaccine, (vac, rows) => {
const pathologiesArray = [];
for (const row of rows) {
pathologiesArray.push({pathology: row.pathology});
}
vac.pathologies = pathologiesArray;
});
}
检索一些详细信息(批次或病理)的通用函数
function getDetailsVaccine(queryIndex, vaccine, hydrateFunction) {
return new Promise((resolve, reject) => {
database.executeQueryWithParams(queries[queryIndex], [vaccine.identifier], (err, rows) => {
if (err) {
reject({error: err, query: queries[queryIndex], identifier: vaccine.identifier});
} else {
hydrateFunction(vaccine, rows);
resolve(vaccine);
}
});
});
如果没有发生很多请求,这一切都很好,但是一旦发生超过 10 个请求(例如使用 ab -k -c 2 -n 10),我就被拒绝连接并且池有一个最大值连接数 1000.
我觉得我混合使用回调和 Promise 可能是个问题,但我目前无法将 executeQueryWithParams 函数作为 Promise 来实现。
编辑:
这是用于创建池的代码(在 executeQueryWithParams 函数中引用为 this.pool)
const pool = mysql.createPool({
connectionLimit : '1000',
host : 'localhost',
user : 'readOnlyUser',
password : 'hRND74SKUjuH4uLU',
database : 'Calendar',
debug : false
});
我会 post 我自己的解决方案,正如@abdulbarik 所指出的那样。
以下列方式实现 executeQueryWithParams 允许用户使用 mysql 池和 Promise,这已经在总共 100000 个连接上使用 500 个并发连接进行了测试,[=15 没有问题=] 错误,如果你想链接,可以用作 Promise。
function executeQueryWithParams(queryToExecute, queryArgs) {
return new Promise((resolve, reject) => {
this.pool.query(queryToExecute, queryArgs, function(err, rows) {
if (err) {
reject({reason: 'Error executing query', err});
} else {
resolve(rows);
}
});
});
}
我有一种叫做疫苗的table。对于每种疫苗,都有一定数量的批次和一定数量的病理学,因此我为批次 (VacLots) 创建了一个 table,为病理学 (VacPathologies) 创建了一个 table。
VacLots 和 VacPathologies 都使用疫苗标识符进行索引。
然后,为了创建疫苗,我进行了查询以检索所有疫苗(针对特定国家/地区),并且对于每个标识符,我需要执行两个额外的查询:一个用于识别其批次,另一个用于识别其病理。
代码: 这是用于执行带有指定参数的查询的函数。
executeQueryWithParams(queryToExecute, queryArgs, processRow) {
this.pool.getConnection((err, conn) => {
if (err) {
console.log(`${err} executing the query ${queryToExecute} for database ${this.pool}`);
cb({reason: 'Failed to get connection', err});
} else {
let query = conn.query(queryToExecute, queryArgs, (error, rows) => {
conn.release();
if (error) {
cb({reason: `Failed to execute query ${queryToExecute}`, error});
} else {
cb(null , rows);
}
});
}
这是接收国家 ID 并负责创建疫苗对象的函数。
getVaccinesForCountryID = function (countryID) {
return new Promise((resolve, reject) => {
database.executeQueryWithParams(queries[GET_VACCINE_QUERY_INDEX], [countryID], function(err, rows) {
if (err || rows.length == 0) {
reject(utils.isNullOrUndefined(err) ? new Error('Empty results') : err);
} else {
resolve(processResultRows(rows));
}
});
});
过程结果函数。
function processResultRows(rows) {
const promiseArray = [];
for (const row of rows) {
const vaccine = instantiateVaccine(row);
promiseArray.push(hydrateVaccine(vaccine));
}
return Promise.all(promiseArray);
}
instantiateVaccine 函数除了使用行中已有的一些信息创建疫苗对象外什么都不做。
function hydrateVaccine(vaccine) {
return getLotsForVaccine(vaccine).then(data => getPathologiesForVaccine(data));
}
检索特定疫苗的批次。
function getLotsForVaccine(vaccine) {
return getDetailsVaccine(GET_VACCINE_LOTS_QUERY_INDEX, vaccine, (vac, rows) => {
const lotsArray = [];
for (const row of rows) {
lotsArray.push({lot: row.lot});
}
vac.lots = lotsArray;
});
}
检索特定疫苗的病理。
function getPathologiesForVaccine(vaccine) {
return getDetailsVaccine(GET_VACCINE_PATHOLOGIES_QUERY_INDEX, vaccine, (vac, rows) => {
const pathologiesArray = [];
for (const row of rows) {
pathologiesArray.push({pathology: row.pathology});
}
vac.pathologies = pathologiesArray;
});
}
检索一些详细信息(批次或病理)的通用函数
function getDetailsVaccine(queryIndex, vaccine, hydrateFunction) {
return new Promise((resolve, reject) => {
database.executeQueryWithParams(queries[queryIndex], [vaccine.identifier], (err, rows) => {
if (err) {
reject({error: err, query: queries[queryIndex], identifier: vaccine.identifier});
} else {
hydrateFunction(vaccine, rows);
resolve(vaccine);
}
});
});
如果没有发生很多请求,这一切都很好,但是一旦发生超过 10 个请求(例如使用 ab -k -c 2 -n 10),我就被拒绝连接并且池有一个最大值连接数 1000.
我觉得我混合使用回调和 Promise 可能是个问题,但我目前无法将 executeQueryWithParams 函数作为 Promise 来实现。
编辑: 这是用于创建池的代码(在 executeQueryWithParams 函数中引用为 this.pool)
const pool = mysql.createPool({
connectionLimit : '1000',
host : 'localhost',
user : 'readOnlyUser',
password : 'hRND74SKUjuH4uLU',
database : 'Calendar',
debug : false
});
我会 post 我自己的解决方案,正如@abdulbarik 所指出的那样。
以下列方式实现 executeQueryWithParams 允许用户使用 mysql 池和 Promise,这已经在总共 100000 个连接上使用 500 个并发连接进行了测试,[=15 没有问题=] 错误,如果你想链接,可以用作 Promise。
function executeQueryWithParams(queryToExecute, queryArgs) {
return new Promise((resolve, reject) => {
this.pool.query(queryToExecute, queryArgs, function(err, rows) {
if (err) {
reject({reason: 'Error executing query', err});
} else {
resolve(rows);
}
});
});
}