我正在使用Knexjs和Promise运行多个选择查询。在发送结果之前,我需要所有查询都返回一个值,这已经可以实现。但是我认为代码不是非常优化。
knex(table).select('CRMContactId').where('FCIRecognition', '<', -49.00)
.then(function(results) {
data.largeclawbacks = results.length;
knex(table).select('CRMContactId').where('PlanStatus', 'Out of Force').andWhere(function(){this.whereNot('IncomeType', 'Fund Based Commission').andWhereNot('IncomeType', 'Renewal Commission')})
.then(function(results) {
data.outofforce = results.length;
knex(table).select('CRMContactId').where('GroupOneCaption', 'Tier 2').andWhereNot('Payaways Made/Received', 'Payaway Made')
.andWhere((builder) => builder.whereIn('Plantype', ['Flexible Benefits','General Insurance','Group Critical Illness','Group Death In Service','Group Dental Insurance','Group Healthcare Cash Plan','Group Income Protection','Group Life','Group Life;Group Income Protection','Group PMI','Group Travel Insurance']))
.andWhereNot('Payable', 0)
.then(function(results) {
data.tier2 = results.length;
knex(table).select('CRMContactId').where((builder) => builder.where('GroupOneCaption', 'Tier 3').orWhere('GroupOneCaption', 'Tier 4')).
andWhereNot('Payaways Made/Received', 'Payaway Made')
.andWhere((builder) => builder.whereIn('Plantype', ['Accident Sickness & Unemployment Insurance','AVC','Discretionary Managed Service','Endowment','Enhanced Pension Annuity','Executive Pension Plan','FSAVC','General Investment Account','Income Drawdown','Income Protection','Individual Retirement Account', 'Insurance / Investment Bond','Investment Trust','ISA','Long Term Care','Maximum Investment Plan','Money Purchase Contracted','OEIC / Unit Trust','Offshore Bond','Pension Annuity','Pension Term Assurance','Personal Equity Plan','Personal Pension Plan','Regular Savings Plan','Relevant Life Policy','s226 RAC','s32 Buyout Bond','Savings Account','SIPP','SSAS','Stakeholder Individual','Term Protection','Venture Capital Trust','Whole Of Life','Wrap']))
.andWhereNot('Payable', 0)
.then(function(results) {
data.tier3 = results.length;
knex(table).select('CRMContactId').where('FCIRecognition', '>', 500.00).andWhere('IncomeType', 'Renewal Commission')
.then(function(results) {
data.largerenewal = results.length;
knex.raw(`SELECT ContactName AS Adviser, FORMAT(SUM(Payable),2) AS 'Renewal Income' FROM fci_test WHERE IncomeType IN ("Renewal Commission","Fund Based Commission","Ongoing Fee") AND \`Payaways Made/Received\` != 'Payaway Made' GROUP BY ContactName`)
.then(function(results){
data.renewalincome = results[0];
res.send(data)
})
})
})
})
})
})
我确信有更好的方法对此进行编码并获得相同的结果。
答案 0 :(得分:1)
我首先要关注可读性,然后才是性能。 通过首先使代码更具可读性,可以更容易地看出可以应用哪种优化。
经过一些重构,我们可以得到类似于以下代码:
knex(table).select('CRMContactId')
.where('FCIRecognition', '<', -49.00)
.then(function(results) {
data.largeclawbacks = results.length;
knex(table).select('CRMContactId')
.where('PlanStatus', 'Out of Force')
.andWhere((builder) => {
builder.whereNot('IncomeType', 'Fund Based Commission')
.andWhereNot('IncomeType', 'Renewal Commission');
})
.then(function(results) {
data.outofforce = results.length;
knex(table).select('CRMContactId')
.where('GroupOneCaption', 'Tier 2')
.andWhereNot('Payaways Made/Received', 'Payaway Made')
.whereIn('Plantype', tier2PlanTypes)
.andWhereNot('Payable', 0)
.then(function(results) {
data.tier2 = results.length;
knex(table).select('CRMContactId')
.whereIn('GroupOneCaption', ['Tier 3', 'Tier 4'])
.andWhereNot('Payaways Made/Received', 'Payaway Made')
.whereIn('Plantype', tier3PlanTypes)
.andWhereNot('Payable', 0)
.then(function(results) {
data.tier3 = results.length;
knex(table).select('CRMContactId')
.where('FCIRecognition', '>', 500.00)
.andWhere('IncomeType', 'Renewal Commission')
.then(function(results) {
data.largerenewal = results.length;
knex.raw(`SELECT ContactName AS Adviser, FORMAT(SUM(Payable),2) AS 'Renewal Income' FROM fci_test
WHERE IncomeType IN ("Renewal Commission","Fund Based Commission","Ongoing Fee")
AND \`Payaways Made/Received\` != 'Payaway Made' GROUP BY ContactName`)
.then(function(results){
data.renewalincome = results[0];
res.send(data)
});
})
})
})
})
});
它看起来不多,但是我可以更清楚地看到所有查询都是彼此独立的(我将使用它来进行优化)
之后,进一步进行重构,我将每个查询保存为一个常量,然后使用Promise.all
一次发出所有查询,并完成发送查询的方式。
const largeclawbacksQuery = knex(table).select('CRMContactId')
.where('FCIRecognition', '<', -49.00);
const outofforceQuery = knex(table).select('CRMContactId')
.where('PlanStatus', 'Out of Force')
.andWhere((builder) => {
builder.whereNot('IncomeType', 'Fund Based Commission')
.andWhereNot('IncomeType', 'Renewal Commission')
});
const tier2Query = knex(table).select('CRMContactId')
.where('GroupOneCaption', 'Tier 2')
.andWhereNot('Payaways Made/Received', 'Payaway Made')
.whereIn('Plantype', tier2PlanTypes)
.andWhereNot('Payable', 0);
const tier3Query = knex(table).select('CRMContactId')
.whereIn('GroupOneCaption', ['Tier 3', 'Tier 4'])
.andWhereNot('Payaways Made/Received', 'Payaway Made')
.whereIn('Plantype', tier3PlanTypes)
.andWhereNot('Payable', 0);
const largerenewalQuery = knex(table).select('CRMContactId')
.where('FCIRecognition', '>', 500.00)
.andWhere('IncomeType', 'Renewal Commission');
const renewalincomeQuery = knex.raw(
`SELECT ContactName AS Adviser, FORMAT(SUM(Payable),2) AS 'Renewal Income' FROM fci_test
WHERE IncomeType IN ("Renewal Commission","Fund Based Commission","Ongoing Fee")
AND \`Payaways Made/Received\` != 'Payaway Made' GROUP BY ContactName`
);
Promise.all([largeclawbacksQuery, outofforceQuery, tier2Query, tier3Query, largerenewalQuery, renewalincomeQuery])
.then((result) => {
res.send({
largeclawbacks: result[0].length,
outofforce: result[1].length,
tier2: results[2].length,
tier3: results[3].length,
largerenewal: results[4].length,
renewalincome: results[4][0],
});
});
重要点:
WHERE afield IN avalues AND bfield IN bvalues
的sql 进一步的改进:
tier2Query
和tier3Query
定义基本查询。COUNT
而不是查询所有记录来获取长度值,这将提高性能。答案 1 :(得分:0)
只是盲目地组织您的诺言并正确地将其按链退还,就像这样:
knex(table)
.select('CRMContactId')
.where('FCIRecognition', '<', -49.0)
.then(function(results) {
data.largeclawbacks = results.length;
return knex(table)
.select('CRMContactId')
.where('PlanStatus', 'Out of Force')
.andWhere(function() {
this.whereNot('IncomeType', 'Fund Based Commission').andWhereNot('IncomeType', 'Renewal Commission');
});
})
.then(function(results) {
data.outofforce = results.length;
return knex(table)
.select('CRMContactId')
.where('GroupOneCaption', 'Tier 2')
.andWhereNot('Payaways Made/Received', 'Payaway Made')
.andWhere(builder =>
builder.whereIn('Plantype', [
'Flexible Benefits',
'General Insurance',
'Group Critical Illness',
'Group Death In Service',
'Group Dental Insurance',
'Group Healthcare Cash Plan',
'Group Income Protection',
'Group Life',
'Group Life;Group Income Protection',
'Group PMI',
'Group Travel Insurance'
])
)
.andWhereNot('Payable', 0);
})
.then(function(results) {
data.tier2 = results.length;
return knex(table)
.select('CRMContactId')
.where(builder => builder.where('GroupOneCaption', 'Tier 3').orWhere('GroupOneCaption', 'Tier 4'))
.andWhereNot('Payaways Made/Received', 'Payaway Made')
.andWhere(builder =>
builder.whereIn('Plantype', [
'Accident Sickness & Unemployment Insurance',
'AVC',
'Discretionary Managed Service',
'Endowment',
'Enhanced Pension Annuity',
'Executive Pension Plan',
'FSAVC',
'General Investment Account',
'Income Drawdown',
'Income Protection',
'Individual Retirement Account',
'Insurance / Investment Bond',
'Investment Trust',
'ISA',
'Long Term Care',
'Maximum Investment Plan',
'Money Purchase Contracted',
'OEIC / Unit Trust',
'Offshore Bond',
'Pension Annuity',
'Pension Term Assurance',
'Personal Equity Plan',
'Personal Pension Plan',
'Regular Savings Plan',
'Relevant Life Policy',
's226 RAC',
's32 Buyout Bond',
'Savings Account',
'SIPP',
'SSAS',
'Stakeholder Individual',
'Term Protection',
'Venture Capital Trust',
'Whole Of Life',
'Wrap'
])
)
.andWhereNot('Payable', 0);
})
.then(function(results) {
data.tier3 = results.length;
return knex(table)
.select('CRMContactId')
.where('FCIRecognition', '>', 500.0)
.andWhere('IncomeType', 'Renewal Commission');
})
.then(function(results) {
data.largerenewal = results.length;
return knex.raw(
`SELECT ContactName AS Adviser, FORMAT(SUM(Payable),2) AS 'Renewal Income' FROM fci_test WHERE IncomeType IN ("Renewal Commission","Fund Based Commission","Ongoing Fee") AND \`Payaways Made/Received\` != 'Payaway Made' GROUP BY ContactName`
);
})
.then(function(results) {
data.renewalincome = results[0];
res.send(data);
})
.catch(err => {
// TODO: send error response
});
但是,如果您使用async / await来避免需要用于收集结果的全局data
对象,那么使用您的编码样式会非常有用。