Merge pull request #1472 from gradido/admin_user_search_optimization

Admin: Langsame Benutzer-Suche
This commit is contained in:
einhornimmond 2022-02-21 19:33:22 +01:00 committed by GitHub
commit dea26287ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 17 deletions

View File

@ -2,7 +2,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Resolver, Query, Arg, Args, Authorized, Mutation, Ctx } from 'type-graphql' import { Resolver, Query, Arg, Args, Authorized, Mutation, Ctx } from 'type-graphql'
import { getCustomRepository, Raw } from '@dbTools/typeorm' import { getCustomRepository, ObjectLiteral, Raw } from '@dbTools/typeorm'
import { UserAdmin, SearchUsersResult } from '../model/UserAdmin' import { UserAdmin, SearchUsersResult } from '../model/UserAdmin'
import { PendingCreation } from '../model/PendingCreation' import { PendingCreation } from '../model/PendingCreation'
import { CreatePendingCreations } from '../model/CreatePendingCreations' import { CreatePendingCreations } from '../model/CreatePendingCreations'
@ -35,8 +35,26 @@ export class AdminResolver {
@Args() { searchText, currentPage = 1, pageSize = 25, notActivated = false }: SearchUsersArgs, @Args() { searchText, currentPage = 1, pageSize = 25, notActivated = false }: SearchUsersArgs,
): Promise<SearchUsersResult> { ): Promise<SearchUsersResult> {
const userRepository = getCustomRepository(UserRepository) const userRepository = getCustomRepository(UserRepository)
const users = await userRepository.findBySearchCriteria(searchText)
let adminUsers = await Promise.all( const filterCriteria: ObjectLiteral[] = []
if (notActivated) {
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 [users, count] = await userRepository.findBySearchCriteriaPagedFiltered(
userFields.map((fieldName) => {
return 'user.' + fieldName
}),
searchText,
filterCriteria,
currentPage,
pageSize,
)
const adminUsers = await Promise.all(
users.map(async (user) => { users.map(async (user) => {
const adminUser = new UserAdmin() const adminUser = new UserAdmin()
adminUser.userId = user.id adminUser.userId = user.id
@ -56,6 +74,7 @@ export class AdminResolver {
updatedAt: 'DESC', updatedAt: 'DESC',
createdAt: 'DESC', createdAt: 'DESC',
}, },
select: ['updatedAt', 'createdAt'],
}, },
) )
if (emailOptIn) { if (emailOptIn) {
@ -69,11 +88,9 @@ export class AdminResolver {
return adminUser return adminUser
}), }),
) )
if (notActivated) adminUsers = adminUsers.filter((u) => !u.emailChecked)
const first = (currentPage - 1) * pageSize
return { return {
userCount: adminUsers.length, userCount: count,
userList: adminUsers.slice(first, first + pageSize), userList: adminUsers,
} }
} }

View File

@ -1,4 +1,4 @@
import { EntityRepository, Repository } from '@dbTools/typeorm' import { Brackets, EntityRepository, ObjectLiteral, Repository } from '@dbTools/typeorm'
import { User } from '@entity/User' import { User } from '@entity/User'
@EntityRepository(User) @EntityRepository(User)
@ -17,10 +17,19 @@ export class UserRepository extends Repository<User> {
.getMany() .getMany()
} }
async findBySearchCriteria(searchCriteria: string): Promise<User[]> { async findBySearchCriteriaPagedFiltered(
return this.createQueryBuilder('user') select: string[],
searchCriteria: string,
filterCriteria: ObjectLiteral[],
currentPage: number,
pageSize: number,
): Promise<[User[], number]> {
return await this.createQueryBuilder('user')
.select(select)
.withDeleted() .withDeleted()
.where( .where(
new Brackets((qb) => {
qb.where(
'user.firstName like :name or user.lastName like :lastName or user.email like :email', 'user.firstName like :name or user.lastName like :lastName or user.email like :email',
{ {
name: `%${searchCriteria}%`, name: `%${searchCriteria}%`,
@ -28,6 +37,11 @@ export class UserRepository extends Repository<User> {
email: `%${searchCriteria}%`, email: `%${searchCriteria}%`,
}, },
) )
.getMany() }),
)
.andWhere(filterCriteria)
.take(pageSize)
.skip((currentPage - 1) * pageSize)
.getManyAndCount()
} }
} }