2017-06-15 251 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