Skip to content

Commit

Permalink
* move all adhoc usages of EntityRepository->createQueryBuilder() i…
Browse files Browse the repository at this point in the history
…nto method of repositories to use DQL

+ abstract `getPosts()` & `isPostExists()` and implements in derived classes
+ `createQueryWithParam()` & `isPostExistsWrapper()`
@ `Post\PostRepository`

+ `getUsers()` @ `UserRepository`
+ `getForum()` @ `ForumRepository`
+ `getLatestRepliersWithoutNameWhenHasUid()` @ `LatestReplierRepository`
@ `App\Repository`
@ be
  • Loading branch information
n0099 committed Oct 10, 2024
1 parent 18f1b9c commit 3f509c7
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 48 deletions.
28 changes: 7 additions & 21 deletions be/src/Controller/PostsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,15 @@ public function query(Request $request): array
$this->stopwatch->stop('fillWithParentPost');

$this->stopwatch->start('queryUsers');
$latestRepliersId = $result['threads']->map(fn(Thread $thread) => $thread->getLatestReplierId());
$latestRepliers = collect()
->concat($this->latestReplierRepository->createQueryBuilder('t')
->where('t.id IN (:ids)')->setParameter('ids', $latestRepliersId)
->andWhere('t.uid IS NOT NULL')
->select('t.id', 't.uid', 't.createdAt', 't.updatedAt') // removeSelect('t.name', 't.displayName')
->getQuery()->getResult())
->concat($this->latestReplierRepository->createQueryBuilder('t')
->where('t.id IN (:ids)')->setParameter('ids', $latestRepliersId)
->andWhere('t.uid IS NULL')
->getQuery()->getResult());
$latestRepliers = $this->latestReplierRepository->getLatestRepliersWithoutNameWhenHasUid(
$result['threads']->map(fn(Thread $thread) => $thread->getLatestReplierId()),
);
$uids = collect($result)
->only(Helper::POST_TYPES_PLURAL)
->flatMap(static fn(Collection $posts) => $posts->map(fn(Post $post) => $post->getAuthorUid()))
->concat($latestRepliers->pluck('uid'))
->filter()->unique(); // remove NULLs
$users = collect($this->userRepository->createQueryBuilder('t')
->where('t.uid IN (:uids)')
->setParameter('uids', $uids)
->getQuery()->getResult());
->concat($latestRepliers->pluck('uid')->filter()) // filter() will remove NULLs
->unique();
$users = collect($this->userRepository->getUsers($uids));
$this->stopwatch->stop('queryUsers');

$this->stopwatch->start('queryUserRelated');
Expand All @@ -127,10 +116,7 @@ public function query(Request $request): array
...$query->getResultPages(),
...Arr::except($result, ['fid', ...Helper::POST_TYPES_PLURAL]),
],
'forum' => $this->forumRepository->createQueryBuilder('t')
->where('t.fid = :fid')->setParameter('fid', $fid)
->select('t.fid', 't.name')->setMaxResults(1)
->getQuery()->getSingleResult(),
'forum' => $this->forumRepository->getForum($fid),
'threads' => $query->reOrderNestedPosts($query->nestPostsWithParent(...$result)),
'users' => $users,
'latestRepliers' => $latestRepliers,
Expand Down
21 changes: 5 additions & 16 deletions be/src/PostsQuery/BaseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,7 @@ static function (string $postIDName) use ($result): array {
/** @var Collection<int, int> $parentThreadsID parent tid of all replies and their sub replies */
$parentThreadsID = $replies->pluck('tid')->concat($subReplies->pluck('tid'))->unique();
/** @var Collection<int, Thread> $threads */
$threads = collect($postModels['thread']->createQueryBuilder('t')
->where('t.tid IN (:tids)')
->setParameter('tids', $parentThreadsID->concat($tids))
->getQuery()->getResult())
$threads = collect($postModels['thread']->getPosts($parentThreadsID->concat($tids)))
->each(static fn(Thread $thread) =>
$thread->setIsMatchQuery($tids->contains($thread->getTid())));
$this->stopwatch->stop('fillWithThreadsFields');
Expand All @@ -191,31 +188,23 @@ static function (string $postIDName) use ($result): array {
/** @var Collection<int, int> $parentRepliesID parent pid of all sub replies */
$parentRepliesID = $subReplies->pluck('pid')->unique();
$allRepliesId = $parentRepliesID->concat($pids);
$replies = collect($postModels['reply']->createQueryBuilder('t')
->where('t.pid IN (:pids)')->setParameter('pids', $allRepliesId)
->getQuery()->getResult())
$replies = collect($postModels['reply']->getPosts($allRepliesId))
->each(static fn(Reply $reply) =>
$reply->setIsMatchQuery($pids->contains($reply->getPid())));
$this->stopwatch->stop('fillWithRepliesFields');

$this->stopwatch->start('fillWithSubRepliesFields');
$subReplies = collect($postModels['subReply']->createQueryBuilder('t')
->where('t.spid IN (:spids)')->setParameter('spids', $spids)
->getQuery()->getResult());
$subReplies = collect($postModels['subReply']->getPosts($spids));
$this->stopwatch->stop('fillWithSubRepliesFields');

$this->stopwatch->start('parsePostContentProtoBufBytes');
// not using one-to-one association due to relying on PostRepository->getTableNameSuffix()
$replyContents = collect($this->postRepositoryFactory->newReplyContent($fid)->createQueryBuilder('t')
->where('t.pid IN (:pids)')->setParameter('pids', $allRepliesId)
->getQuery()->getResult())
$replyContents = collect($this->postRepositoryFactory->newReplyContent($fid)->getPosts($allRepliesId))
->mapWithKeys(fn(ReplyContent $content) => [$content->getPid() => $content->getContent()]);
$replies->each(fn(Reply $reply) =>
$reply->setContent($replyContents->get($reply->getPid())));

$subReplyContents = collect($this->postRepositoryFactory->newSubReplyContent($fid)->createQueryBuilder('t')
->where('t.spid IN (:spids)')->setParameter('spids', $spids)
->getQuery()->getResult())
$subReplyContents = collect($this->postRepositoryFactory->newSubReplyContent($fid)->getPosts($spids))
->mapWithKeys(fn(SubReplyContent $content) => [$content->getSpid() => $content->getContent()]);
$subReplies->each(fn(SubReply $subReply) =>
$subReply->setContent($subReplyContents->get($subReply->getSpid())));
Expand Down
18 changes: 7 additions & 11 deletions be/src/PostsQuery/IndexQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,14 @@ public function query(QueryParams $params, ?string $cursor): void
->only($postTypes)
->transform(static fn(PostRepository $repository) => $repository->selectCurrentAndParentPostID());
$getFidByPostIDParam = function (string $postIDName, int $postID): int {
$counts = collect($this->forumRepository->getOrderedForumsId())
->map(fn(int $fid) => $this->postRepositoryFactory
$postExistencesKeyByFid = collect($this->forumRepository->getOrderedForumsId())
->mapWithKeys(fn(int $fid) => [$fid => $this->postRepositoryFactory
->new($fid, Helper::POST_ID_TO_TYPE[$postIDName])
->createQueryBuilder('t')
->select("$fid AS fid", 'COUNT(t) AS count')
->where("t.$postIDName = :postID")
->setParameter('postID', $postID)
->getQuery()->getSingleResult())
->where('count', '!=', 0);
Helper::abortAPIIf(50001, $counts->count() > 1);
Helper::abortAPIIf(40401, $counts->count() === 0);
return $counts->pluck('fid')->first();
->isPostExists($postID)])
->filter(fn(bool $isExists) => $isExists);
Helper::abortAPIIf(50001, $postExistencesKeyByFid->count() > 1);
Helper::abortAPIIf(40401, $postExistencesKeyByFid->count() === 0);
return $postExistencesKeyByFid->keys()[0];
};

if (\array_key_exists('fid', $flatParams)) {
Expand Down
7 changes: 7 additions & 0 deletions be/src/Repository/ForumRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,11 @@ public function isForumExists(int $fid): bool
->setParameter('fid', $fid)
->getOneOrNullResult(AbstractQuery::HYDRATE_SINGLE_SCALAR) === 1;
}

public function getForum(int $fid): Forum
{
return $this->getEntityManager()
->createQuery(/** @lang DQL */'SELECT t.fid, t.name FROM App\Entity\Forum t WHERE t.fid = :fid')
->setMaxResults(1)->setParameter('fid', $fid)->getSingleResult();
}
}
18 changes: 18 additions & 0 deletions be/src/Repository/LatestReplierRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,29 @@
use App\Entity\LatestReplier;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Illuminate\Support\Collection;

class LatestReplierRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, LatestReplier::class);
}

public function getLatestRepliersWithoutNameWhenHasUid(\ArrayAccess $latestRepliersId): Collection
{
$entityManager = $this->getEntityManager();
return collect($entityManager->createQuery(<<<'DQL'
SELECT t.id, t.uid, t.createdAt, t.updatedAt
FROM App\Entity\LatestReplier t
WHERE t.id IN (:ids) AND t.uid IS NOT NULL
DQL) // removeSelect('t.name', 't.displayName')
->setParameter('ids', $latestRepliersId)->getResult())
->concat(
$entityManager->createQuery(<<<'DQL'
SELECT t FROM App\Entity\LatestReplier t
WHERE t.id IN (:ids) AND t.uid IS NULL
DQL)->setParameter('ids', $latestRepliersId)->getResult(),
);
}
}
9 changes: 9 additions & 0 deletions be/src/Repository/Post/Content/ReplyContentRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,13 @@ protected function getTableNameSuffix(): string
{
return 'reply_content';
}

public function getPosts(\ArrayAccess $postsId): array
{
return $this->createQueryWithParam(
/** @lang DQL */'SELECT t FROM App\Entity\Post\Content\ReplyContent t WHERE t.pid IN (:pid)',
'pid',
$postsId
)->getResult();
}
}
9 changes: 9 additions & 0 deletions be/src/Repository/Post/Content/SubReplyContentRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,13 @@ protected function getTableNameSuffix(): string
{
return 'subReply_content';
}

public function getPosts(\ArrayAccess $postsId): array
{
return $this->createQueryWithParam(
/** @lang DQL */'SELECT t FROM App\Entity\Post\Content\SubReplyContent t WHERE t.spid IN (:spid)',
'spid',
$postsId
)->getResult();
}
}
16 changes: 16 additions & 0 deletions be/src/Repository/Post/PostRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Entity\Post\Post;
use App\Helper;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
Expand Down Expand Up @@ -47,4 +48,19 @@ public function selectCurrentAndParentPostID(): QueryBuilder
->map(static fn(string $postIDField) => "t.$postIDField")
->all());
}

abstract public function getPosts(\ArrayAccess $postsId): array;

protected function createQueryWithParam(string $dql, string $paramName, int|\ArrayAccess $paramValue): AbstractQuery
{
return $this->getEntityManager()->createQuery($dql)->setParameter($paramName, $paramValue);
}

abstract public function isPostExists(int $postId): bool;

protected function isPostExistsWrapper(int $postId, string $dql, string $postIdParamName): bool
{
return $this->createQueryWithParam($dql, $postIdParamName, $postId)
->getOneOrNullResult(AbstractQuery::HYDRATE_SINGLE_SCALAR) === 1;
}
}
18 changes: 18 additions & 0 deletions be/src/Repository/Post/ReplyRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,22 @@ protected function getTableNameSuffix(): string
{
return 'reply';
}

public function getPosts(\ArrayAccess $postsId): array
{
return $this->createQueryWithParam(
/** @lang DQL */'SELECT t FROM App\Entity\Post\Reply t WHERE t.pid IN (:pid)',
'pid',
$postsId
)->getResult();
}

public function isPostExists(int $postId): bool
{
return $this->isPostExistsWrapper(
$postId,
/** @lang DQL */'SELECT 1 FROM App\Entity\Post\Reply t WHERE t.pid = :pid',
'pid'
);
}
}
18 changes: 18 additions & 0 deletions be/src/Repository/Post/SubReplyRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,22 @@ protected function getTableNameSuffix(): string
{
return 'subReply';
}

public function getPosts(\ArrayAccess $postsId): array
{
return $this->createQueryWithParam(
/** @lang DQL */'SELECT t FROM App\Entity\Post\SubReply t WHERE t.spid IN (:spid)',
'spid',
$postsId
)->getResult();
}

public function isPostExists(int $postId): bool
{
return $this->isPostExistsWrapper(
$postId,
/** @lang DQL */'SELECT 1 FROM App\Entity\Post\SubReply t WHERE t.spid = :spid',
'spid'
);
}
}
18 changes: 18 additions & 0 deletions be/src/Repository/Post/ThreadRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ protected function getTableNameSuffix(): string
return 'thread';
}

public function getPosts(\ArrayAccess $postsId): array
{
return $this->createQueryWithParam(
/** @lang DQL */'SELECT t FROM App\Entity\Post\Thread t WHERE t.tid IN (:tid)',
'tid',
$postsId
)->getResult();
}

public function isPostExists(int $postId): bool
{
return $this->isPostExistsWrapper(
$postId,
/** @lang DQL */'SELECT 1 FROM App\Entity\Post\Thread t WHERE t.tid = :tid',
'tid'
);
}

public function getThreadsIdByChunks(int $chunkSize): array
{
// https://github.com/doctrine/orm/issues/3542
Expand Down
7 changes: 7 additions & 0 deletions be/src/Repository/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}

public function getUsers(array $usersId): array
{
return $this->getEntityManager()
->createQuery(/** @lang DQL */'SELECT t FROM App\Entity\User t WHERE t.uid IN (:usersId)')
->setParameter('usersId', $usersId)->getResult();
}
}

0 comments on commit 3f509c7

Please sign in to comment.