2017-06-15 32 views
2

收集我有下面這段代碼讓所有的評級信息的模型,你可以看到有相當多的查詢事情只是評級信息的可在此功能可以更好地尤其是做對於查詢有效負載,每次請求這些信息時都不會耗盡服務器。laravel查詢這就是被稱爲pior

public function ratingInfo() { 

    $totalCount = $this->ratings()->count(); 
    $one_star = $this->ratings()->where('rating', '>', 0)->where('ratings', '<=', 1); 
    $two_star = $this->ratings()->where('rating', '>', 1)->where('ratings', '<=', 2); 
    $three_star = $this->ratings()->where('rating', '>', 2)->where('ratings', '<=', 3); 
    $four_star = $this->ratings()->where('rating', '>', 3)->where('ratings', '<=', 4); 
    $three_star = $this->ratings()->where('rating', '>', 4)->where('ratings', '<=', 5); 

    return [ 
     'avgRating' => $this->avgRating(), 
     'ratingCount' => $this->ratingCount(), 
     'one_star' => ['count' => $one_star->count(), 'percent' => round(($one_star->count() * $totalCount)/100, 2)], 
     'two_star' => ['count' => $two_star->count(), 'percent' => round(($two_star->count() * $totalCount)/100, 2)], 
     'three_star' => ['count' => $two_star->count(), 'percent' => round(($three_star->count() * $totalCount)/100, 2)], 
     'four_star' => ['count' => $four_star->count(), 'percent' => round(($four_star->count() * $totalCount)/100, 2)], 
     'five_star' => ['count' => $five_star->count(), 'percent' => round(($five_star->count() * $totalCount)/100, 2)], 
    ]; 
} 

我是這樣想的,如果你只有一個查詢就像這樣開始。

$ratings = $this->ratings->all(); 
/* then use $ratings again and again how*/ 
$totalCount = $ratings->count(); 
$one_star = then query the $ratings collection here but how 

評級型號:

class Rating extends Model 
{ 
    protected $table = 'ratings'; 

    protected $fillable = ['rating', 'comment', 'user_id', 'rateable_id', 'rateable_type']; 

    public function rating() 
    { 
     return $this->morphTo(); 
    } 
} 

這就是答案:

public function ratingInfo() { 

    $result = []; 

    $one_star = $this->ratings->filter(function ($item, $key) { 
     return $item->rating > 0 && $item->rating <= 1; 
    }); 

    $two_star = $this->ratings->filter(function ($item, $key) { 
     return $item->rating > 1 && $item->rating <= 2; 
    }); 

    $three_star = $this->ratings->filter(function ($item, $key) { 
     return $item->rating > 2 && $item->rating <= 3; 
    }); 

    $four_star = $this->ratings->filter(function ($item, $key) { 
     return $item->rating > 3 && $item->rating <= 4; 
    }); 

    $five_star = $this->ratings->filter(function ($item, $key) { 
     return $item->rating > 4 && $item->rating <= 5; 
    }); 

    $totalCount = $this->ratings->count(); 
    $avgRating = $this->avgRating(2); 
    $totalRatings = $this->ratings->sum('rating'); 
    //dd('sum: ' . $one_star->sum('rating') . ' count: ' . $one_star->count() . ' percent: ' . round(($one_star->sum('rating')/$this->ratings->sum('rating')) * 100, 2)); 

    return [ 
    'total_count' => $totalCount, 
    'average_rating' => $avgRating, 
    'total_ratings' => $totalRatings, 
     'one_star' => [ 
      'sum' => $one_star->sum('rating'), 
      'count' => $one_star->count(), 
      'percent' => round(($one_star->sum('rating')/$totalRatings) * 100, 2) 
     ], 
     'two_star' => [ 
      'sum' => $two_star->sum('rating'), 
      'count' => $two_star->count(), 
      'percent' => round(($two_star->sum('rating')/$totalRatings) * 100, 2) 
     ], 
     'three_star' => [ 
      'sum' => $three_star->sum('rating'), 
      'count' => $three_star->count(), 
      'percent' => round(($three_star->sum('rating')/$totalRatings) * 100, 2) 
     ], 
     'four_star' => [ 
      'sum' => $four_star->sum('rating'), 
      'count' => $four_star->count(), 
      'percent' => round(($four_star->sum('rating')/$totalRatings) * 100, 2) 
     ], 
     'five_star' => [ 
      'sum' => $five_star->sum('rating'), 
      'count' => $five_star->count(), 
      'percent' => round(($five_star->sum('rating')/$totalRatings) * 100, 2) 
     ] 
    ]; 
} 
+0

我增加了一個possibilty,此時用只是收集操作的收視率 – btl

回答

1

你可以做一個查詢和過濾用PHP結果:相應的計數

$this->whereHas('ratings', function($query) { 
     $query->selectRaw('rating, count(*) as C') 
      ->groupBy('rating') 
      ->orderBy('rating', 'DESC') 
})->get(); 

錯誤這樣做像這樣:

public function ratingInfo() { 

    $all = $this->ratings()->get(); 
    $count = $all->count(); 
    $one_star = $all->filter(function ($item, $key) { 
     return $item->rating === 1; 
    }); 
    $two_star = $all->filter(function ($item, $key) { 
     return $item->rating === 2; 
    }); 
    $three_star = $all->filter(function ($item, $key) { 
     return $item->rating === 3; 
    }); 
    $four_star = $all->filter(function ($item, $key) { 
     return $item->rating === 4; 
    }); 
    $five_star = $all->filter(function ($item, $key) { 
     return $item->rating === 5; 
    }); 

    return [ 
     'avgRating' => $this->avgRating(), 
     'ratingCount' => $this->ratingCount(), 
     'one_star' => ['count' => $one_star->count(), 'percent' => round(($one_star->count() * $totalCount)/100, 2)], 
     'two_star' => ['count' => $two_star->count(), 'percent' => round(($two_star->count() * $totalCount)/100, 2)], 
     'three_star' => ['count' => $two_star->count(), 'percent' => round(($three_star->count() * $totalCount)/100, 2)], 
     'four_star' => ['count' => $four_star->count(), 'percent' => round(($four_star->count() * $totalCount)/100, 2)], 
     'five_star' => ['count' => $five_star->count(), 'percent' => round(($five_star->count() * $totalCount)/100, 2)], 
    ]; 
} 
+0

我得到這個錯誤使用你的例子調用成員函數addEagerConstraints()數組 – ONYX

1

我會嘗試這樣的事:

$this->ratings()->selectRaw('rating, count(*) as C') 
    ->groupBy('rating') 
    ->orderBy('rating', 'DESC'); 

的想法是讓一個計數的每一個評分1 - 5在每一行上都有進一步

$all = $this->ratings()->get(); 

return $all; 

您可以簡化這種通過只是在做

$this->ratings->groupBy('rating')->each(function ($group) { 
    return count($group); 
}); 
+0

我試圖做你的榜樣,但我沒有提到評級()是morphMany關係。我的代碼中出現以下錯誤 - 調用未定義的方法Illuminate \ Database \ Query \ Builder :: ratings() – ONYX

+0

現在嘗試使用多態關係。如果不嘗試只是這個 - $>評級 - > ....沒有() – btl

+0

幾乎沒有,但我現在得到這個錯誤沒有找到列:1054未知列「DESC」「以條款」 – ONYX

0

嘗試構建帶有case表達式的pivoting函數,將您的結果作爲一個查詢執行的一部分,它將優化服務器負載很多,請注意,mysql不具有本機pivoting功能,這就是爲什麼我建議您使用case expression, 然後你必須使用laravel查詢生成器方法.. 下面是一個樣本而已,試圖重寫相應的它並運行它以執行查詢的原始查詢..

select id, 
sum(case when value = 1 then 1 else 0 end) ANSWER1_COUNT, 
sum(case when value = 2 then 1 else 0 end) ANSWER2_COUNT 
from survey 
group by answer