Ho un problema nell'ordinare / ordinare i risultati. Fondamentalmente ho messaggi tavolo, e conto popularity_count in base a quanti commenti e piace ha. Il fatto è che impagino anche i risultati. Così quando uso qualcosa come questo
$Posts->paginate(5);
$Posts->sortBy("popularity_count");
$Posts->get();
Ordina solo per pagine specifiche, quindi ad es. la pagina 1 ha risultati con la popolarità che conta: 6,5,4,3,2 e la seconda pagina ha 10,7,5,2,1. Come puoi vedere ci sono post con popolarità 10 e dovrebbe essere il primo risultato sulla prima pagina.
Quando cerco di usare
$Posts->orderBy("popularity_count")
non funziona perché non ho colonne nel mio database come questo. C'è qualche possibilità di ottenere ciò che voglio senza usare i selettori e i join RAW? Ho più attributi personalizzati sul mio modello.
Grazie!
modificare:
`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;
}`
risposte:
1 per risposta № 1Una soluzione rapida (in termini di implementazione) è da utilizzare 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
");
Questo tuttavia sarà molto lento se il tuo posts
il tavolo è enorme Potresti provare a creare una query con due join e due aggregati, ma questo non cambierà molto. Non importa che tu voglia recuperare solo 5 righe - Dovrai calcolare la "popolarità" per ogni post nel DB ogni volta.
Quindi se la prestazione è un problema, puoi creare tre nuove colonne "cache" nel tuo posts
tavolo:
likes_count
comments_count
popularity
con un indice per il popularity
colonna.
Ogni volta che inserisci o cancelli un commento o qualcosa di simile, dovrai anche aggiornare il post correlato. Lo farei probabilmente con i grilletti.
Avendo ciò, puoi semplicemente usarlo orderBy("popularity", "DESC")
.
Puoi anche creare una nuova tabella (post_popularity
) con le colonne post_id, comments_count, likes_count, popularity
per separare fisicamente i dati memorizzati nella cache. Ma allora avresti bisogno di unirti:
$Posts->join("post_popularity as pp", "pp.post.id", "=", "posts.id")
->orderBy(pp.popularity, "DESC");
0 per risposta № 2
Devi ordinare i dati prima di ottenerli:
$Posts->orderBy("popularity_count")->paginate(5);
Quando usi sortBy()
dopo paginate()
, stai solo selezionando una raccolta di 5 elementi.