Laravel Eloquent按时间范围统计文件下载次数方案问询
统计下载记录的时段下载次数
我有一张用于记录下载信息的Download表,数据库中的每条记录代表一次下载,表结构如下:
id file_id created_at updated_at
我已在File与Download模型间建立关联,可通过以下方式获取文件对应的下载记录:
$file->downloads // 返回结果: Illuminate\Database\Eloquent\Collection {#4585 all: [ App\Models\Download {#4587 id: 12, file_id: 2, created_at: "2022-09-02 12:05:12", updated_at: "2022-09-02 12:05:12", }, App\Models\Download {#4597 id: 13, file_id: 1, created_at: "2022-09-03 12:05:14", updated_at: "2022-09-03 12:05:14", }, App\Models\Download {#4598 id: 14, file_id: 1, created_at: "2022-09-03 12:08:33", updated_at: "2022-09-03 12:08:33", }, ], }
我现在需要选择一个时间范围(日、周或月),统计该范围内各时段的下载次数。以按日统计为例,期望得到如下格式的结果:
[ '2022-09-02' => 1, '2022-09-03' => 2, ]
我能想到几种实现方法但都不够理想,问题不在于日期比较,而在于如何统计次数,希望得到简洁的解决方案。
更新:
根据提示我使用了groupBy方法,代码如下:
$grouped = $file->downloads->groupBy(function ($item, $key) { return $item->created_at->format('Y M d'); }); // 返回结果: Illuminate\Database\Eloquent\Collection {#4648 all: [ "2022 Sep 02" => Illuminate\Database\Eloquent\Collection {#4651 all: [ App\Models\Download {#4625 id: 12, file_id: 2, created_at: "2022-09-02 12:05:12", updated_at: "2022-09-02 12:05:12", }, ], }, "2022 Sep 03" => Illuminate\Database\Eloquent\Collection {#4649 all: [ App\Models\Download {#4598 id: 13, file_id: 1, created_at: "2022-09-03 12:05:14", updated_at: "2022-09-03 12:05:14", }, App\Models\Download {#4630 id: 14, file_id: 1, created_at: "2022-09-03 12:08:33", updated_at: "2022-09-03 12:08:33", }, ], }, ], }
这已经接近目标,但还不是我想要的格式:
[ '2022-09-02' => 1, '2022-09-03' => 2, ]
解决方案
你只需要调整日期格式,并将分组后的集合转为对应数量即可:
$downloadStats = $file->downloads->groupBy(function ($item) { // 调整日期格式为你需要的Y-m-d return $item->created_at->format('Y-m-d'); })->map(function ($group) { // 将每个分组的集合转为数量 return $group->count(); })->toArray();
执行后就能得到你期望的键为日期字符串、值为对应下载次数的数组。
如果需要支持按周或月统计,只需修改format的参数:
- 按周统计:可使用
'Y-W'(年份+周数),或取每周第一天格式化为Y-m-d:$item->created_at->startOfWeek()->format('Y-m-d') - 按月统计:使用
'Y-m'(年份+月份)
更高效的数据库层面统计方案
如果数据量较大,建议直接在数据库完成分组统计,避免加载所有模型实例:
// 按日统计(MySQL) $downloadStats = $file->downloads() ->selectRaw('DATE(created_at) as date, COUNT(*) as count') ->groupBy('date') ->pluck('count', 'date') ->toArray(); // 按周统计(MySQL) $downloadStats = $file->downloads() ->selectRaw('YEARWEEK(created_at) as week, COUNT(*) as count') ->groupBy('week') ->pluck('count', 'week') ->toArray(); // 按月统计(MySQL) $downloadStats = $file->downloads() ->selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month, COUNT(*) as count') ->groupBy('month') ->pluck('count', 'month') ->toArray();
这种方式性能更优,返回结果同样是符合需求的键值对数组。
内容的提问来源于stack exchange,提问作者Brainmaniac
相关产品推荐
相关产品推荐

