mirror of
https://github.com/shlinkio/shlink.git
synced 2024-12-22 15:13:59 -06:00
Include left join with domains when listing short URLs to avoid N+1 SELECT problem
This commit is contained in:
parent
3149adebdb
commit
84a187a26f
@ -264,7 +264,13 @@ class ShortUrl extends AbstractEntity
|
||||
return true;
|
||||
}
|
||||
|
||||
public function toArray(?VisitsSummary $precalculatedSummary = null): array
|
||||
/**
|
||||
* @param null|(callable(): string|null) $getAuthority -
|
||||
* This is a callback so that we trust its return value if provided, even if it is null.
|
||||
* Providing the raw authority as `string|null` would result in a fallback to `$this->domain` when the authority
|
||||
* was null.
|
||||
*/
|
||||
public function toArray(?VisitsSummary $precalculatedSummary = null, callable|null $getAuthority = null): array
|
||||
{
|
||||
return [
|
||||
'shortCode' => $this->shortCode,
|
||||
@ -276,7 +282,7 @@ class ShortUrl extends AbstractEntity
|
||||
'validUntil' => $this->validUntil?->toAtomString(),
|
||||
'maxVisits' => $this->maxVisits,
|
||||
],
|
||||
'domain' => $this->domain,
|
||||
'domain' => $getAuthority !== null ? $getAuthority() : $this->domain?->authority,
|
||||
'title' => $this->title,
|
||||
'crawlable' => $this->crawlable,
|
||||
'forwardQuery' => $this->forwardQuery,
|
||||
|
@ -9,19 +9,26 @@ use Shlinkio\Shlink\Core\Visit\Model\VisitsSummary;
|
||||
|
||||
final readonly class ShortUrlWithVisitsSummary
|
||||
{
|
||||
private function __construct(public ShortUrl $shortUrl, private ?VisitsSummary $visitsSummary = null)
|
||||
{
|
||||
private function __construct(
|
||||
public ShortUrl $shortUrl,
|
||||
private VisitsSummary|null $visitsSummary = null,
|
||||
private string|null $authority = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{shortUrl: ShortUrl, visits: string|int, nonBotVisits: string|int} $data
|
||||
* @param array{shortUrl: ShortUrl, visits: string|int, nonBotVisits: string|int, authority: string|null} $data
|
||||
*/
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
return new self($data['shortUrl'], VisitsSummary::fromTotalAndNonBots(
|
||||
(int) $data['visits'],
|
||||
(int) $data['nonBotVisits'],
|
||||
));
|
||||
return new self(
|
||||
shortUrl: $data['shortUrl'],
|
||||
visitsSummary: VisitsSummary::fromTotalAndNonBots(
|
||||
total: (int) $data['visits'],
|
||||
nonBots: (int) $data['nonBotVisits'],
|
||||
),
|
||||
authority: $data['authority'] ?? null,
|
||||
);
|
||||
}
|
||||
|
||||
public static function fromShortUrl(ShortUrl $shortUrl): self
|
||||
@ -31,6 +38,6 @@ final readonly class ShortUrlWithVisitsSummary
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->shortUrl->toArray($this->visitsSummary);
|
||||
return $this->shortUrl->toArray($this->visitsSummary, fn() => $this->authority);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class ShortUrlListRepository extends EntitySpecificationRepository implements Sh
|
||||
|
||||
$qb = $this->createListQueryBuilder($filtering);
|
||||
$qb->select(
|
||||
'DISTINCT s AS shortUrl',
|
||||
'DISTINCT s AS shortUrl, d.authority',
|
||||
'(' . $buildVisitsSubQuery('v', excludingBots: false) . ') AS ' . OrderableField::VISITS->value,
|
||||
'(' . $buildVisitsSubQuery('v2', excludingBots: true) . ') AS ' . OrderableField::NON_BOT_VISITS->value,
|
||||
// This is added only to have a consistent order by title between database engines
|
||||
@ -89,6 +89,7 @@ class ShortUrlListRepository extends EntitySpecificationRepository implements Sh
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb->from(ShortUrl::class, 's')
|
||||
->leftJoin('s.domain', 'd')
|
||||
->where('1=1');
|
||||
|
||||
$dateRange = $filtering->dateRange;
|
||||
@ -129,8 +130,7 @@ class ShortUrlListRepository extends EntitySpecificationRepository implements Sh
|
||||
$conditions[] = $qb->expr()->like('t.name', ':searchPattern');
|
||||
}
|
||||
|
||||
$qb->leftJoin('s.domain', 'd')
|
||||
->andWhere($qb->expr()->orX(...$conditions))
|
||||
$qb->andWhere($qb->expr()->orX(...$conditions))
|
||||
->setParameter('searchPattern', '%' . $searchTerm . '%');
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user