Upload beautify
This commit is contained in:
106
app/Console/Commands/AggregateFeedAnalyticsCommand.php
Normal file
106
app/Console/Commands/AggregateFeedAnalyticsCommand.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AggregateFeedAnalyticsCommand extends Command
|
||||
{
|
||||
protected $signature = 'analytics:aggregate-feed {--date= : Date (Y-m-d), defaults to yesterday}';
|
||||
|
||||
protected $description = 'Aggregate feed analytics into daily metrics by algo version and source';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$date = $this->option('date')
|
||||
? (string) $this->option('date')
|
||||
: now()->subDay()->toDateString();
|
||||
|
||||
$rows = DB::table('feed_events')
|
||||
->selectRaw('algo_version, source')
|
||||
->selectRaw("SUM(CASE WHEN event_type = 'feed_impression' THEN 1 ELSE 0 END) AS impressions")
|
||||
->selectRaw("SUM(CASE WHEN event_type = 'feed_click' THEN 1 ELSE 0 END) AS clicks")
|
||||
->selectRaw("SUM(CASE WHEN event_type = 'feed_click' AND dwell_seconds IS NOT NULL AND dwell_seconds < 5 THEN 1 ELSE 0 END) AS dwell_0_5")
|
||||
->selectRaw("SUM(CASE WHEN event_type = 'feed_click' AND dwell_seconds >= 5 AND dwell_seconds < 30 THEN 1 ELSE 0 END) AS dwell_5_30")
|
||||
->selectRaw("SUM(CASE WHEN event_type = 'feed_click' AND dwell_seconds >= 30 AND dwell_seconds < 120 THEN 1 ELSE 0 END) AS dwell_30_120")
|
||||
->selectRaw("SUM(CASE WHEN event_type = 'feed_click' AND dwell_seconds >= 120 THEN 1 ELSE 0 END) AS dwell_120_plus")
|
||||
->whereDate('event_date', $date)
|
||||
->groupBy('algo_version', 'source')
|
||||
->get();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$algoVersion = (string) $row->algo_version;
|
||||
$source = (string) $row->source;
|
||||
$impressions = (int) ($row->impressions ?? 0);
|
||||
$clicks = (int) ($row->clicks ?? 0);
|
||||
|
||||
$saves = $this->countSavesForGroup($date, $algoVersion, $source);
|
||||
|
||||
$ctr = $impressions > 0 ? $clicks / $impressions : 0.0;
|
||||
$saveRate = $clicks > 0 ? $saves / $clicks : 0.0;
|
||||
|
||||
DB::table('feed_daily_metrics')->updateOrInsert(
|
||||
[
|
||||
'metric_date' => $date,
|
||||
'algo_version' => $algoVersion,
|
||||
'source' => $source,
|
||||
],
|
||||
[
|
||||
'impressions' => $impressions,
|
||||
'clicks' => $clicks,
|
||||
'saves' => $saves,
|
||||
'ctr' => $ctr,
|
||||
'save_rate' => $saveRate,
|
||||
'dwell_0_5' => (int) ($row->dwell_0_5 ?? 0),
|
||||
'dwell_5_30' => (int) ($row->dwell_5_30 ?? 0),
|
||||
'dwell_30_120' => (int) ($row->dwell_30_120 ?? 0),
|
||||
'dwell_120_plus' => (int) ($row->dwell_120_plus ?? 0),
|
||||
'updated_at' => now(),
|
||||
'created_at' => now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$this->info("Aggregated feed analytics for {$date}.");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function countSavesForGroup(string $date, string $algoVersion, string $source): int
|
||||
{
|
||||
/** @var Collection<int, object{user_id:int,artwork_id:int}> $clickedPairs */
|
||||
$clickedPairs = DB::table('feed_events')
|
||||
->select('user_id', 'artwork_id')
|
||||
->whereDate('event_date', $date)
|
||||
->where('event_type', 'feed_click')
|
||||
->where('algo_version', $algoVersion)
|
||||
->where('source', $source)
|
||||
->groupBy('user_id', 'artwork_id')
|
||||
->get();
|
||||
|
||||
if ($clickedPairs->isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$saves = 0;
|
||||
foreach ($clickedPairs as $pair) {
|
||||
$hasSave = DB::table('user_discovery_events')
|
||||
->whereDate('event_date', $date)
|
||||
->where('user_id', (int) $pair->user_id)
|
||||
->where('artwork_id', (int) $pair->artwork_id)
|
||||
->where('algo_version', $algoVersion)
|
||||
->whereIn('event_type', ['favorite', 'download'])
|
||||
->exists();
|
||||
|
||||
if ($hasSave) {
|
||||
$saves++;
|
||||
}
|
||||
}
|
||||
|
||||
return $saves;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user