diff --git a/ghost/core/core/server/services/email-analytics/lib/queries.js b/ghost/core/core/server/services/email-analytics/lib/queries.js index c641496db8a6..fbe2019fdc3a 100644 --- a/ghost/core/core/server/services/email-analytics/lib/queries.js +++ b/ghost/core/core/server/services/email-analytics/lib/queries.js @@ -41,12 +41,14 @@ module.exports = { }, async aggregateEmailStats(emailId) { - const [deliveredCount] = await db.knex('email_recipients').count('id as count').whereRaw('email_id = ? AND delivered_at IS NOT NULL', [emailId]); + const {totalCount} = await db.knex('emails').select(db.knex.raw('email_count as totalCount')).where('id', emailId).first() || {totalCount: 0}; + // use IS NULL here because that will typically match far fewer rows than IS NOT NULL making the query faster + const [undeliveredCount] = await db.knex('email_recipients').count('id as count').whereRaw('email_id = ? AND delivered_at IS NULL', [emailId]); const [openedCount] = await db.knex('email_recipients').count('id as count').whereRaw('email_id = ? AND opened_at IS NOT NULL', [emailId]); const [failedCount] = await db.knex('email_recipients').count('id as count').whereRaw('email_id = ? AND failed_at IS NOT NULL', [emailId]); await db.knex('emails').update({ - delivered_count: deliveredCount.count, + delivered_count: totalCount - undeliveredCount.count, opened_count: openedCount.count, failed_count: failedCount.count }).where('id', emailId); diff --git a/ghost/core/test/e2e-api/admin/__snapshots__/emails.test.js.snap b/ghost/core/test/e2e-api/admin/__snapshots__/emails.test.js.snap index 37f8f6f0aabd..c6f86209e5ad 100644 --- a/ghost/core/test/e2e-api/admin/__snapshots__/emails.test.js.snap +++ b/ghost/core/test/e2e-api/admin/__snapshots__/emails.test.js.snap @@ -491,7 +491,7 @@ Object { Object { "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "delivered_count": 1, - "email_count": 2, + "email_count": 6, "error": null, "error_data": null, "failed_count": 1, @@ -517,7 +517,7 @@ Object { }, Object { "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, - "delivered_count": 0, + "delivered_count": 3, "email_count": 3, "error": "Everything went south", "error_data": null, @@ -690,7 +690,7 @@ Object { Object { "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, "delivered_count": 1, - "email_count": 2, + "email_count": 6, "error": null, "error_data": null, "failed_count": 1, @@ -736,7 +736,7 @@ Object { "emails": Array [ Object { "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, - "delivered_count": 0, + "delivered_count": 3, "email_count": 3, "error": "Everything went south", "error_data": null, diff --git a/ghost/core/test/utils/fixtures/data-generator.js b/ghost/core/test/utils/fixtures/data-generator.js index d671503b014b..be1a079d808d 100644 --- a/ghost/core/test/utils/fixtures/data-generator.js +++ b/ghost/core/test/utils/fixtures/data-generator.js @@ -731,7 +731,7 @@ DataGenerator.Content = { id: ObjectId().toHexString(), uuid: '6b6afda6-4b5e-4893-bff6-f16859e8349a', status: 'submitted', - email_count: 2, + email_count: 6, // match the number of email_recipients relations below recipient_filter: 'all', subject: 'You got mailed!', html: '

Look! I\'m an email

', @@ -745,7 +745,7 @@ DataGenerator.Content = { uuid: '365daa11-4bf0-4614-ad43-6346387ffa00', status: 'failed', error: 'Everything went south', - email_count: 3, + email_count: 3, // doesn't match the number of email_recipients relations below, some calculations may be off subject: 'You got mailed! Again!', html: '

What\'s that? Another email!

', plaintext: 'yes this is an email',