perf: optimize querying post index (#4178)

This commit is contained in:
Sami Mazouz 2025-02-08 18:35:44 +01:00 committed by GitHub
parent 6b31a47f05
commit 55cd0850c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 7 additions and 15 deletions

View File

@ -129,16 +129,16 @@ class PostResource extends AbstractDatabaseResource
$sort = $defaultExtracts['sort']; $sort = $defaultExtracts['sort'];
$filter = $defaultExtracts['filter']; $filter = $defaultExtracts['filter'];
if (count($filter) > 1 || ! isset($filter['discussion']) || $sort) { if (count($filter) > 1 || ! isset($filter['discussion']) || ($sort && $sort !== ['number' => 'asc'])) {
throw new BadRequestException( throw new BadRequestException(
'You can only use page[near] with filter[discussion] and the default sort order' 'You can only use page[near] with filter[discussion] and the default sort order'
); );
} }
$limit = $defaultExtracts['limit']; $limit = $defaultExtracts['limit'];
$offset = $this->posts->getIndexForNumber((int) $filter['discussion'], $near, $context->getActor()); $index = $this->posts->getIndexForNumber((int) $filter['discussion'], $near, $context->getActor());
return max(0, $offset - $limit / 2); return max(0, $index - $limit / 2);
} }
return $defaultExtracts['offset']; return $defaultExtracts['offset'];
@ -150,6 +150,7 @@ class PostResource extends AbstractDatabaseResource
'hiddenUser', 'hiddenUser',
'discussion' 'discussion'
]) ])
->defaultSort('number')
->paginate(static::$defaultLimit), ->paginate(static::$defaultLimit),
]; ];
} }

View File

@ -85,23 +85,14 @@ class PostRepository
*/ */
public function getIndexForNumber(int $discussionId, int $number, ?User $actor = null): int public function getIndexForNumber(int $discussionId, int $number, ?User $actor = null): int
{ {
if (! ($discussion = Discussion::find($discussionId))) { if (! ($discussion = Discussion::query()->find($discussionId))) {
return 0; return 0;
} }
$query = $discussion->posts() $query = $discussion->posts()
->whereVisibleTo($actor) ->whereVisibleTo($actor)
->where('created_at', '<', function ($query) use ($discussionId, $number) { ->where('number', '<=', $number)
$query->select('created_at') ->orderBy('number');
->from('posts')
->where('discussion_id', $discussionId)
->whereNotNull('number')
->take(1)
// We don't add $number as a binding because for some
// reason doing so makes the bindings go out of order.
->orderByRaw('ABS(CAST(number AS SIGNED) - '.(int) $number.')');
});
return $query->count(); return $query->count();
} }