model AdClickEvents { id String @id @map("_id") @default(auto()) @db.ObjectId uid String // 设备码(from JWT / device) adId String @db.ObjectId // 广告 ID adType String // 广告类型 (BANNER/STARTUP/...) clickedAt BigInt // 点击时间 (epoch) ip String // 点击 IP channelId String // 用户自带渠道 Id (required) machine String // 客户端提供 : 设备的信息,品牌及系统版本什么的 (required) createAt BigInt // 记录创建时间 updateAt BigInt // 记录更新时间 // Query helpers // 1. 查某广告的点击列表 @@index([adId, clickedAt]) // 2. 查某设备的点击轨迹 @@index([uid, clickedAt]) // 3. 按渠道+设备分析(报表) @@index([channelId, uid, clickedAt]) // 4. 按广告类型/时间分析 @@index([adType, clickedAt]) // 5. 全局按时间片 @@index([clickedAt]) @@map("adClickEvents") } model VideoClickEvents { id String @id @map("_id") @default(auto()) @db.ObjectId uid String // 设备码 videoId String @db.ObjectId // 视频 ID clickedAt BigInt // 点击时间 (epoch) ip String // 点击 IP channelId String // 用户自带渠道 Id (required) machine String // 客户端提供 : 设备的信息,品牌及系统版本什么的 (required) createAt BigInt // 记录创建时间 updateAt BigInt // 记录更新时间 // Query helpers // 1. 查某视频的点击 @@index([videoId, clickedAt]) // 2. 查设备点击 @@index([uid, clickedAt]) // 3. 按渠道+设备分析(报表) @@index([channelId, uid, clickedAt]) // 4. 全局时间窗口 @@index([clickedAt]) @@map("videoClickEvents") } model AdImpressionEvents { id String @id @map("_id") @default(auto()) @db.ObjectId uid String // 设备码 adId String @db.ObjectId // 广告 ID adType String // 广告类型 (BANNER/STARTUP/...) impressionAt BigInt // 曝光时间 (epoch) visibleDurationMs BigInt? // 可见时长(毫秒,optional) ip String // IP channelId String // 用户自带渠道 Id (required) machine String // 客户端提供 : 设备的信息,品牌及系统版本什么的 (required) createAt BigInt // 记录创建时间 updateAt BigInt // 记录更新时间 // Query helpers // 1. 按广告查看曝光 @@index([adId, impressionAt]) // 2. 设备曝光轨迹 @@index([uid, impressionAt]) // 3. 按渠道+设备分析(报表) @@index([channelId, uid, impressionAt]) // 4. 按广告类型 @@index([adType, impressionAt]) // 5. 时间片 @@index([impressionAt]) @@map("adImpressionEvents") } model ProcessedMessage { id String @id @map("_id") @default(auto()) @db.ObjectId messageId String @unique // 去重用的唯一消息 ID eventType String // 事件类型(如 stats.ad.click) processedAt BigInt // 处理时间(epoch ms) createdAt BigInt // 创建时间(epoch ms) @@map("processedMessages") } model VideoGlobalStats { id String @id @map("_id") @default(auto()) @db.ObjectId videoId String @unique @db.ObjectId // 视频 ID(唯一) impressions BigInt @default(0) // 曝光总数 clicks BigInt @default(0) // 点击总数 firstSeenAt BigInt // 首次出现时间 (epoch) lastSeenAt BigInt // 最后活跃时间 (epoch) computedCtr Float @default(0) // 计算的点击率 (clicks/impressions) computedPopularity Float @default(0) // 计算的热度得分 computedRecency Float @default(0) // 计算的时效性得分 computedScore Float @default(0) // 综合得分 createAt BigInt // 创建时间 (epoch) updateAt BigInt // 更新时间 (epoch) // Query helpers // 1. videoId has unique index via @unique // 2. 按综合得分排序(热门视频推荐) @@index([computedScore]) // 3. 按时效性排序(最新热点) @@index([computedRecency, computedScore]) // 4. 按点击率排序(高转化内容) @@index([computedCtr]) // 5. 按最后活跃时间排序 @@index([lastSeenAt]) @@map("videoGlobalStats") } model AdsGlobalStats { id String @id @map("_id") @default(auto()) @db.ObjectId adId String @unique @db.ObjectId // 广告 ID(唯一) impressions BigInt @default(0) // 曝光总数 clicks BigInt @default(0) // 点击总数 firstSeenAt BigInt // 首次出现时间 (epoch) lastSeenAt BigInt // 最后活跃时间 (epoch) computedCtr Float @default(0) // 计算的点击率 (clicks/impressions) computedPopularity Float @default(0) // 计算的热度得分 computedRecency Float @default(0) // 计算的时效性得分 computedScore Float @default(0) // 综合得分 createAt BigInt // 创建时间 (epoch) updateAt BigInt // 更新时间 (epoch) // Query helpers // 1. adId has unique index via @unique // 2. 按综合得分排序(热门广告推荐) @@index([computedScore]) // 3. 按时效性排序(最新热点) @@index([computedRecency, computedScore]) // 4. 按点击率排序(高转化广告) @@index([computedCtr]) // 5. 按最后活跃时间排序 @@index([lastSeenAt]) @@map("adsGlobalStats") }