/ / Laravel - Атрибут PopularityCount - Порядок порядку - laravel, красномовний

Laravel - Атрибут PopularityCount - Порядок замовлення - laravel, красномовний

У мене є проблема в замовленні / сортування результатів. В основному я пости стіл, і я рахую popular_count виходячи з того, скільки коментарів і подобається їм. Вся справа в тому, що я також болю на результати. Так коли я використовую щось подібне

$Posts->paginate(5);
$Posts->sortBy("popularity_count");
$Posts->get();

Це сортування лише для певної сторінки, наприклад, сторінка 1 має результати з кількістю популярності: 6,5,4,3,2, а на другій сторінці 10,7,5,2,1. Як бачите, там є популярні пости 10 і це має бути як перший результат на першій сторінці.

Коли я намагаюся використовувати

 $Posts->orderBy("popularity_count")

у моїй базі даних не працює так, як я. Чи є можливість досягти того, що я хочу без використання RAW вибору та приєднання? У моїй моделі є більше спеціальних атрибутів.

Дякую!

редагувати:

`public function getPopularityCountAttribute(){

$comments = $this->getRelation("commentsCount");

$likes = $this->getRelation("likesCount");


$comments = ($comments) ? (int) $comments->comments_count : 0;

$likes = ($likes) ? (int) $likes->likes_count : 0;

$Result = $likes + ( $comments * 1.2 );

return $Result;
}`

Відповіді:

1 для відповіді № 1

Швидке рішення (з точки зору реалізації) - використовувати oderByRaw():

$Posts->orderByRaw("
(
select count(*)
from likes
where likes.post_id = posts.id
) + (
select count(*)
from comments
where comments.post_id = posts.id
) * 1.2 DESC
");

Однак це буде дуже повільно, якщо ваш posts стіл величезний. Ви можете спробувати створити запит з двома об'єднаннями та двома агрегатами, але це не зміниться сильно. Не має значення, що ви хочете отримати лише 5 рядків - вам потрібно буде щоразу обчислювати "популярність" для кожної публікації в БД.

Тож якщо продуктивність не викликає труднощів, ви можете створити три нові стовпці "кеша" у вашому posts таблиця:

  • likes_count
  • comments_count
  • popularity

з індексом для popularity колонка

Щоразу, коли ви вставляєте чи видаляєте коментар чи подібний, вам також потрібно буде оновлювати відповідну публікацію. Я, мабуть, зробив би це за допомогою тригерів.

Маючи це, ви можете просто використовувати orderBy("popularity", "DESC").

Ви також можете створити нову таблицю (post_popularity) зі стовпцями post_id, comments_count, likes_count, popularity щоб фізологічно розділити кешовані дані. Але тоді вам знадобиться приєднання:

$Posts->join("post_popularity as pp", "pp.post.id", "=", "posts.id")
->orderBy(pp.popularity, "DESC");

0 для відповіді № 2

Ви повинні сортувати дані, перш ніж їх отримувати:

$Posts->orderBy("popularity_count")->paginate(5);

Коли ви використовуєте sortBy() після paginate(), ви лише сортуєте колекцію з 5 предметів.