2017-08-16 2 views
0

J'ai un classements et leaderboard_scores tableau.Laravel obtenir la position/rang d'une rangée dans la collection

leaderboard_scores a colonnes: id, leaderboard_id, player_id, score de.

Dans modèle Leaderboard, je défini un hasMany relation avec LeaderboardScore:

public function scores() 
{ 
    return $this->hasMany('App\LeaderboardScore')->orderBy('score', 'desc'); 
} 

Maintenant, je veux obtenir le classement d'un joueur dans un leaderboard particulier.

Donc, dans le contrôleur, je fais une boucle pour trouver la position donnée un player_id:

$score = $leaderboard->scores; 

$scoreCount = $scores->count(); 
$myScore = $scores->where('player_id', $request->query('player_id')); 

if ($myScore) { // If got my score 
    $myRank = 1; 
    for ($i = 0; $i < $scoreCount; $i++) { 
     if ($scores[$i]->player_id == $request->query('player_id')) { 
      $myRank = $i + 1; 
      break; 
     } 
    } 
    // Output or do something with $myRank 
} 

Il fonctionne très bien, mais je suis inquiet au sujet de la performance, quand j'ai cent mille joueurs et ils constamment obtenir leur classement. La boucle for ne semble pas une bonne option.

Dois-je utiliser une requête de base de données brute? Ou une meilleure idée?

Répondre

1

Voici quelques idées

  • Au lieu de calculer les rangs chaque fois que vous obtenez la demande, puis boucle à travers toutes les données. vous pouvez simplement stocker les joueurs dans la base de données ou dans le cache. Vous avez seulement besoin de les calculer quand un nouveau joueur a été ajouté/supprimé ou que le score a changé.

Check Pour Caching: https://laravel.com/docs/5.4/redis

  • si vous voulez toujours calculer chaque fois que vous pouvez utiliser la fonction de rang mysql qui est plus optimisé qu'une boucle primitive

Mysql Rang: http://www.folkstalk.com/2013/03/grouped-rank-function-mysql-sql-query.html