use only one query to get the open creations

This commit is contained in:
Moriz Wahl 2022-02-22 13:25:26 +01:00
parent 7be2fb68b4
commit 2bdcea15f0

View File

@ -40,9 +40,7 @@ export class AdminResolver {
if (notActivated) { if (notActivated) {
filterCriteria.push({ emailChecked: false }) filterCriteria.push({ emailChecked: false })
} }
// prevent overfetching data from db, select only needed columns
// prevent reading and transmitting data from db at least 300 Bytes
// one of my example dataset shrink down from 342 Bytes to 42 Bytes, that's ~88% saved db bandwith
const userFields = ['id', 'firstName', 'lastName', 'email', 'emailChecked'] const userFields = ['id', 'firstName', 'lastName', 'email', 'emailChecked']
const [users, count] = await userRepository.findBySearchCriteriaPagedFiltered( const [users, count] = await userRepository.findBySearchCriteriaPagedFiltered(
userFields.map((fieldName) => { userFields.map((fieldName) => {
@ -54,6 +52,8 @@ export class AdminResolver {
pageSize, pageSize,
) )
const creations = await getUserCreations(users.map((u) => u.id))
const adminUsers = await Promise.all( const adminUsers = await Promise.all(
users.map(async (user) => { users.map(async (user) => {
const adminUser = new UserAdmin() const adminUser = new UserAdmin()
@ -61,7 +61,8 @@ export class AdminResolver {
adminUser.firstName = user.firstName adminUser.firstName = user.firstName
adminUser.lastName = user.lastName adminUser.lastName = user.lastName
adminUser.email = user.email adminUser.email = user.email
adminUser.creation = await getUserCreations(user.id) const userCreations = creations.find((c) => c.id === user.id)
adminUser.creation = userCreations ? userCreations.creations : [1000, 1000, 1000]
adminUser.emailChecked = user.emailChecked adminUser.emailChecked = user.emailChecked
adminUser.hasElopage = await hasElopageBuys(user.email) adminUser.hasElopage = await hasElopageBuys(user.email)
if (!user.emailChecked) { if (!user.emailChecked) {
@ -109,7 +110,7 @@ export class AdminResolver {
if (!user.emailChecked) { if (!user.emailChecked) {
throw new Error('Creation could not be saved, Email is not activated') throw new Error('Creation could not be saved, Email is not activated')
} }
const creations = await getUserCreations(user.id) const creations = await getUserCreation(user.id)
const creationDateObj = new Date(creationDate) const creationDateObj = new Date(creationDate)
if (isCreationValid(creations, amount, creationDateObj)) { if (isCreationValid(creations, amount, creationDateObj)) {
const adminPendingCreation = AdminPendingCreation.create() const adminPendingCreation = AdminPendingCreation.create()
@ -122,7 +123,7 @@ export class AdminResolver {
await AdminPendingCreation.save(adminPendingCreation) await AdminPendingCreation.save(adminPendingCreation)
} }
return getUserCreations(user.id) return getUserCreation(user.id)
} }
@Authorized([RIGHTS.CREATE_PENDING_CREATION]) @Authorized([RIGHTS.CREATE_PENDING_CREATION])
@ -171,7 +172,7 @@ export class AdminResolver {
} }
const creationDateObj = new Date(creationDate) const creationDateObj = new Date(creationDate)
let creations = await getUserCreations(user.id) let creations = await getUserCreation(user.id)
if (pendingCreationToUpdate.date.getMonth() === creationDateObj.getMonth()) { if (pendingCreationToUpdate.date.getMonth() === creationDateObj.getMonth()) {
creations = updateCreations(creations, pendingCreationToUpdate) creations = updateCreations(creations, pendingCreationToUpdate)
} }
@ -190,7 +191,8 @@ export class AdminResolver {
result.memo = pendingCreationToUpdate.memo result.memo = pendingCreationToUpdate.memo
result.date = pendingCreationToUpdate.date result.date = pendingCreationToUpdate.date
result.moderator = pendingCreationToUpdate.moderator result.moderator = pendingCreationToUpdate.moderator
result.creation = await getUserCreations(user.id)
result.creation = await getUserCreation(user.id)
return result return result
} }
@ -213,7 +215,7 @@ export class AdminResolver {
firstName: user.firstName, firstName: user.firstName,
lastName: user.lastName, lastName: user.lastName,
email: user.email, email: user.email,
creation: await getUserCreations(user.id), creation: await getUserCreation(user.id),
} }
return newPendingCreation return newPendingCreation
@ -292,7 +294,17 @@ export class AdminResolver {
} }
} }
async function getUserCreations(id: number): Promise<number[]> { interface CreationMap {
id: number
creations: number[]
}
async function getUserCreation(id: number): Promise<number[]> {
const creations = await getUserCreations([id])
return creations[0] ? creations[0].creations : [1000, 1000, 1000]
}
async function getUserCreations(ids: number[]): Promise<CreationMap[]> {
const now = new Date(Date.now()) const now = new Date(Date.now())
const months = [ const months = [
now.getMonth() + 1, now.getMonth() + 1,
@ -304,23 +316,30 @@ async function getUserCreations(id: number): Promise<number[]> {
await queryRunner.connect() await queryRunner.connect()
const unionQuery = await queryRunner.manager.query(` const unionQuery = await queryRunner.manager.query(`
SELECT MONTH(date) AS month, sum(amount) AS sum FROM SELECT MONTH(date) AS month, sum(amount) AS sum, userId AS id FROM
(SELECT creation_date AS date, amount AS amount FROM transactions (SELECT creation_date AS date, amount AS amount, user_id AS userId FROM transactions
WHERE user_id = ${id} AND transaction_type_id = 1 WHERE user_id IN (${ids.toString()}) AND transaction_type_id = 1
AND creation_date >= last_day(curdate() - interval 3 month) + interval 1 day AND creation_date >= last_day(curdate() - interval 3 month) + interval 1 day
UNION UNION
SELECT date AS date, amount AS amount FROM admin_pending_creations SELECT date AS date, amount AS amount, userId AS userId FROM admin_pending_creations
WHERE userId = ${id} WHERE userId IN (${ids.toString()})
AND date >= last_day(curdate() - interval 3 month) + interval 1 day) AS result AND date >= last_day(curdate() - interval 3 month) + interval 1 day) AS result
GROUP BY month GROUP BY month, userId
ORDER BY date DESC ORDER BY date DESC
`) `)
await queryRunner.release() await queryRunner.release()
return months.map((month) => { return ids.map((id) => {
const creation = unionQuery.find((raw: any) => parseInt(raw.month) === month) return {
return 1000 - (creation ? Number(creation.sum) / 10000 : 0) id,
creations: months.map((month) => {
const creation = unionQuery.find(
(raw: any) => parseInt(raw.month) === month && parseInt(raw.id) === id,
)
return 1000 - (creation ? Number(creation.sum) / 10000 : 0)
}),
}
}) })
} }