/ / Laravel - Attributo PopularityCount - Ordina per - laravel, eloquente

Laravel - Attributo PopularityCount - Ordina per - laravel, eloquente

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 № 1

Una 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.