2017-08-16 19 views
0

私はリーダーボードleaderboard_scoresテーブルを持っています。 ID leaderboard_id、player_idスコア:Laravelコレクションの行の位置/順位を取得

leaderboard_scores列を有しています。

リーダーモデルでは、私はLeaderboardScorehasManyのの関係を定義した:

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

今、私は特定のリーダーボードでプレーヤーのランキングを取得したいです。

だからコントローラで、私は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 
} 

が、私は選手たちと彼らの10万を持っているとき、私は、パフォーマンスが心配です絶えず彼らのランキングを得ている。 forループは良い選択肢ではないようです。

生データベースクエリを使用する必要がありますか?それとも良いアイデアですか?ここで

答えて

1

その後、いくつかのアイデア

  • 代わりのランクにあなたが要求を取得するたびに計算すると、すべてのデータをループ。プレイヤーをデータベースまたはキャッシュのいずれかに格付けすることができます。新しいプレイヤーが追加/削除されたとき、またはスコアが変更されたときに計算する必要があります。キャッシングに

チェック:http://www.folkstalk.com/2013/03/grouped-rank-function-mysql-sql-query.htmlhttps://laravel.com/docs/5.4/redis

  • それでも毎回それを計算したい場合は、より原始的なループ

Mysqlのランクよりも最適化されたMySQLのランク機能を使用することができます