У мене є проблема в замовленні / сортування результатів. В основному я пости стіл, і я рахую 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 предметів.